Blame internal/distro/fedora32/distro.go

Packit 63bb0d
package fedora32
Packit 63bb0d
Packit 63bb0d
import (
Packit 63bb0d
	"encoding/json"
Packit 63bb0d
	"errors"
Packit 63bb0d
	"fmt"
Packit 63bb0d
	"sort"
Packit 63bb0d
Packit 63bb0d
	"github.com/osbuild/osbuild-composer/internal/distro"
Packit Service 15f37d
	osbuild "github.com/osbuild/osbuild-composer/internal/osbuild1"
Packit 63bb0d
Packit 63bb0d
	"github.com/google/uuid"
Packit 63bb0d
Packit 63bb0d
	"github.com/osbuild/osbuild-composer/internal/blueprint"
Packit 63bb0d
	"github.com/osbuild/osbuild-composer/internal/crypt"
Packit 63bb0d
	"github.com/osbuild/osbuild-composer/internal/rpmmd"
Packit 63bb0d
)
Packit 63bb0d
Packit 63bb0d
const name = "fedora-32"
Packit 63bb0d
const modulePlatformID = "platform:f32"
Packit Service bcdfb1
const ostreeRef = "fedora/32/%s/iot"
Packit 63bb0d
Packit 63bb0d
type distribution struct {
Packit 63bb0d
	arches        map[string]architecture
Packit 63bb0d
	imageTypes    map[string]imageType
Packit 63bb0d
	buildPackages []string
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
type architecture struct {
Packit 63bb0d
	distro             *distribution
Packit 63bb0d
	name               string
Packit 63bb0d
	bootloaderPackages []string
Packit 63bb0d
	buildPackages      []string
Packit 63bb0d
	legacy             string
Packit 63bb0d
	uefi               bool
Packit 63bb0d
	imageTypes         map[string]imageType
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
type imageType struct {
Packit 63bb0d
	arch             *architecture
Packit 63bb0d
	name             string
Packit 63bb0d
	filename         string
Packit 63bb0d
	mimeType         string
Packit 63bb0d
	packages         []string
Packit 63bb0d
	excludedPackages []string
Packit 63bb0d
	enabledServices  []string
Packit 63bb0d
	disabledServices []string
Packit 63bb0d
	kernelOptions    string
Packit 63bb0d
	bootable         bool
Packit 63bb0d
	rpmOstree        bool
Packit 63bb0d
	defaultSize      uint64
Packit 63bb0d
	assembler        func(uefi bool, options distro.ImageOptions, arch distro.Arch) *osbuild.Assembler
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
func (a *architecture) Distro() distro.Distro {
Packit 63bb0d
	return a.distro
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
func (t *imageType) Arch() distro.Arch {
Packit 63bb0d
	return t.arch
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
func (d *distribution) ListArches() []string {
Packit 63bb0d
	archs := make([]string, 0, len(d.arches))
Packit 63bb0d
	for name := range d.arches {
Packit 63bb0d
		archs = append(archs, name)
Packit 63bb0d
	}
Packit 63bb0d
	sort.Strings(archs)
Packit 63bb0d
	return archs
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
func (d *distribution) GetArch(arch string) (distro.Arch, error) {
Packit 63bb0d
	a, exists := d.arches[arch]
Packit 63bb0d
	if !exists {
Packit 63bb0d
		return nil, errors.New("invalid architecture: " + arch)
Packit 63bb0d
	}
Packit 63bb0d
Packit 63bb0d
	return &a, nil
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
func (d *distribution) setArches(arches ...architecture) {
Packit 63bb0d
	d.arches = map[string]architecture{}
Packit 63bb0d
	for _, a := range arches {
Packit 63bb0d
		d.arches[a.name] = architecture{
Packit 63bb0d
			distro:             d,
Packit 63bb0d
			name:               a.name,
Packit 63bb0d
			bootloaderPackages: a.bootloaderPackages,
Packit 63bb0d
			buildPackages:      a.buildPackages,
Packit 63bb0d
			uefi:               a.uefi,
Packit 63bb0d
			imageTypes:         a.imageTypes,
Packit 63bb0d
		}
Packit 63bb0d
	}
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
func (a *architecture) Name() string {
Packit 63bb0d
	return a.name
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
func (a *architecture) ListImageTypes() []string {
Packit 63bb0d
	formats := make([]string, 0, len(a.imageTypes))
Packit 63bb0d
	for name := range a.imageTypes {
Packit 63bb0d
		formats = append(formats, name)
Packit 63bb0d
	}
Packit 63bb0d
	sort.Strings(formats)
Packit 63bb0d
	return formats
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
func (a *architecture) GetImageType(imageType string) (distro.ImageType, error) {
Packit 63bb0d
	t, exists := a.imageTypes[imageType]
Packit 63bb0d
	if !exists {
Packit 63bb0d
		return nil, errors.New("invalid image type: " + imageType)
Packit 63bb0d
	}
Packit 63bb0d
Packit 63bb0d
	return &t, nil
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
func (a *architecture) setImageTypes(imageTypes ...imageType) {
Packit 63bb0d
	a.imageTypes = map[string]imageType{}
Packit 63bb0d
	for _, it := range imageTypes {
Packit 63bb0d
		a.imageTypes[it.name] = imageType{
Packit 63bb0d
			arch:             a,
Packit 63bb0d
			name:             it.name,
Packit 63bb0d
			filename:         it.filename,
Packit 63bb0d
			mimeType:         it.mimeType,
Packit 63bb0d
			packages:         it.packages,
Packit 63bb0d
			excludedPackages: it.excludedPackages,
Packit 63bb0d
			enabledServices:  it.enabledServices,
Packit 63bb0d
			disabledServices: it.disabledServices,
Packit 63bb0d
			kernelOptions:    it.kernelOptions,
Packit 63bb0d
			bootable:         it.bootable,
Packit 63bb0d
			rpmOstree:        it.rpmOstree,
Packit 63bb0d
			defaultSize:      it.defaultSize,
Packit 63bb0d
			assembler:        it.assembler,
Packit 63bb0d
		}
Packit 63bb0d
	}
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
func (t *imageType) Name() string {
Packit 63bb0d
	return t.name
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
func (t *imageType) Filename() string {
Packit 63bb0d
	return t.filename
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
func (t *imageType) MIMEType() string {
Packit 63bb0d
	return t.mimeType
Packit 63bb0d
}
Packit 63bb0d
Packit Service bcdfb1
func (t *imageType) OSTreeRef() string {
Packit Service bcdfb1
	if t.rpmOstree {
Packit Service bcdfb1
		return fmt.Sprintf(ostreeRef, t.arch.name)
Packit Service bcdfb1
	}
Packit Service bcdfb1
	return ""
Packit Service bcdfb1
}
Packit Service bcdfb1
Packit 63bb0d
func (t *imageType) Size(size uint64) uint64 {
Packit 63bb0d
	const MegaByte = 1024 * 1024
Packit 63bb0d
	// Microsoft Azure requires vhd images to be rounded up to the nearest MB
Packit 63bb0d
	if t.name == "vhd" && size%MegaByte != 0 {
Packit 63bb0d
		size = (size/MegaByte + 1) * MegaByte
Packit 63bb0d
	}
Packit 63bb0d
	if size == 0 {
Packit 63bb0d
		size = t.defaultSize
Packit 63bb0d
	}
Packit 63bb0d
	return size
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
func (t *imageType) Packages(bp blueprint.Blueprint) ([]string, []string) {
Packit 63bb0d
	packages := append(t.packages, bp.GetPackages()...)
Packit 63bb0d
	timezone, _ := bp.Customizations.GetTimezoneSettings()
Packit 63bb0d
	if timezone != nil {
Packit 63bb0d
		packages = append(packages, "chrony")
Packit 63bb0d
	}
Packit 63bb0d
	if t.bootable {
Packit 63bb0d
		packages = append(packages, t.arch.bootloaderPackages...)
Packit 63bb0d
	}
Packit 63bb0d
Packit 63bb0d
	return packages, t.excludedPackages
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
func (t *imageType) BuildPackages() []string {
Packit 63bb0d
	packages := append(t.arch.distro.buildPackages, t.arch.buildPackages...)
Packit 63bb0d
	if t.rpmOstree {
Packit 63bb0d
		packages = append(packages, "rpm-ostree")
Packit 63bb0d
	}
Packit 63bb0d
	return packages
Packit 63bb0d
}
Packit 63bb0d
Packit Service 15f37d
func (t *imageType) PackageSets(bp blueprint.Blueprint) map[string]rpmmd.PackageSet {
Packit Service 15f37d
	includePackages, excludePackages := t.Packages(bp)
Packit Service 15f37d
	return map[string]rpmmd.PackageSet{
Packit Service 15f37d
		"packages": {
Packit Service 15f37d
			Include: includePackages,
Packit Service 15f37d
			Exclude: excludePackages,
Packit Service 15f37d
		},
Packit Service 15f37d
		"build-packages": {
Packit Service 15f37d
			Include: t.BuildPackages(),
Packit Service 15f37d
		},
Packit Service 15f37d
	}
Packit Service 15f37d
}
Packit Service 15f37d
Packit Service 15f37d
func (t *imageType) Exports() []string {
Packit Service 15f37d
	return []string{"assembler"}
Packit Service 15f37d
}
Packit Service 15f37d
Packit 63bb0d
func (t *imageType) Manifest(c *blueprint.Customizations,
Packit 63bb0d
	options distro.ImageOptions,
Packit 63bb0d
	repos []rpmmd.RepoConfig,
Packit Service 15f37d
	packageSpecSets map[string][]rpmmd.PackageSpec,
Packit Service 509fd4
	seed int64) (distro.Manifest, error) {
Packit Service 15f37d
	pipeline, err := t.pipeline(c, options, repos, packageSpecSets["packages"], packageSpecSets["build-packages"])
Packit 63bb0d
	if err != nil {
Packit 63bb0d
		return distro.Manifest{}, err
Packit 63bb0d
	}
Packit 63bb0d
Packit 63bb0d
	return json.Marshal(
Packit 63bb0d
		osbuild.Manifest{
Packit Service 15f37d
			Sources:  *sources(append(packageSpecSets["packages"], packageSpecSets["build-packages"]...)),
Packit 63bb0d
			Pipeline: *pipeline,
Packit 63bb0d
		},
Packit 63bb0d
	)
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
func (d *distribution) Name() string {
Packit 63bb0d
	return name
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
func (d *distribution) ModulePlatformID() string {
Packit 63bb0d
	return modulePlatformID
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
func sources(packages []rpmmd.PackageSpec) *osbuild.Sources {
Packit 63bb0d
	files := &osbuild.FilesSource{
Packit 63bb0d
		URLs: make(map[string]osbuild.FileSource),
Packit 63bb0d
	}
Packit 63bb0d
	for _, pkg := range packages {
Packit 63bb0d
		fileSource := osbuild.FileSource{
Packit 63bb0d
			URL: pkg.RemoteLocation,
Packit 63bb0d
		}
Packit 63bb0d
		files.URLs[pkg.Checksum] = fileSource
Packit 63bb0d
	}
Packit 63bb0d
	return &osbuild.Sources{
Packit 63bb0d
		"org.osbuild.files": files,
Packit 63bb0d
	}
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
func (t *imageType) pipeline(c *blueprint.Customizations, options distro.ImageOptions, repos []rpmmd.RepoConfig, packageSpecs, buildPackageSpecs []rpmmd.PackageSpec) (*osbuild.Pipeline, error) {
Packit Service bcdfb1
Packit Service bcdfb1
	if kernelOpts := c.GetKernel(); kernelOpts != nil && kernelOpts.Append != "" && t.rpmOstree {
Packit Service bcdfb1
		return nil, fmt.Errorf("kernel boot parameter customizations are not supported for ostree types")
Packit Service bcdfb1
	}
Packit Service bcdfb1
Packit 63bb0d
	p := &osbuild.Pipeline{}
Packit 63bb0d
	p.SetBuild(t.buildPipeline(repos, *t.arch, buildPackageSpecs), "org.osbuild.fedora32")
Packit 63bb0d
Packit 63bb0d
	p.AddStage(osbuild.NewRPMStage(t.rpmStageOptions(*t.arch, repos, packageSpecs)))
Packit 63bb0d
	p.AddStage(osbuild.NewFixBLSStage())
Packit 63bb0d
Packit 63bb0d
	// TODO support setting all languages and install corresponding langpack-* package
Packit 63bb0d
	language, keyboard := c.GetPrimaryLocale()
Packit 63bb0d
Packit 63bb0d
	if language != nil {
Packit 63bb0d
		p.AddStage(osbuild.NewLocaleStage(&osbuild.LocaleStageOptions{Language: *language}))
Packit 63bb0d
	} else {
Packit 63bb0d
		p.AddStage(osbuild.NewLocaleStage(&osbuild.LocaleStageOptions{Language: "en_US"}))
Packit 63bb0d
	}
Packit 63bb0d
Packit 63bb0d
	if keyboard != nil {
Packit 63bb0d
		p.AddStage(osbuild.NewKeymapStage(&osbuild.KeymapStageOptions{Keymap: *keyboard}))
Packit 63bb0d
	}
Packit 63bb0d
Packit 63bb0d
	if hostname := c.GetHostname(); hostname != nil {
Packit 63bb0d
		p.AddStage(osbuild.NewHostnameStage(&osbuild.HostnameStageOptions{Hostname: *hostname}))
Packit 63bb0d
	}
Packit 63bb0d
Packit 63bb0d
	timezone, ntpServers := c.GetTimezoneSettings()
Packit 63bb0d
Packit 63bb0d
	if timezone != nil {
Packit 63bb0d
		p.AddStage(osbuild.NewTimezoneStage(&osbuild.TimezoneStageOptions{Zone: *timezone}))
Packit 63bb0d
	}
Packit 63bb0d
Packit 63bb0d
	if len(ntpServers) > 0 {
Packit 63bb0d
		p.AddStage(osbuild.NewChronyStage(&osbuild.ChronyStageOptions{Timeservers: ntpServers}))
Packit 63bb0d
	}
Packit 63bb0d
Packit 63bb0d
	if groups := c.GetGroups(); len(groups) > 0 {
Packit 63bb0d
		p.AddStage(osbuild.NewGroupsStage(t.groupStageOptions(groups)))
Packit 63bb0d
	}
Packit 63bb0d
Packit 63bb0d
	if users := c.GetUsers(); len(users) > 0 {
Packit 63bb0d
		options, err := t.userStageOptions(users)
Packit 63bb0d
		if err != nil {
Packit 63bb0d
			return nil, err
Packit 63bb0d
		}
Packit 63bb0d
		p.AddStage(osbuild.NewUsersStage(options))
Packit 63bb0d
	}
Packit 63bb0d
Packit 63bb0d
	if t.bootable {
Packit 63bb0d
		p.AddStage(osbuild.NewFSTabStage(t.fsTabStageOptions(t.arch.uefi)))
Packit 63bb0d
		p.AddStage(osbuild.NewGRUB2Stage(t.grub2StageOptions(t.kernelOptions, c.GetKernel(), t.arch.uefi)))
Packit 63bb0d
	}
Packit 63bb0d
Packit 63bb0d
	if services := c.GetServices(); services != nil || t.enabledServices != nil {
Packit 63bb0d
		p.AddStage(osbuild.NewSystemdStage(t.systemdStageOptions(t.enabledServices, t.disabledServices, services)))
Packit 63bb0d
	}
Packit 63bb0d
Packit 63bb0d
	if firewall := c.GetFirewall(); firewall != nil {
Packit 63bb0d
		p.AddStage(osbuild.NewFirewallStage(t.firewallStageOptions(firewall)))
Packit 63bb0d
	}
Packit 63bb0d
Packit 63bb0d
	p.AddStage(osbuild.NewSELinuxStage(t.selinuxStageOptions()))
Packit 63bb0d
Packit 63bb0d
	if t.rpmOstree {
Packit 63bb0d
		p.AddStage(osbuild.NewRPMOSTreeStage(&osbuild.RPMOSTreeStageOptions{
Packit 63bb0d
			EtcGroupMembers: []string{
Packit 63bb0d
				// NOTE: We may want to make this configurable.
Packit 63bb0d
				"wheel", "docker",
Packit 63bb0d
			},
Packit 63bb0d
		}))
Packit 63bb0d
	}
Packit 63bb0d
Packit 63bb0d
	p.Assembler = t.assembler(t.arch.uefi, options, t.arch)
Packit 63bb0d
Packit 63bb0d
	return p, nil
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
func (t *imageType) buildPipeline(repos []rpmmd.RepoConfig, arch architecture, buildPackageSpecs []rpmmd.PackageSpec) *osbuild.Pipeline {
Packit 63bb0d
	p := &osbuild.Pipeline{}
Packit 63bb0d
	p.AddStage(osbuild.NewRPMStage(t.rpmStageOptions(arch, repos, buildPackageSpecs)))
Packit 63bb0d
Packit 63bb0d
	selinuxOptions := osbuild.SELinuxStageOptions{
Packit 63bb0d
		FileContexts: "etc/selinux/targeted/contexts/files/file_contexts",
Packit 63bb0d
		Labels: map[string]string{
Packit 63bb0d
			"/usr/bin/cp": "system_u:object_r:install_exec_t:s0",
Packit 63bb0d
		},
Packit 63bb0d
	}
Packit 63bb0d
Packit 63bb0d
	p.AddStage(osbuild.NewSELinuxStage(&selinuxOptions))
Packit 63bb0d
	return p
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
func (t *imageType) rpmStageOptions(arch architecture, repos []rpmmd.RepoConfig, specs []rpmmd.PackageSpec) *osbuild.RPMStageOptions {
Packit 63bb0d
	var gpgKeys []string
Packit 63bb0d
	for _, repo := range repos {
Packit 63bb0d
		if repo.GPGKey == "" {
Packit 63bb0d
			continue
Packit 63bb0d
		}
Packit 63bb0d
		gpgKeys = append(gpgKeys, repo.GPGKey)
Packit 63bb0d
	}
Packit 63bb0d
Packit 63bb0d
	var packages []osbuild.RPMPackage
Packit 63bb0d
	for _, spec := range specs {
Packit 63bb0d
		pkg := osbuild.RPMPackage{
Packit 63bb0d
			Checksum: spec.Checksum,
Packit 63bb0d
			CheckGPG: spec.CheckGPG,
Packit 63bb0d
		}
Packit 63bb0d
		packages = append(packages, pkg)
Packit 63bb0d
	}
Packit 63bb0d
Packit 63bb0d
	return &osbuild.RPMStageOptions{
Packit 63bb0d
		GPGKeys:  gpgKeys,
Packit 63bb0d
		Packages: packages,
Packit 63bb0d
	}
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
func (t *imageType) userStageOptions(users []blueprint.UserCustomization) (*osbuild.UsersStageOptions, error) {
Packit 63bb0d
	options := osbuild.UsersStageOptions{
Packit 63bb0d
		Users: make(map[string]osbuild.UsersStageOptionsUser),
Packit 63bb0d
	}
Packit 63bb0d
Packit 63bb0d
	for _, c := range users {
Packit 63bb0d
		if c.Password != nil && !crypt.PasswordIsCrypted(*c.Password) {
Packit 63bb0d
			cryptedPassword, err := crypt.CryptSHA512(*c.Password)
Packit 63bb0d
			if err != nil {
Packit 63bb0d
				return nil, err
Packit 63bb0d
			}
Packit 63bb0d
Packit 63bb0d
			c.Password = &cryptedPassword
Packit 63bb0d
		}
Packit 63bb0d
Packit 63bb0d
		user := osbuild.UsersStageOptionsUser{
Packit 63bb0d
			Groups:      c.Groups,
Packit 63bb0d
			Description: c.Description,
Packit 63bb0d
			Home:        c.Home,
Packit 63bb0d
			Shell:       c.Shell,
Packit 63bb0d
			Password:    c.Password,
Packit 63bb0d
			Key:         c.Key,
Packit 63bb0d
		}
Packit 63bb0d
Packit 63bb0d
		user.UID = c.UID
Packit 63bb0d
		user.GID = c.GID
Packit 63bb0d
Packit 63bb0d
		options.Users[c.Name] = user
Packit 63bb0d
	}
Packit 63bb0d
Packit 63bb0d
	return &options, nil
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
func (t *imageType) groupStageOptions(groups []blueprint.GroupCustomization) *osbuild.GroupsStageOptions {
Packit 63bb0d
	options := osbuild.GroupsStageOptions{
Packit 63bb0d
		Groups: map[string]osbuild.GroupsStageOptionsGroup{},
Packit 63bb0d
	}
Packit 63bb0d
Packit 63bb0d
	for _, group := range groups {
Packit 63bb0d
		groupData := osbuild.GroupsStageOptionsGroup{
Packit 63bb0d
			Name: group.Name,
Packit 63bb0d
		}
Packit 63bb0d
		groupData.GID = group.GID
Packit 63bb0d
Packit 63bb0d
		options.Groups[group.Name] = groupData
Packit 63bb0d
	}
Packit 63bb0d
Packit 63bb0d
	return &options
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
func (t *imageType) firewallStageOptions(firewall *blueprint.FirewallCustomization) *osbuild.FirewallStageOptions {
Packit 63bb0d
	options := osbuild.FirewallStageOptions{
Packit 63bb0d
		Ports: firewall.Ports,
Packit 63bb0d
	}
Packit 63bb0d
Packit 63bb0d
	if firewall.Services != nil {
Packit 63bb0d
		options.EnabledServices = firewall.Services.Enabled
Packit 63bb0d
		options.DisabledServices = firewall.Services.Disabled
Packit 63bb0d
	}
Packit 63bb0d
Packit 63bb0d
	return &options
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
func (t *imageType) systemdStageOptions(enabledServices, disabledServices []string, s *blueprint.ServicesCustomization) *osbuild.SystemdStageOptions {
Packit 63bb0d
	if s != nil {
Packit 63bb0d
		enabledServices = append(enabledServices, s.Enabled...)
Packit 63bb0d
		disabledServices = append(disabledServices, s.Disabled...)
Packit 63bb0d
	}
Packit 63bb0d
	return &osbuild.SystemdStageOptions{
Packit 63bb0d
		EnabledServices:  enabledServices,
Packit 63bb0d
		DisabledServices: disabledServices,
Packit 63bb0d
	}
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
func (t *imageType) fsTabStageOptions(uefi bool) *osbuild.FSTabStageOptions {
Packit 63bb0d
	options := osbuild.FSTabStageOptions{}
Packit 63bb0d
	options.AddFilesystem("76a22bf4-f153-4541-b6c7-0332c0dfaeac", "ext4", "/", "defaults", 1, 1)
Packit 63bb0d
	if uefi {
Packit 63bb0d
		options.AddFilesystem("46BB-8120", "vfat", "/boot/efi", "umask=0077,shortname=winnt", 0, 2)
Packit 63bb0d
	}
Packit 63bb0d
	return &options
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
func (t *imageType) grub2StageOptions(kernelOptions string, kernel *blueprint.KernelCustomization, uefi bool) *osbuild.GRUB2StageOptions {
Packit 63bb0d
	id := uuid.MustParse("76a22bf4-f153-4541-b6c7-0332c0dfaeac")
Packit 63bb0d
Packit Service 15f37d
	if kernel != nil && kernel.Append != "" {
Packit 63bb0d
		kernelOptions += " " + kernel.Append
Packit 63bb0d
	}
Packit 63bb0d
Packit 63bb0d
	var uefiOptions *osbuild.GRUB2UEFI
Packit 63bb0d
	if uefi {
Packit 63bb0d
		uefiOptions = &osbuild.GRUB2UEFI{
Packit 63bb0d
			Vendor: "fedora",
Packit 63bb0d
		}
Packit 63bb0d
	}
Packit 63bb0d
Packit 63bb0d
	var legacy string
Packit 63bb0d
	if !uefi {
Packit 63bb0d
		legacy = t.arch.legacy
Packit 63bb0d
	}
Packit 63bb0d
Packit 63bb0d
	return &osbuild.GRUB2StageOptions{
Packit 63bb0d
		RootFilesystemUUID: id,
Packit 63bb0d
		KernelOptions:      kernelOptions,
Packit 63bb0d
		Legacy:             legacy,
Packit 63bb0d
		UEFI:               uefiOptions,
Packit 63bb0d
	}
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
func (t *imageType) selinuxStageOptions() *osbuild.SELinuxStageOptions {
Packit 63bb0d
	return &osbuild.SELinuxStageOptions{
Packit 63bb0d
		FileContexts: "etc/selinux/targeted/contexts/files/file_contexts",
Packit 63bb0d
	}
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
func qemuAssembler(format string, filename string, uefi bool, imageOptions distro.ImageOptions) *osbuild.Assembler {
Packit 63bb0d
	var options osbuild.QEMUAssemblerOptions
Packit 63bb0d
	if uefi {
Packit 63bb0d
		options = osbuild.QEMUAssemblerOptions{
Packit 63bb0d
			Format:   format,
Packit 63bb0d
			Filename: filename,
Packit 63bb0d
			Size:     imageOptions.Size,
Packit 63bb0d
			PTUUID:   "8DFDFF87-C96E-EA48-A3A6-9408F1F6B1EF",
Packit 63bb0d
			PTType:   "gpt",
Packit 63bb0d
			Partitions: []osbuild.QEMUPartition{
Packit 63bb0d
				{
Packit 63bb0d
					Start: 2048,
Packit 63bb0d
					Size:  972800,
Packit 63bb0d
					Type:  "C12A7328-F81F-11D2-BA4B-00A0C93EC93B",
Packit 63bb0d
					UUID:  "02C1E068-1D2F-4DA3-91FD-8DD76A955C9D",
Packit 63bb0d
					Filesystem: &osbuild.QEMUFilesystem{
Packit 63bb0d
						Type:       "vfat",
Packit 63bb0d
						UUID:       "46BB-8120",
Packit 63bb0d
						Label:      "EFI System Partition",
Packit 63bb0d
						Mountpoint: "/boot/efi",
Packit 63bb0d
					},
Packit 63bb0d
				},
Packit 63bb0d
				{
Packit 63bb0d
					Start: 976896,
Packit 63bb0d
					UUID:  "8D760010-FAAE-46D1-9E5B-4A2EAC5030CD",
Packit 63bb0d
					Filesystem: &osbuild.QEMUFilesystem{
Packit 63bb0d
						Type:       "ext4",
Packit 63bb0d
						UUID:       "76a22bf4-f153-4541-b6c7-0332c0dfaeac",
Packit 63bb0d
						Mountpoint: "/",
Packit 63bb0d
					},
Packit 63bb0d
				},
Packit 63bb0d
			},
Packit 63bb0d
		}
Packit 63bb0d
	} else {
Packit 63bb0d
		options = osbuild.QEMUAssemblerOptions{
Packit 63bb0d
			Format:   format,
Packit 63bb0d
			Filename: filename,
Packit 63bb0d
			Size:     imageOptions.Size,
Packit 63bb0d
			PTUUID:   "0x14fc63d2",
Packit 63bb0d
			PTType:   "mbr",
Packit 63bb0d
			Partitions: []osbuild.QEMUPartition{
Packit 63bb0d
				{
Packit 63bb0d
					Start:    2048,
Packit 63bb0d
					Bootable: true,
Packit 63bb0d
					Filesystem: &osbuild.QEMUFilesystem{
Packit 63bb0d
						Type:       "ext4",
Packit 63bb0d
						UUID:       "76a22bf4-f153-4541-b6c7-0332c0dfaeac",
Packit 63bb0d
						Mountpoint: "/",
Packit 63bb0d
					},
Packit 63bb0d
				},
Packit 63bb0d
			},
Packit 63bb0d
		}
Packit 63bb0d
	}
Packit 63bb0d
	return osbuild.NewQEMUAssembler(&options)
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
func ostreeCommitAssembler(options distro.ImageOptions, arch distro.Arch) *osbuild.Assembler {
Packit 63bb0d
	return osbuild.NewOSTreeCommitAssembler(
Packit 63bb0d
		&osbuild.OSTreeCommitAssemblerOptions{
Packit Service bcdfb1
			Ref:    options.OSTree.Ref,
Packit 63bb0d
			Parent: options.OSTree.Parent,
Packit 63bb0d
			Tar: osbuild.OSTreeCommitAssemblerTarOptions{
Packit 63bb0d
				Filename: "commit.tar",
Packit 63bb0d
			},
Packit 63bb0d
		},
Packit 63bb0d
	)
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
// New creates a new distro object, defining the supported architectures and image types
Packit 63bb0d
func New() distro.Distro {
Packit 63bb0d
	const GigaByte = 1024 * 1024 * 1024
Packit 63bb0d
Packit 63bb0d
	iotImgType := imageType{
Packit 63bb0d
		name:     "fedora-iot-commit",
Packit 63bb0d
		filename: "commit.tar",
Packit 63bb0d
		mimeType: "application/x-tar",
Packit 63bb0d
		packages: []string{
Packit 63bb0d
			"fedora-release-iot",
Packit 63bb0d
			"glibc", "glibc-minimal-langpack", "nss-altfiles",
Packit 63bb0d
			"sssd-client", "libsss_sudo", "shadow-utils",
Packit 63bb0d
			"dracut-config-generic", "dracut-network",
Packit 63bb0d
			"rpm-ostree", "polkit", "lvm2",
Packit 63bb0d
			"chrony", "zram",
Packit 63bb0d
			"cryptsetup", "pinentry",
Packit 63bb0d
			"keyutils",
Packit 63bb0d
			"e2fsprogs", "dosfstools",
Packit 63bb0d
			"gnupg2",
Packit 63bb0d
			"basesystem", "python3", "bash",
Packit 63bb0d
			"xz", "gzip",
Packit 63bb0d
			"coreutils", "which", "curl",
Packit 63bb0d
			"firewalld", "iptables",
Packit 63bb0d
			"NetworkManager", "NetworkManager-wifi", "NetworkManager-wwan",
Packit 63bb0d
			"wpa_supplicant", "iwd",
Packit 63bb0d
			"dnsmasq", "traceroute",
Packit 63bb0d
			"hostname", "iproute", "iputils",
Packit 63bb0d
			"openssh-clients", "openssh-server", "passwd",
Packit 63bb0d
			"policycoreutils", "procps-ng", "rootfiles", "rpm",
Packit 63bb0d
			"selinux-policy-targeted", "setup", "shadow-utils",
Packit 63bb0d
			"sudo", "systemd", "util-linux", "vim-minimal",
Packit 63bb0d
			"less", "tar",
Packit 63bb0d
			"fwupd", // "usbguard", BUG: this fails due to an SELinux policy issue
Packit 63bb0d
			"greenboot", "greenboot-grub2", "greenboot-rpm-ostree-grub2", "greenboot-reboot", "greenboot-status",
Packit 63bb0d
			"ignition",
Packit 63bb0d
			"rsync",
Packit 63bb0d
			"ima-evm-utils",
Packit 63bb0d
			"bash-completion",
Packit 63bb0d
			"tmux", "screen",
Packit 63bb0d
			"policycoreutils-python-utils",
Packit 63bb0d
			"setools-console",
Packit 63bb0d
			"audit", "rng-tools",
Packit 63bb0d
			"bluez", "bluez-libs", "bluez-mesh", "wpan-tools",
Packit 63bb0d
			"kernel-tools", "libgpiod-utils",
Packit 63bb0d
			"podman", "container-selinux", "skopeo", "criu",
Packit 63bb0d
			"slirp4netns",
Packit 63bb0d
			"clevis", "clevis-dracut", "clevis-luks",
Packit 63bb0d
			"attr",
Packit 63bb0d
			// x86 specific
Packit 63bb0d
			"grub2", "grub2-efi-x64", "efibootmgr", "shim-x64", "microcode_ctl",
Packit 63bb0d
			"iwl1000-firmware", "iwl100-firmware", "iwl105-firmware", "iwl135-firmware",
Packit 63bb0d
			"iwl2000-firmware", "iwl2030-firmware", "iwl3160-firmware", "iwl5000-firmware",
Packit 63bb0d
			"iwl5150-firmware", "iwl6000-firmware", "iwl6050-firmware", "iwl7260-firmware",
Packit 63bb0d
		},
Packit 63bb0d
		enabledServices: []string{
Packit 63bb0d
			"NetworkManager.service", "firewalld.service", "rngd.service", "sshd.service", "zram-swap.service",
Packit 63bb0d
		},
Packit 63bb0d
		rpmOstree: true,
Packit 63bb0d
		assembler: func(uefi bool, options distro.ImageOptions, arch distro.Arch) *osbuild.Assembler {
Packit 63bb0d
			return ostreeCommitAssembler(options, arch)
Packit 63bb0d
		},
Packit 63bb0d
	}
Packit 63bb0d
	amiImgType := imageType{
Packit 63bb0d
		name:     "ami",
Packit 63bb0d
		filename: "image.raw",
Packit 63bb0d
		mimeType: "application/octet-stream",
Packit 63bb0d
		packages: []string{
Packit 63bb0d
			"@Core",
Packit 63bb0d
			"chrony",
Packit 63bb0d
			"selinux-policy-targeted",
Packit 63bb0d
			"langpacks-en",
Packit 63bb0d
			"libxcrypt-compat",
Packit 63bb0d
			"xfsprogs",
Packit 63bb0d
			"cloud-init",
Packit 63bb0d
			"checkpolicy",
Packit 63bb0d
			"net-tools",
Packit 63bb0d
		},
Packit 63bb0d
		excludedPackages: []string{
Packit 63bb0d
			"dracut-config-rescue",
Packit 63bb0d
		},
Packit 63bb0d
		enabledServices: []string{
Packit 63bb0d
			"cloud-init.service",
Packit 63bb0d
		},
Packit 63bb0d
		kernelOptions: "ro no_timer_check console=ttyS0,115200n8 console=tty1 biosdevname=0 net.ifnames=0 console=ttyS0,115200",
Packit 63bb0d
		bootable:      true,
Packit 63bb0d
		defaultSize:   6 * GigaByte,
Packit 63bb0d
		assembler: func(uefi bool, options distro.ImageOptions, arch distro.Arch) *osbuild.Assembler {
Packit 63bb0d
			return qemuAssembler("raw", "image.raw", uefi, options)
Packit 63bb0d
		},
Packit 63bb0d
	}
Packit 63bb0d
Packit 63bb0d
	qcow2ImageType := imageType{
Packit 63bb0d
		name:     "qcow2",
Packit 63bb0d
		filename: "disk.qcow2",
Packit 63bb0d
		mimeType: "application/x-qemu-disk",
Packit 63bb0d
		packages: []string{
Packit 63bb0d
			"kernel-core",
Packit 63bb0d
			"@Fedora Cloud Server",
Packit 63bb0d
			"chrony",
Packit 63bb0d
			"polkit",
Packit 63bb0d
			"systemd-udev",
Packit 63bb0d
			"selinux-policy-targeted",
Packit 63bb0d
			"langpacks-en",
Packit 63bb0d
		},
Packit 63bb0d
		excludedPackages: []string{
Packit 63bb0d
			"dracut-config-rescue",
Packit 63bb0d
			"etables",
Packit 63bb0d
			"firewalld",
Packit 63bb0d
			"gobject-introspection",
Packit 63bb0d
			"plymouth",
Packit 63bb0d
		},
Packit 63bb0d
		enabledServices: []string{
Packit 63bb0d
			"cloud-init.service",
Packit 63bb0d
			"cloud-config.service",
Packit 63bb0d
			"cloud-final.service",
Packit 63bb0d
			"cloud-init-local.service",
Packit 63bb0d
		},
Packit 63bb0d
		kernelOptions: "ro biosdevname=0 net.ifnames=0",
Packit 63bb0d
		bootable:      true,
Packit 63bb0d
		defaultSize:   2 * GigaByte,
Packit 63bb0d
		assembler: func(uefi bool, options distro.ImageOptions, arch distro.Arch) *osbuild.Assembler {
Packit 63bb0d
			return qemuAssembler("qcow2", "disk.qcow2", uefi, options)
Packit 63bb0d
		},
Packit 63bb0d
	}
Packit 63bb0d
Packit 63bb0d
	openstackImgType := imageType{
Packit 63bb0d
		name:     "openstack",
Packit 63bb0d
		filename: "disk.qcow2",
Packit 63bb0d
		mimeType: "application/x-qemu-disk",
Packit 63bb0d
		packages: []string{
Packit 63bb0d
			"@Core",
Packit 63bb0d
			"chrony",
Packit 63bb0d
			"selinux-policy-targeted",
Packit 63bb0d
			"spice-vdagent",
Packit 63bb0d
			"qemu-guest-agent",
Packit 63bb0d
			"xen-libs",
Packit 63bb0d
			"langpacks-en",
Packit 63bb0d
			"cloud-init",
Packit 63bb0d
			"libdrm",
Packit 63bb0d
		},
Packit 63bb0d
		excludedPackages: []string{
Packit 63bb0d
			"dracut-config-rescue",
Packit 63bb0d
		},
Packit 63bb0d
		enabledServices: []string{
Packit 63bb0d
			"cloud-init.service",
Packit 63bb0d
			"cloud-config.service",
Packit 63bb0d
			"cloud-final.service",
Packit 63bb0d
			"cloud-init-local.service",
Packit 63bb0d
		},
Packit 63bb0d
		kernelOptions: "ro biosdevname=0 net.ifnames=0",
Packit 63bb0d
		bootable:      true,
Packit 63bb0d
		defaultSize:   2 * GigaByte,
Packit 63bb0d
		assembler: func(uefi bool, options distro.ImageOptions, arch distro.Arch) *osbuild.Assembler {
Packit 63bb0d
			return qemuAssembler("qcow2", "disk.qcow2", uefi, options)
Packit 63bb0d
		},
Packit 63bb0d
	}
Packit 63bb0d
Packit 63bb0d
	vhdImgType := imageType{
Packit 63bb0d
		name:     "vhd",
Packit 63bb0d
		filename: "disk.vhd",
Packit 63bb0d
		mimeType: "application/x-vhd",
Packit 63bb0d
		packages: []string{
Packit 63bb0d
			"@Core",
Packit 63bb0d
			"chrony",
Packit 63bb0d
			"selinux-policy-targeted",
Packit 63bb0d
			"langpacks-en",
Packit 63bb0d
			"net-tools",
Packit 63bb0d
			"ntfsprogs",
Packit 63bb0d
			"WALinuxAgent",
Packit 63bb0d
			"libxcrypt-compat",
Packit 63bb0d
			"initscripts",
Packit 63bb0d
			"glibc-all-langpacks",
Packit 63bb0d
		},
Packit 63bb0d
		excludedPackages: []string{
Packit 63bb0d
			"dracut-config-rescue",
Packit 63bb0d
		},
Packit 63bb0d
		enabledServices: []string{
Packit 63bb0d
			"sshd",
Packit 63bb0d
			"waagent", // needed to run in Azure
Packit 63bb0d
		},
Packit 63bb0d
		disabledServices: []string{
Packit 63bb0d
			"proc-sys-fs-binfmt_misc.mount",
Packit 63bb0d
			"loadmodules.service",
Packit 63bb0d
		},
Packit 63bb0d
		// These kernel parameters are required by Azure documentation
Packit 63bb0d
		kernelOptions: "ro biosdevname=0 rootdelay=300 console=ttyS0 earlyprintk=ttyS0 net.ifnames=0",
Packit 63bb0d
		bootable:      true,
Packit 63bb0d
		defaultSize:   2 * GigaByte,
Packit 63bb0d
		assembler: func(uefi bool, options distro.ImageOptions, arch distro.Arch) *osbuild.Assembler {
Packit 63bb0d
			return qemuAssembler("vpc", "disk.vhd", uefi, options)
Packit 63bb0d
		},
Packit 63bb0d
	}
Packit 63bb0d
Packit 63bb0d
	vmdkImgType := imageType{
Packit 63bb0d
		name:     "vmdk",
Packit 63bb0d
		filename: "disk.vmdk",
Packit 63bb0d
		mimeType: "application/x-vmdk",
Packit 63bb0d
		packages: []string{
Packit 63bb0d
			"@core",
Packit 63bb0d
			"chrony",
Packit 63bb0d
			"firewalld",
Packit 63bb0d
			"langpacks-en",
Packit 63bb0d
			"open-vm-tools",
Packit 63bb0d
			"selinux-policy-targeted",
Packit 63bb0d
		},
Packit 63bb0d
		excludedPackages: []string{
Packit 63bb0d
			"dracut-config-rescue",
Packit 63bb0d
		},
Packit 63bb0d
		kernelOptions: "ro biosdevname=0 net.ifnames=0",
Packit 63bb0d
		bootable:      true,
Packit 63bb0d
		defaultSize:   2 * GigaByte,
Packit 63bb0d
		assembler: func(uefi bool, options distro.ImageOptions, arch distro.Arch) *osbuild.Assembler {
Packit 63bb0d
			return qemuAssembler("vmdk", "disk.vmdk", uefi, options)
Packit 63bb0d
		},
Packit 63bb0d
	}
Packit 63bb0d
Packit 63bb0d
	r := distribution{
Packit 63bb0d
		imageTypes: map[string]imageType{},
Packit 63bb0d
		buildPackages: []string{
Packit 63bb0d
			"dnf",
Packit 63bb0d
			"dosfstools",
Packit 63bb0d
			"e2fsprogs",
Packit 63bb0d
			"policycoreutils",
Packit 63bb0d
			"qemu-img",
Packit 63bb0d
			"selinux-policy-targeted",
Packit 63bb0d
			"systemd",
Packit 63bb0d
			"tar",
Packit 63bb0d
			"xz",
Packit 63bb0d
		},
Packit 63bb0d
	}
Packit 63bb0d
	x8664 := architecture{
Packit 63bb0d
		distro: &r,
Packit 63bb0d
		name:   "x86_64",
Packit 63bb0d
		bootloaderPackages: []string{
Packit 63bb0d
			"dracut-config-generic",
Packit 63bb0d
			"grub2-pc",
Packit 63bb0d
		},
Packit 63bb0d
		buildPackages: []string{
Packit 63bb0d
			"grub2-pc",
Packit 63bb0d
		},
Packit 63bb0d
		legacy: "i386-pc",
Packit 63bb0d
	}
Packit 63bb0d
	x8664.setImageTypes(
Packit 63bb0d
		iotImgType,
Packit 63bb0d
		amiImgType,
Packit 63bb0d
		qcow2ImageType,
Packit 63bb0d
		openstackImgType,
Packit 63bb0d
		vhdImgType,
Packit 63bb0d
		vmdkImgType,
Packit 63bb0d
	)
Packit 63bb0d
Packit 63bb0d
	aarch64 := architecture{
Packit 63bb0d
		distro: &r,
Packit 63bb0d
		name:   "aarch64",
Packit 63bb0d
		bootloaderPackages: []string{
Packit 63bb0d
			"dracut-config-generic",
Packit 63bb0d
			"efibootmgr",
Packit 63bb0d
			"grub2-efi-aa64",
Packit 63bb0d
			"grub2-tools",
Packit 63bb0d
			"shim-aa64",
Packit 63bb0d
		},
Packit 63bb0d
		uefi: true,
Packit 63bb0d
	}
Packit 63bb0d
	aarch64.setImageTypes(
Packit 63bb0d
		amiImgType,
Packit 63bb0d
		qcow2ImageType,
Packit 63bb0d
		openstackImgType,
Packit 63bb0d
	)
Packit 63bb0d
Packit 63bb0d
	r.setArches(x8664, aarch64)
Packit 63bb0d
Packit 63bb0d
	return &r
Packit 63bb0d
}