platform: introduce hardware platform abstraction
These objects describes the hardware an image runs on. Including - architecture - bootloader - required firmware Use the platform abstraction to move firmware packages out of the package set definitions.
This commit is contained in:
parent
682481d4d7
commit
ec8cc01f95
9 changed files with 227 additions and 141 deletions
|
|
@ -2,6 +2,7 @@ package main
|
|||
|
||||
import (
|
||||
"github.com/osbuild/osbuild-composer/internal/manifest"
|
||||
"github.com/osbuild/osbuild-composer/internal/platform"
|
||||
"github.com/osbuild/osbuild-composer/internal/rpmmd"
|
||||
)
|
||||
|
||||
|
|
@ -31,7 +32,7 @@ func MyManifest(m *manifest.Manifest, options *MyOptions, repos []rpmmd.RepoConf
|
|||
build := manifest.NewBuildPipeline(m, runner, repos)
|
||||
|
||||
// create a non-bootable OS tree containing the `core` comps group
|
||||
os := manifest.NewOSPipeline(m, build, manifest.ARCH_X86_64, repos)
|
||||
os := manifest.NewOSPipeline(m, build, &platform.X86{}, repos)
|
||||
os.ExtraBasePackages = []string{
|
||||
"@core",
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import (
|
|||
"github.com/osbuild/osbuild-composer/internal/disk"
|
||||
"github.com/osbuild/osbuild-composer/internal/distro"
|
||||
"github.com/osbuild/osbuild-composer/internal/manifest"
|
||||
"github.com/osbuild/osbuild-composer/internal/platform"
|
||||
"github.com/osbuild/osbuild-composer/internal/rpmmd"
|
||||
)
|
||||
|
||||
|
|
@ -273,7 +274,6 @@ var (
|
|||
defaultImageConfig: defaultEc2ImageConfig,
|
||||
kernelOptions: defaultKernelOptions,
|
||||
bootable: true,
|
||||
bootType: distro.LegacyBootType,
|
||||
defaultSize: 6 * GigaByte,
|
||||
manifest: ec2Manifest,
|
||||
buildPipelines: []string{"build"},
|
||||
|
|
@ -421,8 +421,6 @@ type architecture struct {
|
|||
name string
|
||||
imageTypes map[string]distro.ImageType
|
||||
imageTypeAliases map[string]string
|
||||
legacy string
|
||||
bootType distro.BootType
|
||||
}
|
||||
|
||||
func (a *architecture) Name() string {
|
||||
|
|
@ -453,13 +451,14 @@ func (a *architecture) GetImageType(name string) (distro.ImageType, error) {
|
|||
return t, nil
|
||||
}
|
||||
|
||||
func (a *architecture) addImageTypes(imageTypes ...imageType) {
|
||||
func (a *architecture) addImageTypes(platform platform.Platform, imageTypes ...imageType) {
|
||||
if a.imageTypes == nil {
|
||||
a.imageTypes = map[string]distro.ImageType{}
|
||||
}
|
||||
for idx := range imageTypes {
|
||||
it := imageTypes[idx]
|
||||
it.arch = a
|
||||
it.platform = platform
|
||||
a.imageTypes[it.name] = &it
|
||||
for _, alias := range it.nameAliases {
|
||||
if a.imageTypeAliases == nil {
|
||||
|
|
@ -483,6 +482,7 @@ type packageSetFunc func(t *imageType) rpmmd.PackageSet
|
|||
|
||||
type imageType struct {
|
||||
arch *architecture
|
||||
platform platform.Platform
|
||||
name string
|
||||
nameAliases []string
|
||||
filename string
|
||||
|
|
@ -503,8 +503,6 @@ type imageType struct {
|
|||
rpmOstree bool
|
||||
// bootable image
|
||||
bootable bool
|
||||
// If set to a value, it is preferred over the architecture value
|
||||
bootType distro.BootType
|
||||
// List of valid arches for the image type
|
||||
basePartitionTables distro.BasePartitionTableMap
|
||||
}
|
||||
|
|
@ -581,9 +579,9 @@ func (t *imageType) PackageSets(bp blueprint.Blueprint, options distro.ImageOpti
|
|||
// the layout is converted to LVM so we need to corresponding packages
|
||||
if t.bootable && !t.rpmOstree {
|
||||
|
||||
pt, exists := t.basePartitionTables[t.arch.Name()]
|
||||
pt, exists := t.basePartitionTables[t.platform.GetArch().String()]
|
||||
if !exists {
|
||||
panic(fmt.Sprintf("unknown architecture with boot type: %s %s", t.arch.Name(), t.bootType))
|
||||
panic(fmt.Sprintf("unknown no partition table for architecture %s", t.platform.GetArch().String()))
|
||||
}
|
||||
haveNewMountpoint := false
|
||||
|
||||
|
|
@ -643,23 +641,6 @@ func (t *imageType) Exports() []string {
|
|||
return []string{"assembler"}
|
||||
}
|
||||
|
||||
// getBootType returns the BootType which should be used for this particular
|
||||
// combination of architecture and image type.
|
||||
func (t *imageType) getBootType() distro.BootType {
|
||||
bootType := t.arch.bootType
|
||||
if t.bootType != distro.UnsetBootType {
|
||||
if bootType == distro.HybridBootType {
|
||||
bootType = t.bootType
|
||||
}
|
||||
}
|
||||
return bootType
|
||||
}
|
||||
|
||||
func (t *imageType) supportsUEFI() bool {
|
||||
bootType := t.getBootType()
|
||||
return bootType == distro.HybridBootType || bootType == distro.UEFIBootType
|
||||
}
|
||||
|
||||
func (t *imageType) getPartitionTable(
|
||||
mountpoints []blueprint.FilesystemCustomization,
|
||||
options distro.ImageOptions,
|
||||
|
|
@ -794,51 +775,99 @@ func newDistro(distroName string) distro.Distro {
|
|||
|
||||
// Architecture definitions
|
||||
x86_64 := architecture{
|
||||
name: distro.X86_64ArchName,
|
||||
distro: &rd,
|
||||
legacy: "i386-pc",
|
||||
bootType: distro.HybridBootType,
|
||||
name: distro.X86_64ArchName,
|
||||
distro: &rd,
|
||||
}
|
||||
|
||||
aarch64 := architecture{
|
||||
name: distro.Aarch64ArchName,
|
||||
distro: &rd,
|
||||
bootType: distro.UEFIBootType,
|
||||
name: distro.Aarch64ArchName,
|
||||
distro: &rd,
|
||||
}
|
||||
|
||||
s390x := architecture{
|
||||
distro: &rd,
|
||||
name: distro.S390xArchName,
|
||||
bootType: distro.LegacyBootType,
|
||||
distro: &rd,
|
||||
name: distro.S390xArchName,
|
||||
}
|
||||
|
||||
ociImgType := qcow2ImgType
|
||||
ociImgType.name = "oci"
|
||||
|
||||
x86_64.addImageTypes(
|
||||
amiImgType,
|
||||
containerImgType,
|
||||
&platform.X86{
|
||||
BIOS: true,
|
||||
UEFIVendor: "fedora",
|
||||
},
|
||||
qcow2ImgType,
|
||||
openstackImgType,
|
||||
vhdImgType,
|
||||
vmdkImgType,
|
||||
ociImgType,
|
||||
)
|
||||
x86_64.addImageTypes(
|
||||
&platform.X86{
|
||||
BIOS: true,
|
||||
},
|
||||
amiImgType,
|
||||
)
|
||||
x86_64.addImageTypes(
|
||||
&platform.X86{},
|
||||
containerImgType,
|
||||
)
|
||||
x86_64.addImageTypes(
|
||||
&platform.X86{
|
||||
BasePlatform: platform.BasePlatform{
|
||||
FirmwarePackages: []string{
|
||||
"microcode_ctl", // ??
|
||||
"iwl1000-firmware",
|
||||
"iwl100-firmware",
|
||||
"iwl105-firmware",
|
||||
"iwl135-firmware",
|
||||
"iwl2000-firmware",
|
||||
"iwl2030-firmware",
|
||||
"iwl3160-firmware",
|
||||
"iwl5000-firmware",
|
||||
"iwl5150-firmware",
|
||||
"iwl6000-firmware",
|
||||
"iwl6050-firmware",
|
||||
},
|
||||
},
|
||||
BIOS: true,
|
||||
UEFIVendor: "fedora",
|
||||
},
|
||||
iotOCIImgType,
|
||||
iotCommitImgType,
|
||||
iotInstallerImgType,
|
||||
)
|
||||
aarch64.addImageTypes(
|
||||
&platform.Aarch64{
|
||||
UEFIVendor: "fedora",
|
||||
},
|
||||
amiImgType,
|
||||
containerImgType,
|
||||
qcow2ImgType,
|
||||
openstackImgType,
|
||||
ociImgType,
|
||||
)
|
||||
aarch64.addImageTypes(
|
||||
&platform.Aarch64{},
|
||||
containerImgType,
|
||||
)
|
||||
aarch64.addImageTypes(
|
||||
&platform.Aarch64{
|
||||
BasePlatform: platform.BasePlatform{
|
||||
FirmwarePackages: []string{
|
||||
"uboot-images-armv8", // ??
|
||||
"bcm283x-firmware",
|
||||
"arm-image-installer", // ??
|
||||
},
|
||||
},
|
||||
UEFIVendor: "fedora",
|
||||
},
|
||||
iotCommitImgType,
|
||||
iotOCIImgType,
|
||||
iotInstallerImgType,
|
||||
)
|
||||
|
||||
s390x.addImageTypes()
|
||||
s390x.addImageTypes(nil)
|
||||
|
||||
rd.addArches(x86_64, aarch64, s390x)
|
||||
return &rd
|
||||
|
|
|
|||
|
|
@ -208,19 +208,7 @@ func osPipeline(m *manifest.Manifest,
|
|||
|
||||
imageConfig := t.getDefaultImageConfig()
|
||||
|
||||
var arch manifest.Arch
|
||||
switch t.Arch().Name() {
|
||||
case distro.X86_64ArchName:
|
||||
arch = manifest.ARCH_X86_64
|
||||
case distro.Aarch64ArchName:
|
||||
arch = manifest.ARCH_AARCH64
|
||||
case distro.Ppc64leArchName:
|
||||
arch = manifest.ARCH_PPC64LE
|
||||
case distro.S390xArchName:
|
||||
arch = manifest.ARCH_S390X
|
||||
}
|
||||
|
||||
pl := manifest.NewOSPipeline(m, buildPipeline, arch, repos)
|
||||
pl := manifest.NewOSPipeline(m, buildPipeline, t.platform, repos)
|
||||
|
||||
if t.bootable {
|
||||
var err error
|
||||
|
|
@ -232,12 +220,6 @@ func osPipeline(m *manifest.Manifest,
|
|||
}
|
||||
|
||||
if t.bootable || t.rpmOstree {
|
||||
if t.supportsUEFI() {
|
||||
pl.UEFIVendor = t.arch.distro.vendor
|
||||
}
|
||||
|
||||
pl.BIOSPlatform = t.arch.legacy
|
||||
|
||||
pl.KernelName = c.GetKernel().Name
|
||||
|
||||
var kernelOptions []string
|
||||
|
|
|
|||
|
|
@ -235,46 +235,11 @@ func iotCommitPackageSet(t *imageType) rpmmd.PackageSet {
|
|||
"iwlax2xx-firmware",
|
||||
},
|
||||
}
|
||||
switch t.Arch().Name() {
|
||||
case distro.X86_64ArchName:
|
||||
ps = ps.Append(x8664IOTCommitPackageSet())
|
||||
|
||||
case distro.Aarch64ArchName:
|
||||
ps = ps.Append(aarch64IOTCommitPackageSet())
|
||||
}
|
||||
|
||||
return ps
|
||||
|
||||
}
|
||||
|
||||
func x8664IOTCommitPackageSet() rpmmd.PackageSet {
|
||||
return rpmmd.PackageSet{
|
||||
Include: []string{
|
||||
"microcode_ctl",
|
||||
"iwl1000-firmware",
|
||||
"iwl100-firmware",
|
||||
"iwl105-firmware",
|
||||
"iwl135-firmware",
|
||||
"iwl2000-firmware",
|
||||
"iwl2030-firmware",
|
||||
"iwl3160-firmware",
|
||||
"iwl5000-firmware",
|
||||
"iwl5150-firmware",
|
||||
"iwl6000-firmware",
|
||||
"iwl6050-firmware",
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func aarch64IOTCommitPackageSet() rpmmd.PackageSet {
|
||||
return rpmmd.PackageSet{
|
||||
Include: []string{
|
||||
"uboot-images-armv8",
|
||||
"bcm283x-firmware",
|
||||
"arm-image-installer"},
|
||||
}
|
||||
}
|
||||
|
||||
// INSTALLER PACKAGE SET
|
||||
|
||||
func installerPackageSet(t *imageType) rpmmd.PackageSet {
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package manifest
|
|||
|
||||
import (
|
||||
"github.com/osbuild/osbuild-composer/internal/osbuild2"
|
||||
"github.com/osbuild/osbuild-composer/internal/platform"
|
||||
)
|
||||
|
||||
// A LiveImgPipeline represents a raw image file which can be booted in a
|
||||
|
|
@ -51,12 +52,12 @@ func (p *LiveImgPipeline) serialize() osbuild2.Pipeline {
|
|||
pipeline.AddStage(stage)
|
||||
}
|
||||
|
||||
switch p.treePipeline.arch {
|
||||
case ARCH_S390X:
|
||||
switch p.treePipeline.platform.GetArch() {
|
||||
case platform.ARCH_S390X:
|
||||
loopback := osbuild2.NewLoopbackDevice(&osbuild2.LoopbackDeviceOptions{Filename: p.filename})
|
||||
pipeline.AddStage(osbuild2.NewZiplInstStage(osbuild2.NewZiplInstStageOptions(p.treePipeline.kernelVer, pt), loopback, copyDevices, copyMounts))
|
||||
default:
|
||||
if grubLegacy := p.treePipeline.BIOSPlatform; grubLegacy != "" {
|
||||
if grubLegacy := p.treePipeline.platform.GetBIOSPlatform(); grubLegacy != "" {
|
||||
pipeline.AddStage(osbuild2.NewGrub2InstStage(osbuild2.NewGrub2InstStageOption(p.filename, pt, grubLegacy)))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import (
|
|||
"github.com/osbuild/osbuild-composer/internal/common"
|
||||
"github.com/osbuild/osbuild-composer/internal/disk"
|
||||
"github.com/osbuild/osbuild-composer/internal/osbuild2"
|
||||
"github.com/osbuild/osbuild-composer/internal/platform"
|
||||
"github.com/osbuild/osbuild-composer/internal/rpmmd"
|
||||
)
|
||||
|
||||
|
|
@ -49,12 +50,6 @@ type OSPipeline struct {
|
|||
KernelOptionsAppend []string
|
||||
// UEFIVendor indicates whether or not the image should support UEFI and
|
||||
// if set namespaces the UEFI binaries with this string.
|
||||
UEFIVendor string
|
||||
// BIOSPlatform indicates whether or not the image should support BIOS
|
||||
// booting and if set, the name of the platform, e.g., i386-pc
|
||||
BIOSPlatform string
|
||||
// GPGKeyFiles are a list of filenames in the OS which will be imported
|
||||
// as GPG keys into the RPM database.
|
||||
GPGKeyFiles []string
|
||||
Language string
|
||||
Keyboard *string
|
||||
|
|
@ -98,7 +93,7 @@ type OSPipeline struct {
|
|||
|
||||
repos []rpmmd.RepoConfig
|
||||
packageSpecs []rpmmd.PackageSpec
|
||||
arch Arch
|
||||
platform platform.Platform
|
||||
kernelVer string
|
||||
}
|
||||
|
||||
|
|
@ -110,12 +105,12 @@ type OSPipeline struct {
|
|||
// kernel package that will be used on the target system.
|
||||
func NewOSPipeline(m *Manifest,
|
||||
buildPipeline *BuildPipeline,
|
||||
arch Arch,
|
||||
platform platform.Platform,
|
||||
repos []rpmmd.RepoConfig) *OSPipeline {
|
||||
p := &OSPipeline{
|
||||
BasePipeline: NewBasePipeline(m, "os", buildPipeline, nil),
|
||||
repos: repos,
|
||||
arch: arch,
|
||||
platform: platform,
|
||||
Language: "C.UTF-8",
|
||||
Hostname: "localhost.localdomain",
|
||||
Timezone: "UTC",
|
||||
|
|
@ -127,34 +122,7 @@ func NewOSPipeline(m *Manifest,
|
|||
}
|
||||
|
||||
func (p *OSPipeline) getPackageSetChain() []rpmmd.PackageSet {
|
||||
packages := []string{}
|
||||
|
||||
switch p.arch {
|
||||
case ARCH_X86_64:
|
||||
if p.BIOSPlatform != "" {
|
||||
packages = append(packages,
|
||||
"dracut-config-generic",
|
||||
"grub2-pc")
|
||||
}
|
||||
if p.UEFIVendor != "" {
|
||||
packages = append(packages,
|
||||
"dracut-config-generic",
|
||||
"efibootmgr",
|
||||
"grub2-efi-x64",
|
||||
"shim-x64")
|
||||
}
|
||||
case ARCH_AARCH64:
|
||||
if p.UEFIVendor != "" {
|
||||
packages = append(packages,
|
||||
"dracut-config-generic",
|
||||
"efibootmgr",
|
||||
"grub2-efi-aa64",
|
||||
"grub2-tools",
|
||||
"shim-aa64")
|
||||
}
|
||||
default:
|
||||
panic("unsupported architecture")
|
||||
}
|
||||
packages := p.platform.GetPackages()
|
||||
|
||||
chain := []rpmmd.PackageSet{
|
||||
{
|
||||
|
|
@ -175,10 +143,7 @@ func (p *OSPipeline) getPackageSetChain() []rpmmd.PackageSet {
|
|||
}
|
||||
|
||||
func (p *OSPipeline) getBuildPackages() []string {
|
||||
packages := []string{}
|
||||
if p.BIOSPlatform != "" {
|
||||
packages = append(packages, "grub2-pc")
|
||||
}
|
||||
packages := p.platform.GetBuildPackages()
|
||||
if p.OSTree != nil {
|
||||
packages = append(packages, "rpm-ostree")
|
||||
}
|
||||
|
|
@ -383,11 +348,15 @@ func (p *OSPipeline) serialize() osbuild2.Pipeline {
|
|||
pipeline.AddStage(osbuild2.NewFSTabStage(osbuild2.NewFSTabStageOptions(pt)))
|
||||
|
||||
var bootloader *osbuild2.Stage
|
||||
switch p.arch {
|
||||
case ARCH_S390X:
|
||||
switch p.platform.GetArch() {
|
||||
case platform.ARCH_S390X:
|
||||
bootloader = osbuild2.NewZiplStage(new(osbuild2.ZiplStageOptions))
|
||||
default:
|
||||
options := osbuild2.NewGrub2StageOptionsUnified(pt, p.kernelVer, p.UEFIVendor != "", p.BIOSPlatform, p.UEFIVendor, false)
|
||||
options := osbuild2.NewGrub2StageOptionsUnified(pt,
|
||||
p.kernelVer,
|
||||
p.platform.GetUEFIVendor() != "",
|
||||
p.platform.GetBIOSPlatform(),
|
||||
p.platform.GetUEFIVendor(), false)
|
||||
if cfg := p.Grub2Config; cfg != nil {
|
||||
// TODO: don't store Grub2Config in OSPipeline, making the overrides unnecessary
|
||||
// grub2.Config.Default is owned and set by `NewGrub2StageOptionsUnified`
|
||||
|
|
|
|||
29
internal/platform/aarch64.go
Normal file
29
internal/platform/aarch64.go
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
package platform
|
||||
|
||||
type Aarch64 struct {
|
||||
BasePlatform
|
||||
UEFIVendor string
|
||||
}
|
||||
|
||||
func (p *Aarch64) GetArch() Arch {
|
||||
return ARCH_AARCH64
|
||||
}
|
||||
|
||||
func (p *Aarch64) GetUEFIVendor() string {
|
||||
return p.UEFIVendor
|
||||
}
|
||||
|
||||
func (p *Aarch64) GetPackages() []string {
|
||||
packages := p.BasePlatform.FirmwarePackages
|
||||
|
||||
if p.UEFIVendor != "" {
|
||||
packages = append(packages,
|
||||
"dracut-config-generic",
|
||||
"efibootmgr",
|
||||
"grub2-efi-aa64",
|
||||
"grub2-tools",
|
||||
"shim-aa64")
|
||||
}
|
||||
|
||||
return packages
|
||||
}
|
||||
58
internal/platform/platform.go
Normal file
58
internal/platform/platform.go
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
package platform
|
||||
|
||||
type Arch uint64
|
||||
|
||||
const (
|
||||
ARCH_AARCH64 Arch = iota
|
||||
ARCH_PPC64LE
|
||||
ARCH_S390X
|
||||
ARCH_X86_64
|
||||
)
|
||||
|
||||
func (a Arch) String() string {
|
||||
switch a {
|
||||
case ARCH_AARCH64:
|
||||
return "aarch64"
|
||||
case ARCH_PPC64LE:
|
||||
return "ppc64le"
|
||||
case ARCH_S390X:
|
||||
return "s390x"
|
||||
case ARCH_X86_64:
|
||||
return "x86_64"
|
||||
default:
|
||||
panic("invalid architecture")
|
||||
}
|
||||
}
|
||||
|
||||
type Platform interface {
|
||||
GetArch() Arch
|
||||
GetBIOSPlatform() string
|
||||
GetUEFIVendor() string
|
||||
GetZiplSupport() bool
|
||||
GetPackages() []string
|
||||
GetBuildPackages() []string
|
||||
}
|
||||
|
||||
type BasePlatform struct {
|
||||
FirmwarePackages []string
|
||||
}
|
||||
|
||||
func (p BasePlatform) GetBIOSPlatform() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (p BasePlatform) GetUEFIVendor() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (p BasePlatform) GetZiplSupport() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (p BasePlatform) GetPackages() []string {
|
||||
return p.FirmwarePackages
|
||||
}
|
||||
|
||||
func (p BasePlatform) GetBuildPackages() []string {
|
||||
return []string{}
|
||||
}
|
||||
52
internal/platform/x86_64.go
Normal file
52
internal/platform/x86_64.go
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
package platform
|
||||
|
||||
type X86BootLoader uint64
|
||||
|
||||
type X86 struct {
|
||||
BasePlatform
|
||||
BIOS bool
|
||||
UEFIVendor string
|
||||
}
|
||||
|
||||
func (p *X86) GetArch() Arch {
|
||||
return ARCH_X86_64
|
||||
}
|
||||
|
||||
func (p *X86) GetBIOSPlatform() string {
|
||||
if p.BIOS {
|
||||
return "i386-pc"
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (p *X86) GetUEFIVendor() string {
|
||||
return p.UEFIVendor
|
||||
}
|
||||
|
||||
func (p *X86) GetPackages() []string {
|
||||
packages := p.BasePlatform.FirmwarePackages
|
||||
|
||||
if p.BIOS {
|
||||
packages = append(packages,
|
||||
"dracut-config-generic",
|
||||
"grub2-pc")
|
||||
}
|
||||
|
||||
if p.UEFIVendor != "" {
|
||||
packages = append(packages,
|
||||
"dracut-config-generic",
|
||||
"efibootmgr",
|
||||
"grub2-efi-x64",
|
||||
"shim-x64")
|
||||
}
|
||||
|
||||
return packages
|
||||
}
|
||||
|
||||
func (p *X86) GetBuildPackages() []string {
|
||||
packages := []string{}
|
||||
if p.BIOS {
|
||||
packages = append(packages, "grub2-pc")
|
||||
}
|
||||
return packages
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue