Commit: a95b833c
This commit is contained in:
jimmy committed 2022-08-23 20:51:43 -04:00
commit a8d8515b75
71 files changed
+6908

No files matched your search

+2
View File
@@ -0,0 +1,2 @@
*.json
!*.mpp.json
+212
View File
@@ -0,0 +1,212 @@
NULL=
EMPTY :=
SPACE := $(EMPTY) $(EMPTY)
COMMA := ,
ESCAPEDSPACE := \$(SPACE)
ESCAPEDSPACE_REPLACEMENT := @@SPACE@@
# This is useful to handle space in forech rules
handle-escaped-space = $(subst $(ESCAPEDSPACE),$(ESCAPEDSPACE_REPLACEMENT),$1)
apply-escaped-space = $(subst $(ESCAPEDSPACE_REPLACEMENT),$(SPACE),$1)
HOST_ARCH:=$(shell arch)
ARCHES := x86_64 aarch64
export VM=0
OSBUILD_MPP=osbuild-mpp
DEFINES=
DEFINES_ARGS:=$(foreach def,$(call handle-escaped-space,$(DEFINES)),-D '$(call apply-escaped-space,$(def))')
MPP_ARGS=
export OSBUILD_ARGS=
BUILDDIR=_build
export STOREDIR=$(BUILDDIR)/osbuild_store
export OUTPUTDIR=$(BUILDDIR)/image_output
IMAGEDIR=
DISTROS := $(basename $(basename $(notdir f,$(wildcard distro/*.ipp.yml))))
MANIFESTS := $(wildcard images/*.mpp.yml) $(foreach DIR,$(IMAGEDIR),$(wildcard $(DIR)/*))
EXTRA_MPP_ARGS= # For internal use
ifdef OSTREE_REPO
EXTRA_MPP_ARGS +=-D ostree_parent_refs='$(shell tools/ot-refs $(OSTREE_REPO))'
endif
export CHECKPOINTS=build
IMAGETYPES := regular ostree direct
FORMATS := img qcow2 oci.tar repo rootfs ext4 tar
aarch64_TARGETS := rpi4
COMMON_TARGETS := qemu aws
HOST_TARGETS := $(COMMON_TARGETS) $($(HOST_ARCH)_TARGETS)
ALL_TARGETS := $(COMMON_TARGETS) $(foreach a,$(ARCHES), $($(a)_TARGETS))
manifest-get-name = $(basename $(basename $(notdir $1)))
manifest-get-dir = $(notdir $(patsubst %/,%,$(dir $1)))
image-name-noarch = $1-$3-$(call manifest-get-name,$2)-$4
image-name = $(call image-name-noarch,$1,$2,$3,$4).$5
# variable name for image type
regular_IMAGETYPE := regular
ostree_IMAGETYPE := ostree
direct_IMAGETYPE := directboot
help:
@echo
@echo This makefile is a wrapper around osbuild-mpp and osbuild to easily build images
@echo
@echo To build a raw image, run \"make image.img\", or to build a qcow2 image, run \"make image.qcow2\".
@echo This will build any image from a file called \"image.mpp.yml\" in the \"images\" subdirectory. You can
@echo pass IMAGEDIR=/some/other/path to make also to pick up manifests from an external directory.
@echo
@echo For example, to build a minimal qcow2 image with ostree support targeting qemu, run:
@echo ' make cs9-qemu-minimal-ostree.$(HOST_ARCH).qcow2'
@echo
@echo Other extensions are also supported:
@echo \ \* .repo: Generate a repo with an ostree commit \(only works for ostree targets\)
@echo \ \* .rootfs: Generate a directory with the rootfs content
@echo \ \* .tar: Generate a tar file with the rootfs content
@echo \ \* .ext4: Generate an ext4 filesystem with the rootfs content \(size from \"image_size\"\)
@echo \ \* oci.tar: Generate an oci container image with the rootfs content
@echo
@echo You can pass variable declarations to osbuild-mpp with the DEFINES make variable.
@echo Multiple defines are separated by space, if you need a space inside a value escape it using \"\\ \".
@echo For example, to add extra rpms to a minimal regular image, use:
@echo " make cs9-qemu-minimal-regular.$(HOST_ARCH).qcow2 DEFINES='extra_rpms=[\"gdb\",\"strace\"]'"
@echo
@echo To easily run the image with qemu, you can use the included runvm tool, like:
@echo \ \ ./runvm cs9-qemu-minimal-regular.$(HOST_ARCH).qcow2
@echo
@echo There are some additional targets:
@echo \ \ manifests: generates resolved json manifests for all images without building them.
@echo \ \ clean_caches: Removes intermediate image build artifacts \(that improve rebuild speed\)
@echo \ \ clean_downloads: Removes files downloaded during image builds
@echo \ \ clean: Run clean_caches and clean_downloads
@echo \ \ osbuildvm-images: Build a image that can be used to build images inside a VM
@echo
@echo There are also some common conversion rules:
@echo \ \ foo.ext4.simg will build foo.ext4 and then convert it with img2simg
@echo \ \ foo.simg will build foo.img and then convert it with img2simg
@echo \ \ foo.tar.gz will build $foo.tar and then gzip it
@echo
@echo "When building a custom variant of an image (say with an extra package) you can use a"
@echo custom @suffix to change the name of the produced file. For example:
@echo " make cs9-qemu-minimal-ostree@gdb.$(HOST_ARCH).qcow2 DEFINES='extra_rpms=[\"gdb\"]'"
@echo
@echo If you pass VM=1, then the images used from \"make osbuildvm-images\" will be used to do the
@echo actual building. This means that you don\'t need sudo rights to run osbuild, and it means
@echo architectures other than the current ones can be built.
@echo
@echo Available image targets \(for $(HOST_ARCH)\) are:
@echo
@$(foreach d, $(DISTROS), $(foreach m, $(MANIFESTS), $(foreach t, $(HOST_TARGETS), $(foreach i,$(IMAGETYPES), echo -e " " $(call image-name,$d,$m,$t,$i,$(HOST_ARCH)).[$(subst $(SPACE),$(COMMA),$(FORMATS))];))))
@echo
# We pre-create all the toplevel dirs, so that they are owned by the user, not root (when created under sudo)
.PHONY: $(BUILDDIR)
$(BUILDDIR):
@mkdir -p $(BUILDDIR)
@mkdir -p $(STOREDIR)/{objects,refs,sources/org.osbuild.files,tmp}
@mkdir -p $(OUTPUTDIR)
# Template rule for producing osbuild json manifest from mpp yaml and image type
# $1 == distro name
# $2 == yaml manifest path
# $3 == Target name
# $4 == Image type
# $5 == Arch
define json-rule
$(BUILDDIR)/$(call image-name,$1,$2,$3,$4,$5).json: $2 $(BUILDDIR)
$(OSBUILD_MPP) -I . -D image_type="\"$($4_IMAGETYPE)\"" -D arch=\"$5\" -D distro_name="\"$1\"" -D target="\"$3\"" $(DEFINES_ARGS) $(EXTRA_MPP_ARGS) $(MPP_ARGS) $$< $$@
.PHONY: $(BUILDDIR)/$(call image-name,$1,$2,$3,$4,$5).json
endef
$(foreach d, $(DISTROS), \
$(foreach m, $(MANIFESTS), \
$(foreach a,$(ARCHES), \
$(foreach t,$(COMMON_TARGETS) $($(a)_TARGETS), \
$(foreach i,$(IMAGETYPES), \
$(eval $(call json-rule,$d,$m,$t,$i,$a)))))))
# Template rule for producing image from json manifest
# $1 == distro name
# $2 == Manifest path
# $3 == Target
# $4 == Image type
# $5 == Arch
# $6 == Export format (extension)
define image-rule
$(call image-name,$1,$2,$3,$4,$5).$6: $(BUILDDIR)/$(call image-name,$1,$2,$3,$4,$5).json
@tools/runosbuild "$$@" "$$<" "$3" "$4" "$5" "$6"
$(call image-name-noarch,$1,$2,$3,$4)@%.$5.$6: $(BUILDDIR)/$(call image-name,$1,$2,$3,$4,$5).json
@tools/runosbuild "$$@" "$$<" "$3" "$4" "$5" "$6"
endef
$(foreach d, $(DISTROS), \
$(foreach m, $(MANIFESTS), \
$(foreach a,$(ARCHES), \
$(foreach t, $(COMMON_TARGETS) $($(a)_TARGETS), \
$(foreach f,$(FORMATS), \
$(foreach i,$(IMAGETYPES), \
$(eval $(call image-rule,$d,$m,$t,$i,$a,$f))))))))
# Rule to pre-generate all manifests
manifests: $(foreach d, $(DISTROS),$(foreach m, $(MANIFESTS), $(foreach a,$(ARCHES), $(foreach t, $(COMMON_TARGETS) $($(a)_TARGETS), $(foreach i,$(IMAGETYPES), $(BUILDDIR)/$(call image-name,$d,$m,$t,$i,$a).json)))))
define packages-rule
.PHONY: packages-$(call manifest-get-name,$1).json
packages-$(call manifest-get-name,$1).json: $1
osbuild-mpp $$< -D arch=\"x86_64\" - | jq -f tools/extract-rpms.jq > $$@.x86_64
osbuild-mpp $$< -D arch=\"aarch64\" - | jq -f tools/extract-rpms.jq > $$@.aarch64
echo 1 | jq --indent 4 -f tools/create-packagelist.jq --slurpfile x86_64 $$@.x86_64 --slurpfile aarch64 $$@.aarch64 > $$@
endef
$(foreach m, $(MANIFESTS), $(eval $(call packages-rule,$m)))
.PHONY: clean_downloads
clean_downloads:
sudo rm -rf _build/osbuild_store/sources/org.osbuild.files/*
.PHONY: clean_caches
clean_caches:
sudo rm -rf $(STOREDIR)/refs/*
sudo rm -rf $(STOREDIR)/refs_tars/*
sudo rm -rf $(STOREDIR)/objects/*
sudo rm -rf $(STOREDIR)/tmp/*
sudo rm -rf $(STOREDIR)/image_output/*
.PHONY: clean
clean: clean_downloads clean_caches
ifeq ($(VM), 1)
VM_SUDO=
VM_OSBUILD="osbuildvm/osbuildvm --arch=$(HOST_ARCH)"
else
VM_SUDO=sudo
VM_OSBUILD=sudo osbuild
endif
.PHONY: osbuildvm-images
osbuildvm-images: $(BUILDDIR)
osbuild-mpp osbuildvm/osbuildvm.mpp.yml _build/osbuildvm-$(HOST_ARCH).json
$(VM_OSBUILD) --store $(STOREDIR) --output-directory $(OUTPUTDIR) --export osbuildvm _build/osbuildvm-$(HOST_ARCH).json
cp $(OUTPUTDIR)/osbuildvm/disk.qcow2 _build/osbuildvm-$(HOST_ARCH).img
cp $(OUTPUTDIR)/osbuildvm/initramfs _build/osbuildvm-$(HOST_ARCH).initramfs
cp $(OUTPUTDIR)/osbuildvm/vmlinuz _build/osbuildvm-$(HOST_ARCH).vmlinuz
$(VM_SUDO) rm -rf $(OUTPUTDIR)/osbuildvm
%.ext4.simg : %.ext4
img2simg $< $@
rm $<
%.simg : %.img
img2simg $< $@
rm $<
%.tar.gz : %.tar
gzip -f $<
+27
View File
@@ -0,0 +1,27 @@
version: '2'
mpp-vars:
distro_name: cs9
distro_version: 9
distro_baseurl: http://mirror.stream.centos.org/9-stream
distro_repos:
- id: baseos
baseurl: $distro_baseurl/BaseOS/$arch/os/
- id: appstream
baseurl: $distro_baseurl/AppStream/$arch/os/
- id: automotive
baseurl: https://buildlogs.centos.org/9-stream/automotive/$arch/packages-main/
- id: autosd
baseurl: https://buildlogs.centos.org/9-stream/autosd/$arch/packages-main/
distro_devel_repos:
- id: crb
baseurl: $distro_baseurl/CRB/$arch/os/
distro_debug_repos:
- id: baseos-debug
baseurl: $distro_baseurl/BaseOS/$arch/debug/tree/
- id: appstream-debug
baseurl: $distro_baseurl/AppStream/$arch/debug/tree/
- id: crb-debug
baseurl: $distro_baseurl/CRB/$arch/debug/tree/
- id: autosd-debug
baseurl: https://buildlogs.centos.org/9-stream/autosd/$arch/packages-main/debug/
distro_module_id: platform:el9
+14
View File
@@ -0,0 +1,14 @@
[Unit]
Description=Demo engine service container
Requires=routingmanagerd.socket
[Container]
Image=localhost/auto-apps
Volume=/run/vsomeip:/run/vsomeip
Exec=/usr/bin/engine-service
[Service]
Restart=always
[Install]
WantedBy=multi-user.target
@@ -0,0 +1,19 @@
## custom.conf
# GDM configuration storage
[daemon]
# Uncomment the line below to force the login screen to use Xorg
# WaylandEnable=false
AutomaticLoginEnable=True
AutomaticLogin=neptune
[security]
[xdmcp]
[chooser]
[debug]
# Uncomment the line below to turn on debugging
#Enable=true
@@ -0,0 +1,19 @@
## custom.conf
# GDM configuration storage
[daemon]
# Uncomment the line below to force the login screen to use Xorg
WaylandEnable=false
AutomaticLoginEnable=True
AutomaticLogin=neptune
[security]
[xdmcp]
[chooser]
[debug]
# Uncomment the line below to turn on debugging
#Enable=true
@@ -0,0 +1,14 @@
[Unit]
Description=Init neptune gdm session conf
ConditionPathExists=!/var/lib/AccountsService/users/neptune
Before=gdm.service
[Service]
Type=service
ExecStart=/bin/sh -c ' \
echo -e "[User]\nSession=neptune-%i\nXSession=neptune-xorg\nPasswordHint=\nIcon=/var/lib/AccountsService/icons/guest\nSystemAccount=false\n" \
> /var/lib/AccountsService/users/neptune'
RemainAfterExit=yes
[Install]
WantedBy=multi-user.target
+15
View File
@@ -0,0 +1,15 @@
[Unit]
Description=Demo radio service container
Requires=routingmanagerd.socket
Wants=engine.service
[Container]
Image=localhost/auto-apps
Volume=/run/vsomeip:/run/vsomeip
Exec=/usr/bin/radio-service
[Service]
Restart=always
[Install]
WantedBy=multi-user.target
+16
View File
@@ -0,0 +1,16 @@
[storage]
driver = "overlay"
runroot = "/run/containers/storage"
graphroot = "/var/lib/containers/storage"
[storage.options]
# We add a custom "/usr/share/containers/storage" here to allow readonly in-image containers
additionalimagestores = [
"/usr/share/containers/storage"
]
[storage.options.overlay]
# Nodev for security (default in cs9)
# We use metacopy to allow better pagecache sharing of base-layers (default in cs9)
mountopt = "nodev,metacopy=on"
@@ -0,0 +1,79 @@
formatVersion: 1
formatType: am-configuration
---
# basic AM functionality - the builtin apps are in 'apps'.
# installations will go into the standard QStandardPath AppLocalDataLocation
# (e.g. ~/.local/share/Luxoft Sweden AB/Neptune UI) /am hierarchy
applications:
builtinAppsManifestDir: "${CONFIG_PWD}/apps"
installedAppsManifestDir: "${stdpath:AppLocalDataLocation}/neptune3-ui/manifests"
installationDir: "${stdpath:AppLocalDataLocation}/neptune3-ui/apps"
documentDir: "${stdpath:AppLocalDataLocation}/neptune3-ui/docs"
# QML apps will be able to import from modules...
runtimes:
qml:
importPaths: [ "${CONFIG_PWD}/imports_shared" ]
environmentVariables:
QT_PLUGIN_PATH: "${CONFIG_PWD}"
SERVER_CONF_PATH: "${CONFIG_PWD}/server.conf"
native:
importPaths: [ "${CONFIG_PWD}/imports_shared" ]
environmentVariables:
QT_PLUGIN_PATH: "${CONFIG_PWD}"
SERVER_CONF_PATH: "${CONFIG_PWD}/server.conf"
# ... as well as the SystemUI
ui:
fullscreen: yes
style: "${CONFIG_PWD}/styles/neptune"
iconThemeName: "neptune"
iconThemeSearchPaths: [ "${CONFIG_PWD}/imports_shared/assets/icons" ]
mainQml: "${CONFIG_PWD}/Main.qml"
importPaths: [ "${CONFIG_PWD}/imports_shared", "${CONFIG_PWD}/imports_system", "${CONFIG_PWD}/sysui" ]
windowIcon: "${CONFIG_PWD}/imports_shared/assets/icons/neptune/sysui/ic-menu-home.png"
enableTouchEmulation: yes
systemProperties:
public:
showCluster: no
showHUD: no
devMode: yes
enableCursorManagement: no
hardwareVariant: 'high'
#Qt Safe Renderer settings
qsrEnabled: no
qsrServerAddress: '127.0.0.1'
qsrServerPort: '1111'
showSystemAppsInLauncher: no
private:
appStoreServerUrl: 'http://demoappsdeploy.qt.io:8514'
userName: 't'
userPassword: 't'
imei: '112163001487801'
orientation: 'Landscape'
adjustSizesForScreen: yes
# development setup: no security
flags:
noSecurity: yes
noUiWatchdog: yes
# default logging
logging:
rules:
- "*=false"
- "qt.*=false"
- "qt.gamepad*=true"
- "am.*=false"
- "qml*=true"
- "cursor.navigation=false"
- "qt3ds.*=false"
- "shared.com.pelagicore.map.info=false"
- "*.warning=false"
- "*.critical=true"
@@ -0,0 +1,7 @@
[Desktop Entry]
Type=Application
Exec=neptune3-ui
StartupNotify=false
Terminal=false
Name[en_US]=neptune3-ui
Comment[en_US]=Launches neptune3-ui on logging in
@@ -0,0 +1,7 @@
[Desktop Entry]
Type=Application
Exec=env QT_QPA_PLATFORM=wayland QT_IM_MODULE=qtvirtualkeyboard neptune3-ui
StartupNotify=false
Terminal=false
Name[en_US]=neptune3-ui
Comment[en_US]=Launches neptune3-ui on logging in
@@ -0,0 +1,3 @@
[GNOME Session]
Name=Neptune XOrg
RequiredComponents=mutter;neptune3-ui-xorg;
@@ -0,0 +1,3 @@
[GNOME Session]
Name=Neptune
RequiredComponents=mutter;neptune3-ui;
@@ -0,0 +1,7 @@
[Desktop Entry]
Name=Neptune (Wayland)
Comment=This session logs you into Neptune
Exec=gnome-session --session=neptune
Type=Application
DesktopNames=GNOME
X-GDM-SessionRegisters=true
@@ -0,0 +1,7 @@
[Desktop Entry]
Name=Neptune (XOrg)
Comment=This session logs you into Neptune
Exec=gnome-session --session=neptune-xorg
Type=Application
DesktopNames=GNOME
X-GDM-SessionRegisters=true
+121
View File
@@ -0,0 +1,121 @@
version: '2'
mpp-vars:
name: container
pipelines:
- mpp-import-pipelines:
path: include/build.ipp.yml
- name: rootfs
build: name:build
stages:
- type: org.osbuild.kernel-cmdline
options:
root_fs_uuid:
mpp-eval: rootfs_uuid
kernel_opts:
mpp-eval: ''' '' .join(kernel_opts)'
- type: org.osbuild.rpm
options:
gpgkeys:
- mpp-eval: centos_gpg_key
- mpp-eval: redhat_gpg_key
disable_dracut: true
inputs:
packages:
type: org.osbuild.files
origin: org.osbuild.source
mpp-depsolve:
architecture: $arch
ignore-weak-deps: true
module-platform-id: $distro_module_id
baseurl: $distro_baseurl/BaseOS/$arch/os/
repos:
mpp-join:
- mpp-eval: distro_repos
- mpp-eval: target_repos
- mpp-eval: extra_repos
- - id: copr-quadlet
baseurl: https://download.copr.fedorainfracloud.org/results/alexl/quadlet/centos-stream-9-$arch/
- - id: copr-sample-apps
baseurl: https://download.copr.fedorainfracloud.org/results/alexl/cs9-sample-images/centos-stream-9-$arch/
packages:
mpp-join:
- mpp-eval: base_rpms
- mpp-eval: image_rpms
- mpp-eval: extra_rpms
- - podman
- quadlet
- curl
- vsomeip3-routingmanager
- auto-apps
excludes:
- dracut-config-rescue
- type: org.osbuild.copy
inputs:
inlinefile:
type: org.osbuild.files
origin: org.osbuild.source
mpp-embed:
id: storage.conf
path: ../files/storage.conf
options:
paths:
- from:
mpp-format-string: input://inlinefile/{embedded['storage.conf']}
to: tree:///etc/containers/storage.conf
- type: org.osbuild.skopeo
inputs:
images:
type: org.osbuild.containers
origin: org.osbuild.source
mpp-resolve-images:
images:
- source: registry.gitlab.com/centos/automotive/sample-images/demo/auto-apps
tag: latest
name: localhost/auto-apps
options:
destination:
type: containers-storage
storage-path: /usr/share/containers/storage
- type: org.osbuild.mkdir
options:
paths:
- path: /etc/containers/systemd
parents: true
- type: org.osbuild.copy
inputs:
inlinefile:
type: org.osbuild.files
origin: org.osbuild.source
mpp-embed:
id: radio.container
path: ../files/radio.container
inlinefile2:
type: org.osbuild.files
origin: org.osbuild.source
mpp-embed:
id: engine.container
path: ../files/engine.container
options:
paths:
- from:
mpp-format-string: input://inlinefile/{embedded['radio.container']}
to: tree:///etc/containers/systemd/radio.container
- from:
mpp-format-string: input://inlinefile2/{embedded['engine.container']}
to: tree:///etc/containers/systemd/engine.container
- type: org.osbuild.locale
options:
language: en_US.UTF-8
- type: org.osbuild.users
options:
users:
guest:
password:
mpp-eval: guest_password
- type: org.osbuild.systemd
options:
enabled_services:
- NetworkManager.service
- rngd.service
- mpp-import-pipelines:
path: include/image.ipp.yml
+114
View File
@@ -0,0 +1,114 @@
version: '2'
mpp-vars:
name: developer
pipelines:
- mpp-import-pipelines:
path: include/build.ipp.yml
- name: rootfs
build: name:build
stages:
- type: org.osbuild.kernel-cmdline
options:
root_fs_uuid:
mpp-eval: rootfs_uuid
kernel_opts:
mpp-eval: ''' '' .join(kernel_opts)'
- type: org.osbuild.rpm
options:
gpgkeys:
- mpp-eval: centos_gpg_key
- mpp-eval: redhat_gpg_key
disable_dracut: true
exclude:
docs: true
inputs:
packages:
type: org.osbuild.files
origin: org.osbuild.source
mpp-depsolve:
architecture: $arch
ignore-weak-deps: true
module-platform-id: $distro_module_id
baseurl: $distro_baseurl/BaseOS/$arch/os/
repos:
mpp-join:
- mpp-eval: distro_repos
- mpp-eval: distro_devel_repos
- mpp-eval: target_repos
- mpp-eval: extra_repos
- - id: osbuild
baseurl: https://download.copr.fedorainfracloud.org/results/@osbuild/osbuild/centos-stream-9-$arch
packages:
mpp-join:
- mpp-eval: base_rpms
- mpp-eval: image_rpms
- mpp-eval: extra_rpms
- - "@Development Tools"
# Some convenience packages
- bash-completion
- dnf
- emacs-nox
- less
- strace
- sudo
- vim
- git
- wget
- make
# Dependencies to build RPMs and images
- rpm-build
- hostname
- openssl-devel
- bc
- binutils-devel
- bpftool
- clang
- dwarves
- gcc-plugin-devel
- libcap-devel
- libcap-ng-devel
- libmnl-devel
- llvm
- net-tools
- numactl-devel
- osbuild-ostree
- osbuild-tools
- openssh-clients
- openssh-server
- perl-devel
- python3-devel
- python3-docutils
- rsync
- iputils
- iproute
- qemu-kvm
- fuse-devel
- kernel-rpm-macros
# Container tools
- podman
- buildah
- skopeo
excludes:
- dracut-config-rescue
- type: org.osbuild.locale
options:
language: en_US.UTF-8
- type: org.osbuild.users
options:
users:
guest:
password:
mpp-eval: guest_password
- type: org.osbuild.sshd.config
options:
config:
PermitRootLogin:
mpp-eval: ssh_permit_root_login
- type: org.osbuild.systemd
options:
enabled_services:
- NetworkManager.service
- rngd.service
- sshd.service
- mpp-import-pipelines:
path: include/image.ipp.yml
Binary file not shown.
1 l�i�n�u�x�.�e�f�i�,�L�i�n�u�x�,�i�n�i�t�r�d�=�\�E�F�I�\�L�i�n�u�x�\�i�n�i�t�r�a�m�f�s�.�i�m�g�,�D�i�r�e�c�t� �k�e�r�n�e�l� �b�o�o�t�
2 �
@@ -0,0 +1,67 @@
# This image demontrates how to use an encrypted rootfs
# Due to the use of luks_auto_unlock, the passphrase is copied to the initrd and
# the rootfs uses this to automatically unlock the system on the first boot.
# However, the autosig-sample-tpm-enroll service is also installed, and this
# will replace the passphrase with a TPM based token, meaning that later
# boots are tied to this machine only.
# Remember to pass --tpm2 to runvm when testing this.
version: '2'
mpp-vars:
name: encrypted
use_luks: true
luks_auto_unlock: true
extra_boot_rpms:
- clevis-dracut
pipelines:
- mpp-import-pipelines:
path: include/build.ipp.yml
- name: rootfs
build: name:build
stages:
- type: org.osbuild.kernel-cmdline
options:
root_fs_uuid:
mpp-eval: rootfs_uuid
kernel_opts:
mpp-eval: ''' '' .join(kernel_opts)'
- type: org.osbuild.rpm
options:
gpgkeys:
- mpp-eval: centos_gpg_key
- mpp-eval: redhat_gpg_key
disable_dracut: true
exclude:
docs: true
inputs:
packages:
type: org.osbuild.files
origin: org.osbuild.source
mpp-depsolve:
architecture: $arch
ignore-weak-deps: true
module-platform-id: $distro_module_id
baseurl: $distro_baseurl/BaseOS/$arch/os/
repos:
mpp-join:
- mpp-eval: distro_repos
- mpp-eval: target_repos
- mpp-eval: extra_repos
packages:
mpp-join:
- mpp-eval: base_rpms
- mpp-eval: image_rpms
- mpp-eval: extra_rpms
# Install the tools and service files
- - autosig-sample-tpm-enroll
excludes:
- dracut-config-rescue
- type: org.osbuild.locale
options:
language: en_US.UTF-8
- type: org.osbuild.systemd
options:
enabled_services:
- NetworkManager.service
- rngd.service
- mpp-import-pipelines:
path: include/image.ipp.yml
+125
View File
@@ -0,0 +1,125 @@
version: '2'
mpp-vars:
name: gadget
image_size: '3221225472'
pipelines:
- mpp-import-pipelines:
path: include/build.ipp.yml
- name: rootfs
build: name:build
stages:
- type: org.osbuild.kernel-cmdline
options:
root_fs_uuid:
mpp-eval: rootfs_uuid
kernel_opts:
mpp-eval: ''' '' .join(kernel_opts)'
- type: org.osbuild.rpm
options:
gpgkeys:
- mpp-eval: centos_gpg_key
- mpp-eval: redhat_gpg_key
disable_dracut: true
exclude:
docs: true
inputs:
packages:
type: org.osbuild.files
origin: org.osbuild.source
mpp-depsolve:
architecture: $arch
ignore-weak-deps: true
module-platform-id: $distro_module_id
baseurl: $distro_baseurl/BaseOS/$arch/os/
repos:
mpp-join:
- mpp-eval: distro_repos
- mpp-eval: distro_devel_repos
- mpp-eval: target_repos
- mpp-eval: extra_repos
- - id: osbuild
baseurl: https://download.copr.fedorainfracloud.org/results/@osbuild/osbuild/centos-stream-9-$arch
packages:
mpp-join:
- mpp-eval: base_rpms
- mpp-eval: image_rpms
- mpp-eval: extra_rpms
- - "@Development Tools"
- firewalld
# Some convenience packages
- bash-completion
- dnf
- emacs-nox
- less
- strace
- sudo
- vim
- git
- wget
- make
# Dependencies to build RPMs and images
- rpm-build
- hostname
- openssl-devel
- bc
- binutils-devel
- bpftool
- clang
- dwarves
- gcc-plugin-devel
- libcap-devel
- libcap-ng-devel
- libmnl-devel
- llvm
- net-tools
- numactl-devel
- osbuild-ostree
- osbuild-tools
- openssh-clients
- openssh-server
- perl-devel
- python3-devel
- python3-docutils
- rsync
- iputils
- iproute
- qemu-kvm
- fuse-devel
- kernel-rpm-macros
# Container tools
- podman
- buildah
- skopeo
# Gadget
- pi_gadget
excludes:
- dracut-config-rescue
- type: org.osbuild.locale
options:
language: en_US.UTF-8
- type: org.osbuild.users
options:
users:
guest:
password:
mpp-eval: guest_password
- type: org.osbuild.firewall
options:
enabled_services:
- cockpit
- ssh
- type: org.osbuild.sshd.config
options:
config:
PermitRootLogin:
mpp-eval: ssh_permit_root_login
- type: org.osbuild.systemd
options:
enabled_services:
- NetworkManager.service
- firewalld.service
- rngd.service
- sshd.service
- cockpit.socket
- mpp-import-pipelines:
path: include/image.ipp.yml
+62
View File
@@ -0,0 +1,62 @@
version: '2'
mpp-vars:
name: minimal
pipelines:
- mpp-import-pipelines:
path: include/build.ipp.yml
- name: rootfs
build: name:build
stages:
- type: org.osbuild.kernel-cmdline
options:
root_fs_uuid:
mpp-eval: rootfs_uuid
kernel_opts:
mpp-eval: ''' '' .join(kernel_opts)'
- type: org.osbuild.rpm
options:
gpgkeys:
- mpp-eval: centos_gpg_key
- mpp-eval: redhat_gpg_key
disable_dracut: true
exclude:
docs: true
inputs:
packages:
type: org.osbuild.files
origin: org.osbuild.source
mpp-depsolve:
architecture: $arch
ignore-weak-deps: true
module-platform-id: $distro_module_id
baseurl: $distro_baseurl/BaseOS/$arch/os/
repos:
mpp-join:
- mpp-eval: distro_repos
- mpp-eval: target_repos
- mpp-eval: extra_repos
- []
packages:
mpp-join:
- mpp-eval: base_rpms
- mpp-eval: image_rpms
- mpp-eval: extra_rpms
- []
excludes:
- dracut-config-rescue
- type: org.osbuild.locale
options:
language: en_US.UTF-8
- type: org.osbuild.users
options:
users:
guest:
password:
mpp-eval: guest_password
- type: org.osbuild.systemd
options:
enabled_services:
- NetworkManager.service
- rngd.service
- mpp-import-pipelines:
path: include/image.ipp.yml
+206
View File
@@ -0,0 +1,206 @@
version: '2'
mpp-vars:
name: neptune
display_server: wayland
pipelines:
- mpp-import-pipelines:
path: include/build.ipp.yml
- name: rootfs
build: name:build
stages:
- type: org.osbuild.kernel-cmdline
options:
root_fs_uuid:
mpp-eval: rootfs_uuid
kernel_opts:
mpp-eval: ''' '' .join(kernel_opts)'
- type: org.osbuild.rpm
options:
gpgkeys:
- mpp-eval: centos_gpg_key
- mpp-eval: redhat_gpg_key
disable_dracut: true
exclude:
docs: true
inputs:
packages:
type: org.osbuild.files
origin: org.osbuild.source
mpp-depsolve:
architecture: $arch
ignore-weak-deps: true
module-platform-id: $distro_module_id
baseurl: $distro_baseurl/BaseOS/$arch/os/
repos:
mpp-join:
- mpp-eval: distro_repos
- mpp-eval: target_repos
- mpp-eval: extra_repos
- - id: copr-neptune
baseurl: https://download.copr.fedorainfracloud.org/results/pingou/qtappmanager-fedora/centos-stream-9-$arch/
packages:
mpp-join:
- mpp-eval: base_rpms
- mpp-eval: image_rpms
- mpp-eval: extra_rpms
- - dnf
- firewalld
- gdm
- gnome-control-center
- gnome-session-xsession
- gnome-shell
- gnome-terminal
- langpacks-en
- neptune3-ui
- openssh-clients
- openssh-server
- plymouth
- polkit
- sudo
- xorg-x11-drv-fbdev
excludes:
- dracut-config-rescue
- gnome-tour
- type: org.osbuild.locale
options:
language: en_US.UTF-8
- type: org.osbuild.users
options:
users:
guest:
password:
mpp-eval: guest_password
neptune:
password: ''
- type: org.osbuild.copy
inputs:
inlinefile:
type: org.osbuild.files
origin: org.osbuild.source
mpp-embed:
id: custom.conf
path: ../files/etc/gdm/custom-$display_server.conf
options:
paths:
- from:
mpp-format-string: input://inlinefile/{embedded['custom.conf']}
to: tree:///etc/gdm/custom.conf
- type: org.osbuild.copy
inputs:
inlinefile:
type: org.osbuild.files
origin: org.osbuild.source
mpp-embed:
id: init-neptune-session@.service
path: ../files/etc/systemd/system/init-neptune-session@.service
options:
paths:
- from:
mpp-format-string: input://inlinefile/{embedded['init-neptune-session@.service']}
to: tree:///etc/systemd/system/init-neptune-session@.service
- type: org.osbuild.copy
inputs:
inlinefile:
type: org.osbuild.files
origin: org.osbuild.source
mpp-embed:
id: neptune-wayland.desktop
path: ../files/usr/share/wayland-sessions/neptune-wayland.desktop
options:
paths:
- from:
mpp-format-string: input://inlinefile/{embedded['neptune-wayland.desktop']}
to: tree:///usr/share/wayland-sessions/neptune-wayland.desktop
- type: org.osbuild.copy
inputs:
inlinefile:
type: org.osbuild.files
origin: org.osbuild.source
mpp-embed:
id: neptune-xorg.desktop
path: ../files/usr/share/xsessions/neptune-xorg.desktop
options:
paths:
- from:
mpp-format-string: input://inlinefile/{embedded['neptune-xorg.desktop']}
to: tree:///usr/share/xsessions/neptune-xorg.desktop
- type: org.osbuild.copy
inputs:
inlinefile:
type: org.osbuild.files
origin: org.osbuild.source
mpp-embed:
id: neptune.session
path: ../files/usr/share/gnome-session/sessions/neptune.session
options:
paths:
- from:
mpp-format-string: input://inlinefile/{embedded['neptune.session']}
to: tree:///usr/share/gnome-session/sessions/neptune.session
- type: org.osbuild.copy
inputs:
inlinefile:
type: org.osbuild.files
origin: org.osbuild.source
mpp-embed:
id: neptune-xorg.session
path: ../files/usr/share/gnome-session/sessions/neptune-xorg.session
options:
paths:
- from:
mpp-format-string: input://inlinefile/{embedded['neptune-xorg.session']}
to: tree:///usr/share/gnome-session/sessions/neptune-xorg.session
- type: org.osbuild.copy
inputs:
inlinefile:
type: org.osbuild.files
origin: org.osbuild.source
mpp-embed:
id: am-config-neptune.yaml
path: ../files/usr/lib64/neptune3/am-config-neptune.yaml
options:
paths:
- from:
mpp-format-string: input://inlinefile/{embedded['am-config-neptune.yaml']}
to: tree:///usr/lib64/neptune3/am-config-neptune.yaml
- type: org.osbuild.copy
inputs:
inlinefile:
type: org.osbuild.files
origin: org.osbuild.source
mpp-embed:
id: neptune3-ui.desktop
path: ../files/usr/share/applications/neptune3-ui.desktop
options:
paths:
- from:
mpp-format-string: input://inlinefile/{embedded['neptune3-ui.desktop']}
to: tree:///usr/share/applications/neptune3-ui.desktop
- type: org.osbuild.copy
inputs:
inlinefile:
type: org.osbuild.files
origin: org.osbuild.source
mpp-embed:
id: neptune3-ui-xorg.desktop
path: ../files/usr/share/applications/neptune3-ui-xorg.desktop
options:
paths:
- from:
mpp-format-string: input://inlinefile/{embedded['neptune3-ui-xorg.desktop']}
to: tree:///usr/share/applications/neptune3-ui-xorg.desktop
- type: org.osbuild.sshd.config
options:
config:
PermitRootLogin:
mpp-eval: ssh_permit_root_login
- type: org.osbuild.systemd
options:
enabled_services:
- NetworkManager.service
- firewalld.service
- rngd.service
- sshd.service
- mpp-eval: "'init-neptune-session@wayland.service' if display_server == 'wayland' else 'init-neptune-session@xorg.service'"
- mpp-import-pipelines:
path: include/image.ipp.yml
+46
View File
@@ -0,0 +1,46 @@
version: '2'
mpp-vars:
name: soafee
pipelines:
- mpp-import-pipelines:
path: include/build.ipp.yml
- name: rootfs
build: name:build
stages:
- type: org.osbuild.kernel-cmdline
options:
root_fs_uuid:
mpp-eval: rootfs_uuid
kernel_opts:
mpp-eval: ''' '' .join(kernel_opts)'
- type: org.osbuild.rpm
options:
gpgkeys:
- mpp-eval: centos_gpg_key
- mpp-eval: redhat_gpg_key
disable_dracut: true
inputs:
packages:
type: org.osbuild.files
origin: org.osbuild.source
mpp-depsolve:
architecture: $arch
ignore-weak-deps: true
module-platform-id: $distro_module_id
baseurl: $distro_baseurl/BaseOS/$arch/os/
repos:
mpp-join:
- mpp-eval: distro_repos
- mpp-eval: target_repos
- mpp-eval: extra_repos
packages:
mpp-join:
- mpp-eval: base_rpms
- mpp-eval: image_rpms
- mpp-eval: extra_rpms
- - podman
- curl
excludes:
- dracut-config-rescue
- mpp-import-pipelines:
path: include/image.ipp.yml
@@ -0,0 +1,79 @@
version: '2'
mpp-vars:
name: upgrade-demo
pipelines:
- mpp-import-pipelines:
path: include/build.ipp.yml
- name: rootfs
build: name:build
stages:
- type: org.osbuild.kernel-cmdline
options:
root_fs_uuid:
mpp-eval: rootfs_uuid
kernel_opts:
mpp-eval: ''' '' .join(kernel_opts)'
- type: org.osbuild.rpm
options:
gpgkeys:
- mpp-eval: centos_gpg_key
- mpp-eval: redhat_gpg_key
disable_dracut: true
exclude:
docs: true
inputs:
packages:
type: org.osbuild.files
origin: org.osbuild.source
mpp-depsolve:
architecture: $arch
ignore-weak-deps: true
module-platform-id: $distro_module_id
baseurl: $distro_baseurl/BaseOS/$arch/os/
repos:
mpp-join:
- mpp-eval: distro_repos
- mpp-eval: target_repos
- mpp-eval: extra_repos
packages:
mpp-join:
- mpp-eval: base_rpms
- mpp-eval: image_rpms
- mpp-eval: extra_rpms
# Install the watchdog tools and service files
- - autosig-sample-watchdog
- autosig-sample-staticdelta
excludes:
- dracut-config-rescue
# Make sure we only try a failed boot once before rollback (default is 3)
- type: org.osbuild.copy
inputs:
inlinefile:
type: org.osbuild.files
origin: org.osbuild.source
mpp-embed:
id: greenboot.conf
text: "GREENBOOT_MAX_BOOT_ATTEMPTS=1\n"
options:
paths:
- from:
mpp-format-string: input://inlinefile/{embedded['greenboot.conf']}
to: tree:///etc/greenboot/greenboot.conf
- type: org.osbuild.locale
options:
language: en_US.UTF-8
- type: org.osbuild.systemd
options:
enabled_services:
- NetworkManager.service
- rngd.service
# Enable the watchdog ostree/greenboot integration
- watchdog-ostree-start.service
- watchdog-ostree-stop.service
# Work around bug for now (https://github.com/coreos/rpm-ostree/issues/3554)
- type: org.osbuild.mkdir
options:
paths:
- path: /var/lib/containers
- mpp-import-pipelines:
path: include/image.ipp.yml
@@ -0,0 +1,45 @@
version: '2'
mpp-vars:
efiarch: aa64
boot_rpms:
mpp-join:
- mpp-eval: boot_rpms
- - grub2-efi-aa64
base_rpms:
mpp-join:
- mpp-eval: base_rpms
- []
pipelines:
- name: build
runner: org.osbuild.centos9
stages:
- type: org.osbuild.rpm
inputs:
packages:
type: org.osbuild.files
origin: org.osbuild.source
mpp-depsolve:
architecture: $arch
module-platform-id: $distro_module_id
baseurl: $distro_baseurl/BaseOS/$arch/os/
repos:
mpp-eval: distro_repos
packages:
mpp-join:
- mpp-eval: build_rpms
- mpp-eval: extra_build_rpms
- - grub2-efi-aa64
- grub2-efi-aa64-cdboot
- shim-aa64
options:
gpgkeys:
- mpp-eval: centos_gpg_key
- mpp-eval: redhat_gpg_key
exclude:
docs: true
- type: org.osbuild.selinux
options:
file_contexts: etc/selinux/targeted/contexts/files/file_contexts
labels:
/usr/bin/cp: system_u:object_r:install_exec_t:s0
/usr/bin/tar: system_u:object_r:install_exec_t:s0
@@ -0,0 +1,46 @@
version: '2'
mpp-vars:
efiarch: x64
boot_rpms:
mpp-join:
- mpp-eval: boot_rpms
- - grub2-efi-x64
base_rpms:
mpp-join:
- mpp-eval: base_rpms
- - microcode_ctl
pipelines:
- name: build
runner: org.osbuild.centos9
stages:
- type: org.osbuild.rpm
inputs:
packages:
type: org.osbuild.files
origin: org.osbuild.source
mpp-depsolve:
architecture: $arch
module-platform-id: $distro_module_id
baseurl: $distro_baseurl/BaseOS/$arch/os/
repos:
mpp-eval: distro_repos
packages:
mpp-join:
- mpp-eval: build_rpms
- mpp-eval: extra_build_rpms
- - grub2-efi-x64
- grub2-efi-x64-cdboot
- grub2-tools-efi
- shim-x64
options:
gpgkeys:
- mpp-eval: centos_gpg_key
- mpp-eval: redhat_gpg_key
exclude:
docs: true
- type: org.osbuild.selinux
options:
file_contexts: etc/selinux/targeted/contexts/files/file_contexts
labels:
/usr/bin/cp: system_u:object_r:install_exec_t:s0
/usr/bin/tar: system_u:object_r:install_exec_t:s0
+38
View File
@@ -0,0 +1,38 @@
version: '2'
mpp-vars:
distro_name: cs9 # The default
mpp-define-image:
size: $image_size
table:
uuid: $parttab_uuid
label: $partition_label
partitions:
- id: efi
start:
mpp-eval: "0 if partition_label == 'gpt' else 2048"
size: $efipart_size
type:
mpp-eval: "'C12A7328-F81F-11D2-BA4B-00A0C93EC93B' if partition_label == 'gpt' else 'ef'"
uuid: $efipart_uuid
- id: boot
size: $bootpart_size
type:
mpp-eval: "'0FC63DAF-8483-4772-8E79-3D69D8477DE4' if partition_label == 'gpt' else '83'"
uuid: $bootpart_uuid
- id: root
type:
mpp-eval: "'0FC63DAF-8483-4772-8E79-3D69D8477DE4' if partition_label == 'gpt' else '83'"
uuid: $rootpart_uuid
pipelines:
- mpp-import-pipelines:
path: distro/$distro_name.ipp.yml
- mpp-import-pipelines:
path: defaults.ipp.yml
- mpp-import-pipelines:
path: target-$target.ipp.yml
- mpp-import-pipeline:
path: build-$arch.ipp.yml
id: build
runner: org.osbuild.centos9
+315
View File
@@ -0,0 +1,315 @@
version: '2'
mpp-vars:
default_target: qemu
default_image_type: ostree
default_ostree_ref: $distro_name/$arch/$target-$name
default_ostree_os_version: $distro_version
default_osname: centos
default_uefi_vendor: centos
default_kernel_rpm: kernel-automotive
default_linux_firmware_rpm: linux-firmware-automotive
default_partition_label: gpt
default_extra_rpms: []
default_extra_build_rpms: []
default_extra_repos: []
default_target_repos: []
default_root_password: $6$xoLqEUz0cGGJRx01$H3H/bFm0myJPULNMtbSsOFd/2BnHqHkMD92Sfxd.EKM9hXTWSmELG8cf205l6dktomuTcgKGGtGDgtvHVXSWU.
default_guest_password: $6$xoLqEUz0cGGJRx01$H3H/bFm0myJPULNMtbSsOFd/2BnHqHkMD92Sfxd.EKM9hXTWSmELG8cf205l6dktomuTcgKGGtGDgtvHVXSWU.
default_root_ssh_key: ""
default_ssh_permit_root_login: false
default_image_size: '8589934592'
default_efipart_size: 204800
default_bootpart_size: 614400
default_kernel_loglevel: 4
static_uuids:
mpp-eval: locals().get('static_uuids', True)
default_rootfs_uuid:
mpp-eval: ('76a22bf4-f153-4541-b6c7-0332c0dfaeac' if static_uuids else str(__import__('uuid').uuid4()))
default_bootfs_uuid:
mpp-eval: ('156f0420-627b-4151-ae6f-fda298097515' if static_uuids else str(__import__('uuid').uuid4()))
default_parttab_uuid:
mpp-eval: ('d209c89e-ea5e-4fbd-b161-b461cce297e0' if static_uuids else str(__import__('uuid').uuid4()))
default_efipart_uuid:
mpp-eval: ('68b2905b-df3e-4fb3-80fa-49d1e773aa33' if static_uuids else str(__import__('uuid').uuid4()))
default_bootpart_uuid:
mpp-eval: ('61b2905b-df3e-4fb3-80fa-49d1e773aa32' if static_uuids else str(__import__('uuid').uuid4()))
default_rootpart_uuid:
mpp-eval: ('6264d520-3fb9-423f-8ab8-7a0a8e3d3562' if static_uuids else str(__import__('uuid').uuid4()))
default_luks_uuid:
mpp-eval: ('aedd1eef-f24e-425e-a9f3-bb5a1c996a95' if static_uuids else str(__import__('uuid').uuid4()))
default_use_luks: false
use_luks:
mpp-eval: locals().get('use_luks', default_use_luks)
default_luks_use_integrity: false
default_luks_auto_unlock: false
luks_auto_unlock:
mpp-eval: locals().get('luks_auto_unlock', default_luks_auto_unlock)
default_use_efi_runtime: true
default_kernel_opts:
- console=tty0
- console=ttyS0
- systemd.log_target=console
- systemd.journald.forward_to_console=1
default_dracut_add_modules:
- base
- bash
- dracut-systemd
- fs-lib
- i18n
- kernel-modules
- kernel-modules-extra
- rootfs-block
- shutdown
- systemd
- systemd-initrd
- terminfo
- udev-rules
- usrmount
default_dracut_omit_modules:
- mpp-if: not use_luks
then: dm
- lunmask
- mdraid
- memstrack
- nss-softokn
- nvdimm
- resume
- terminfo
default_dracut_filesystems:
- vfat
- ext4
default_dracut_add_drivers: []
default_dracut_install: []
default_ostree_repo_url: http://10.0.2.100/
default_ostree_remote_name: auto-sig
default_luks_passphrase: password
target:
mpp-eval: locals().get('target', default_target)
image_type:
mpp-eval: locals().get('image_type', default_image_type)
kernel_rpm:
mpp-eval: locals().get('kernel_rpm', default_kernel_rpm)
linux_firmware_rpm:
mpp-eval: locals().get('linux_firmware_rpm', default_linux_firmware_rpm)
ostree_ref:
mpp-eval: locals().get('ostree_ref', default_ostree_ref)
ostree_os_version:
mpp-eval: locals().get('ostree_os_version', default_ostree_os_version)
osname:
mpp-eval: locals().get('osname', default_osname)
uefi_vendor:
mpp-eval: locals().get('uefi_vendor', default_uefi_vendor)
partition_label:
mpp-eval: locals().get('partition_label', default_partition_label)
extra_rpms:
mpp-eval: locals().get('extra_rpms', default_extra_rpms)
extra_build_rpms:
mpp-eval: locals().get('extra_build_rpms', default_extra_build_rpms)
extra_repos:
mpp-eval: locals().get('extra_repos', default_extra_repos)
target_repos:
mpp-eval: locals().get('target_repos', default_target_repos)
image_size:
mpp-eval: locals().get('image_size', default_image_size)
rootfs_uuid:
mpp-eval: locals().get('rootfs_uuid', default_rootfs_uuid)
bootfs_uuid:
mpp-eval: locals().get('bootfs_uuid', default_bootfs_uuid)
parttab_uuid:
mpp-eval: locals().get('parttab_uuid', default_parttab_uuid)
rootpart_uuid:
mpp-eval: locals().get('rootpart_uuid', default_rootpart_uuid)
bootpart_uuid:
mpp-eval: locals().get('bootpart_uuid', default_bootpart_uuid)
efipart_uuid:
mpp-eval: locals().get('efipart_uuid', default_efipart_uuid)
luks_uuid:
mpp-eval: locals().get('luks_uuid', default_luks_uuid)
kernel_opts:
mpp-eval: locals().get('kernel_opts', default_kernel_opts)
efipart_size:
mpp-eval: locals().get('efipart_size', default_efipart_size)
bootpart_size:
mpp-eval: locals().get('bootpart_size', default_bootpart_size)
dracut_add_modules:
mpp-eval: locals().get('dracut_add_modules', default_dracut_add_modules)
dracut_omit_modules:
mpp-eval: locals().get('dracut_omit_modules', default_dracut_omit_modules)
dracut_filesystems:
mpp-eval: locals().get('dracut_filesystems', default_dracut_filesystems)
dracut_add_drivers:
mpp-eval: locals().get('dracut_add_drivers', default_dracut_add_drivers)
dracut_install:
mpp-eval: locals().get('dracut_install', default_dracut_install)
root_password:
mpp-eval: locals().get('root_password', default_root_password)
root_ssh_key:
mpp-eval: locals().get('root_ssh_key', default_root_ssh_key)
ssh_permit_root_login:
mpp-eval: locals().get('ssh_permit_root_login', default_ssh_permit_root_login)
guest_password:
mpp-eval: locals().get('guest_password', default_guest_password)
ostree_repo_url:
mpp-eval: locals().get('ostree_repo_url', default_ostree_repo_url)
ostree_remote_name:
mpp-eval: locals().get('ostree_remote_name', default_ostree_remote_name)
luks_passphrase:
mpp-eval: locals().get('luks_passphrase', default_luks_passphrase)
luks_use_integrity:
mpp-eval: locals().get('luks_use_integrity', default_luks_use_integrity)
use_efi_runtime:
mpp-eval: locals().get('use_efi_runtime', default_use_efi_runtime)
kernel_loglevel:
mpp-eval: locals().get('kernel_loglevel', default_kernel_loglevel)
default_target_stages: []
target_stages:
mpp-eval: locals().get('target_stages', default_target_stages)
centos_gpg_key: |
-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: GnuPG v2.0.22 (GNU/Linux)
mQINBFzMWxkBEADHrskpBgN9OphmhRkc7P/YrsAGSvvl7kfu+e9KAaU6f5MeAVyn
rIoM43syyGkgFyWgjZM8/rur7EMPY2yt+2q/1ZfLVCRn9856JqTIq0XRpDUe4nKQ
8BlA7wDVZoSDxUZkSuTIyExbDf0cpw89Tcf62Mxmi8jh74vRlPy1PgjWL5494b3X
5fxDidH4bqPZyxTBqPrUFuo+EfUVEqiGF94Ppq6ZUvrBGOVo1V1+Ifm9CGEK597c
aevcGc1RFlgxIgN84UpuDjPR9/zSndwJ7XsXYvZ6HXcKGagRKsfYDWGPkA5cOL/e
f+yObOnC43yPUvpggQ4KaNJ6+SMTZOKikM8yciyBwLqwrjo8FlJgkv8Vfag/2UR7
JINbyqHHoLUhQ2m6HXSwK4YjtwidF9EUkaBZWrrskYR3IRZLXlWqeOi/+ezYOW0m
vufrkcvsh+TKlVVnuwmEPjJ8mwUSpsLdfPJo1DHsd8FS03SCKPaXFdD7ePfEjiYk
nHpQaKE01aWVSLUiygn7F7rYemGqV9Vt7tBw5pz0vqSC72a5E3zFzIIuHx6aANry
Gat3aqU3qtBXOrA/dPkX9cWE+UR5wo/A2UdKJZLlGhM2WRJ3ltmGT48V9CeS6N9Y
m4CKdzvg7EWjlTlFrd/8WJ2KoqOE9leDPeXRPncubJfJ6LLIHyG09h9kKQARAQAB
tDpDZW50T1MgKENlbnRPUyBPZmZpY2lhbCBTaWduaW5nIEtleSkgPHNlY3VyaXR5
QGNlbnRvcy5vcmc+iQI3BBMBAgAhBQJczFsZAhsDBgsJCAcDAgYVCAIJCgsDFgIB
Ah4BAheAAAoJEAW1VbOEg8ZdjOsP/2ygSxH9jqffOU9SKyJDlraL2gIutqZ3B8pl
Gy/Qnb9QD1EJVb4ZxOEhcY2W9VJfIpnf3yBuAto7zvKe/G1nxH4Bt6WTJQCkUjcs
N3qPWsx1VslsAEz7bXGiHym6Ay4xF28bQ9XYIokIQXd0T2rD3/lNGxNtORZ2bKjD
vOzYzvh2idUIY1DgGWJ11gtHFIA9CvHcW+SMPEhkcKZJAO51ayFBqTSSpiorVwTq
a0cB+cgmCQOI4/MY+kIvzoexfG7xhkUqe0wxmph9RQQxlTbNQDCdaxSgwbF2T+gw
byaDvkS4xtR6Soj7BKjKAmcnf5fn4C5Or0KLUqMzBtDMbfQQihn62iZJN6ZZ/4dg
q4HTqyVpyuzMXsFpJ9L/FqH2DJ4exGGpBv00ba/Zauy7GsqOc5PnNBsYaHCply0X
407DRx51t9YwYI/ttValuehq9+gRJpOTTKp6AjZn/a5Yt3h6jDgpNfM/EyLFIY9z
V6CXqQQ/8JRvaik/JsGCf+eeLZOw4koIjZGEAg04iuyNTjhx0e/QHEVcYAqNLhXG
rCTTbCn3NSUO9qxEXC+K/1m1kaXoCGA0UWlVGZ1JSifbbMx0yxq/brpEZPUYm+32
o8XfbocBWljFUJ+6aljTvZ3LQLKTSPW7TFO+GXycAOmCGhlXh2tlc6iTc41PACqy
yy+mHmSv
=kkH7
-----END PGP PUBLIC KEY BLOCK-----
redhat_gpg_key: |
-----BEGIN PGP PUBLIC KEY BLOCK-----
mQINBErgSTsBEACh2A4b0O9t+vzC9VrVtL1AKvUWi9OPCjkvR7Xd8DtJxeeMZ5eF
0HtzIG58qDRybwUe89FZprB1ffuUKzdE+HcL3FbNWSSOXVjZIersdXyH3NvnLLLF
0DNRB2ix3bXG9Rh/RXpFsNxDp2CEMdUvbYCzE79K1EnUTVh1L0Of023FtPSZXX0c
u7Pb5DI5lX5YeoXO6RoodrIGYJsVBQWnrWw4xNTconUfNPk0EGZtEnzvH2zyPoJh
XGF+Ncu9XwbalnYde10OCvSWAZ5zTCpoLMTvQjWpbCdWXJzCm6G+/hx9upke546H
5IjtYm4dTIVTnc3wvDiODgBKRzOl9rEOCIgOuGtDxRxcQkjrC+xvg5Vkqn7vBUyW
9pHedOU+PoF3DGOM+dqv+eNKBvh9YF9ugFAQBkcG7viZgvGEMGGUpzNgN7XnS1gj
/DPo9mZESOYnKceve2tIC87p2hqjrxOHuI7fkZYeNIcAoa83rBltFXaBDYhWAKS1
PcXS1/7JzP0ky7d0L6Xbu/If5kqWQpKwUInXtySRkuraVfuK3Bpa+X1XecWi24JY
HVtlNX025xx1ewVzGNCTlWn1skQN2OOoQTV4C8/qFpTW6DTWYurd4+fE0OJFJZQF
buhfXYwmRlVOgN5i77NTIJZJQfYFj38c/Iv5vZBPokO6mffrOTv3MHWVgQARAQAB
tDNSZWQgSGF0LCBJbmMuIChyZWxlYXNlIGtleSAyKSA8c2VjdXJpdHlAcmVkaGF0
LmNvbT6JAjYEEwECACAFAkrgSTsCGwMGCwkIBwMCBBUCCAMEFgIDAQIeAQIXgAAK
CRAZni+R/UMdUWzpD/9s5SFR/ZF3yjY5VLUFLMXIKUztNN3oc45fyLdTI3+UClKC
2tEruzYjqNHhqAEXa2sN1fMrsuKec61Ll2NfvJjkLKDvgVIh7kM7aslNYVOP6BTf
C/JJ7/ufz3UZmyViH/WDl+AYdgk3JqCIO5w5ryrC9IyBzYv2m0HqYbWfphY3uHw5
un3ndLJcu8+BGP5F+ONQEGl+DRH58Il9Jp3HwbRa7dvkPgEhfFR+1hI+Btta2C7E
0/2NKzCxZw7Lx3PBRcU92YKyaEihfy/aQKZCAuyfKiMvsmzs+4poIX7I9NQCJpyE
IGfINoZ7VxqHwRn/d5mw2MZTJjbzSf+Um9YJyA0iEEyD6qjriWQRbuxpQXmlAJbh
8okZ4gbVFv1F8MzK+4R8VvWJ0XxgtikSo72fHjwha7MAjqFnOq6eo6fEC/75g3NL
Ght5VdpGuHk0vbdENHMC8wS99e5qXGNDued3hlTavDMlEAHl34q2H9nakTGRF5Ki
JUfNh3DVRGhg8cMIti21njiRh7gyFI2OccATY7bBSr79JhuNwelHuxLrCFpY7V25
OFktl15jZJaMxuQBqYdBgSay2G0U6D1+7VsWufpzd/Abx1/c3oi9ZaJvW22kAggq
dzdA27UUYjWvx42w9menJwh/0jeQcTecIUd0d0rFcw/c1pvgMMl/Q73yzKgKYw==
=zbHE
-----END PGP PUBLIC KEY BLOCK-----
-----BEGIN PGP PUBLIC KEY BLOCK-----
mQINBFsy23UBEACUKSphFEIEvNpy68VeW4Dt6qv+mU6am9a2AAl10JANLj1oqWX+
oYk3en1S6cVe2qehSL5DGVa3HMUZkP3dtbD4SgzXzxPodebPcr4+0QNWigkUisri
XGL5SCEcOP30zDhZvg+4mpO2jMi7Kc1DLPzBBkgppcX91wa0L1pQzBcvYMPyV/Dh
KbQHR75WdkP6OA2JXdfC94nxYq+2e0iPqC1hCP3Elh+YnSkOkrawDPmoB1g4+ft/
xsiVGVy/W0ekXmgvYEHt6si6Y8NwXgnTMqxeSXQ9YUgVIbTpsxHQKGy76T5lMlWX
4LCOmEVomBJg1SqF6yi9Vu8TeNThaDqT4/DddYInd0OO69s0kGIXalVgGYiW2HOD
x2q5R1VGCoJxXomz+EbOXY+HpKPOHAjU0DB9MxbU3S248LQ69nIB5uxysy0PSco1
sdZ8sxRNQ9Dw6on0Nowx5m6Thefzs5iK3dnPGBqHTT43DHbnWc2scjQFG+eZhe98
Ell/kb6vpBoY4bG9/wCG9qu7jj9Z+BceCNKeHllbezVLCU/Hswivr7h2dnaEFvPD
O4GqiWiwOF06XaBMVgxA8p2HRw0KtXqOpZk+o+sUvdPjsBw42BB96A1yFX4jgFNA
PyZYnEUdP6OOv9HSjnl7k/iEkvHq/jGYMMojixlvXpGXhnt5jNyc4GSUJQARAQAB
tDNSZWQgSGF0LCBJbmMuIChhdXhpbGlhcnkga2V5KSA8c2VjdXJpdHlAcmVkaGF0
LmNvbT6JAjkEEwECACMFAlsy23UCGwMHCwkIBwMCAQYVCAIJCgsEFgIDAQIeAQIX
gAAKCRD3b2bD1AgnknqOD/9fB2ASuG2aJIiap4kK58R+RmOVM4qgclAnaG57+vjI
nKvyfV3NH/keplGNRxwqHekfPCqvkpABwhdGEXIE8ILqnPewIMr6PZNZWNJynZ9i
eSMzVuCG7jDoGyQ5/6B0f6xeBtTeBDiRl7+Alehet1twuGL1BJUYG0QuLgcEzkaE
/gkuumeVcazLzz7L12D22nMk66GxmgXfqS5zcbqOAuZwaA6VgSEgFdV2X2JU79zS
BQJXv7NKc+nDXFG7M7EHjY3Rma3HXkDbkT8bzh9tJV7Z7TlpT829pStWQyoxKCVq
sEX8WsSapTKA3P9YkYCwLShgZu4HKRFvHMaIasSIZWzLu+RZH/4yyHOhj0QB7XMY
eHQ6fGSbtJ+K6SrpHOOsKQNAJ0hVbSrnA1cr5+2SDfel1RfYt0W9FA6DoH/S5gAR
dzT1u44QVwwp3U+eFpHphFy//uzxNMtCjjdkpzhYYhOCLNkDrlRPb+bcoL/6ePSr
016PA7eEnuC305YU1Ml2WcCn7wQV8x90o33klJmEkWtXh3X39vYtI4nCPIvZn1eP
Vy+F+wWt4vN2b8oOdlzc2paOembbCo2B+Wapv5Y9peBvlbsDSgqtJABfK8KQq/jK
Yl3h5elIa1I3uNfczeHOnf1enLOUOlq630yeM/yHizz99G1g+z/guMh5+x/OHraW
iA==
=+Gxh
-----END PGP PUBLIC KEY BLOCK-----
fstab:
- uuid:
mpp-eval: rootfs_uuid
vfs_type: ext4
path: /
freq: 1
passno: 1
- label: ESP
vfs_type: vfat
path: /boot/efi
freq: 1
passno: 1
- uuid:
mpp-eval: bootfs_uuid
vfs_type: ext4
path: /boot
freq: 1
passno: 1
build_rpms:
- mpp-if: use_luks
then: cryptsetup
- dnf
- dosfstools
- e2fsprogs
- efibootmgr
- grub2-tools
- grub2-tools-minimal
- mpp-if: use_luks
then: lvm2
- policycoreutils
- python3-iniparse
- python3
- qemu-img
- rpm-ostree
- selinux-policy-targeted
- skopeo
- systemd
- tar
- xz
boot_rpms:
- dracut-config-generic
- grub2-tools-minimal
- $kernel_rpm
base_rpms:
- $linux_firmware_rpm
- NetworkManager
- audit
- chrony
- e2fsprogs
- efibootmgr
- glibc-langpack-en
- hostname
- passwd
- rng-tools
- rootfiles
- selinux-policy-targeted
- systemd-udev
- mpp-if: use_luks
then: lvm2
@@ -0,0 +1,180 @@
version: '2'
mpp-vars:
image_rpms:
mpp-join:
- mpp-eval: locals().get('extra_image_rpms', [])
- []
pipelines:
- name: kernel-tree
build: name:build
stages:
- type: org.osbuild.kernel-cmdline
options:
root_fs_uuid:
mpp-eval: rootfs_uuid
kernel_opts:
mpp-eval: ''' '' .join(kernel_opts)'
- type: org.osbuild.rpm
options:
gpgkeys:
- mpp-eval: centos_gpg_key
- mpp-eval: redhat_gpg_key
disable_dracut: true
inputs:
packages:
type: org.osbuild.files
origin: org.osbuild.source
mpp-depsolve:
architecture: $arch
module-platform-id: $distro_module_id
baseurl: $distro_baseurl/BaseOS/$arch/os/
repos:
mpp-join:
- mpp-eval: distro_repos
- - id: cs9-shim
baseurl: https://download.copr.fedorainfracloud.org/results/alexl/cs9-shim/fedora-35-$arch/
packages:
mpp-join:
- mpp-eval: base_rpms
- mpp-eval: boot_rpms
- mpp-eval: locals().get('extra_boot_rpms', [])
- - shim-unsigned-$efiarch
excludes:
- dracut-config-rescue
- type: org.osbuild.mkdir
options:
paths:
- path: /boot/efi/EFI/Linux
parents: true
- type: org.osbuild.copy
inputs:
bootcsv:
type: org.osbuild.files
origin: org.osbuild.source
mpp-embed:
id: directboot.csv
path: directboot.csv
extra-tree:
type: org.osbuild.tree
origin: org.osbuild.pipeline
references:
- name:extra-tree-content
options:
paths:
mpp-join:
- - from:
mpp-format-string: input://bootcsv/{embedded['directboot.csv']}
to: tree:///boot/efi/EFI/Linux/boot.csv
- mpp-eval: extra_tree_content
- type: org.osbuild.dracut
options:
kernel:
- mpp-eval: rpms['kernel-tree'][kernel_rpm + '-core'].evra
add_modules:
mpp-eval: dracut_add_modules
omit_modules:
mpp-eval: dracut_omit_modules
add_drivers:
mpp-eval: dracut_add_drivers
filesystems:
mpp-eval: dracut_filesystems
install:
mpp-eval: dracut_install
extra:
- /boot/efi/EFI/Linux/initramfs.img
- --kernel-cmdline
- mpp-format-string: root=UUID={rootfs_uuid} {' ' .join(kernel_opts)}
- name: image-tree
build: name:build
stages:
mpp-join:
- - type: org.osbuild.copy
inputs:
tree:
type: org.osbuild.tree
origin: org.osbuild.pipeline
references:
- name:rootfs
extra-tree:
type: org.osbuild.tree
origin: org.osbuild.pipeline
references:
- name:extra-tree-content
options:
paths:
mpp-join:
- - from: input://tree/
to: tree:///
- mpp-eval: extra_tree_content
- type: org.osbuild.copy
inputs:
kernel:
type: org.osbuild.tree
origin: org.osbuild.pipeline
references:
- name:kernel-tree
options:
paths:
- from: input://kernel/lib/modules
to: tree:///lib/
- from: input://kernel/boot/efi/EFI/BOOT
to: tree:////boot/efi/EFI/
- from: input://kernel/boot/efi/EFI/Linux
to: tree:////boot/efi/EFI/
- type: org.osbuild.copy
inputs:
kernel:
type: org.osbuild.tree
origin: org.osbuild.pipeline
references:
- name:kernel-tree
options:
paths:
- from: input://kernel/lib/modules
to: tree:///lib/
- from: input://kernel/boot/efi/EFI/BOOT
to: tree:////boot/efi/EFI/
- from: input://kernel/boot/efi/EFI/Linux
to: tree:////boot/efi/EFI/
- mpp-if: arch == 'aarch64'
then:
type: org.osbuild.gunzip
inputs:
file:
type: org.osbuild.files
origin: org.osbuild.pipeline
references:
name:kernel-tree:
file:
mpp-format-string: boot/vmlinuz-{rpms['kernel-tree'][kernel_rpm + '-core'].evra}
options:
path: /boot/efi/EFI/Linux/linux.efi
else:
type: org.osbuild.copy
inputs:
kernel:
type: org.osbuild.tree
origin: org.osbuild.pipeline
references:
- name:kernel-tree
options:
paths:
- from:
mpp-format-string: input://kernel/boot/vmlinuz-{rpms['kernel-tree'][kernel_rpm + '-core'].evra}
to: tree:///boot/efi/EFI/Linux/linux.efi
- type: org.osbuild.users
options:
users:
root:
password:
mpp-eval: root_password
key:
mpp-eval: root_ssh_key
- mpp-eval: target_stages
- - type: org.osbuild.fstab
options:
filesystems:
mpp-eval: fstab
- type: org.osbuild.selinux
options:
file_contexts: etc/selinux/targeted/contexts/files/file_contexts
@@ -0,0 +1,214 @@
version: '2'
mpp-vars:
image_rpms:
mpp-join:
- mpp-eval: locals().get('extra_image_rpms', [])
- mpp-eval: boot_rpms
- mpp-eval: locals().get('extra_boot_rpms', [])
- - nss-altfiles
- greenboot
- greenboot-grub2
- greenboot-reboot
- greenboot-status
- greenboot-rpm-ostree-grub2
- polkit # Needed by rpm-ostree upgrade (until fix for https://github.com/coreos/rpm-ostree/issues/3554 is in)
pipelines:
- name: ostree-tree
build: name:build
stages:
mpp-join:
- - type: org.osbuild.copy
inputs:
tree:
type: org.osbuild.tree
origin: org.osbuild.pipeline
references:
- name:rootfs
extra-tree:
type: org.osbuild.tree
origin: org.osbuild.pipeline
references:
- name:extra-tree-content
options:
paths:
mpp-join:
- - from: input://tree/
to: tree:///
- mpp-eval: extra_tree_content
- type: org.osbuild.systemd
options:
enabled_services:
- greenboot-grub2-set-counter.service
- greenboot-grub2-set-success.service
- greenboot-healthcheck.service
- greenboot-rpm-ostree-grub2-check-fallback.service
- greenboot-status.service
- greenboot-task-runner.service
- mpp-eval: target_stages
- - type: org.osbuild.selinux
options:
file_contexts: etc/selinux/targeted/contexts/files/file_contexts
- type: org.osbuild.ostree.preptree
options:
etc_group_members:
- wheel
- docker
initramfs-args:
- mpp-if: dracut_add_modules
then: "--add"
- mpp-if: dracut_add_modules
then:
mpp-eval: "' '.join(dracut_add_modules)"
- mpp-if: dracut_omit_modules
then: "--omit"
- mpp-if: dracut_omit_modules
then:
mpp-eval: "' '.join(dracut_omit_modules)"
- mpp-if: dracut_filesystems
then: "--filesystems"
- mpp-if: dracut_filesystems
then:
mpp-eval: "' '.join(dracut_filesystems)"
- mpp-if: dracut_add_drivers
then: "--add-drivers"
- mpp-if: dracut_add_drivers
then:
mpp-eval: "' '.join(dracut_add_drivers)"
- mpp-if: dracut_install
then: "--install"
- mpp-if: dracut_install
then:
mpp-eval: "' '.join(dracut_install)"
- name: ostree-commit
build: name:build
stages:
- type: org.osbuild.ostree.init
options:
path: /repo
- type: org.osbuild.ostree.commit
inputs:
tree:
type: org.osbuild.tree
origin: org.osbuild.pipeline
references:
- name:ostree-tree
options:
ref:
mpp-eval: ostree_ref
os_version:
mpp-eval: ostree_os_version
parent:
mpp-if: ostree_ref in locals().get("ostree_parent_refs", {})
then:
mpp-eval: ostree_parent_refs[ostree_ref]
- name: image-tree
build: name:build
stages:
- type: org.osbuild.ostree.init-fs
- type: org.osbuild.ostree.pull
options:
repo: /ostree/repo
remote:
mpp-eval: ostree_remote_name
inputs:
commits:
type: org.osbuild.ostree
origin: org.osbuild.pipeline
references:
name:ostree-commit:
ref:
mpp-eval: ostree_ref
- type: org.osbuild.ostree.os-init
options:
osname:
mpp-eval: osname
- type: org.osbuild.ostree.config
options:
repo: /ostree/repo
config:
sysroot:
readonly: true
bootloader: none
- type: org.osbuild.ostree.remotes
options:
repo: /ostree/repo
remotes:
- name:
mpp-eval: ostree_remote_name
url:
mpp-eval: ostree_repo_url
- type: org.osbuild.mkdir
options:
paths:
- path: /boot/efi
mode: 448
- type: org.osbuild.ostree.deploy
options:
osname:
mpp-eval: osname
ref:
mpp-eval: ostree_ref
remote:
mpp-eval: ostree_remote_name
mounts:
- /boot
- /boot/efi
rootfs:
label: root
kernel_opts:
mpp-eval: kernel_opts
- type: org.osbuild.ostree.fillvar
options:
deployment:
osname:
mpp-eval: osname
ref:
mpp-eval: ostree_ref
- type: org.osbuild.users
mounts:
- type: org.osbuild.ostree.deployment
name: ostree.deployment
options:
deployment:
osname:
mpp-eval: osname
ref:
mpp-eval: ostree_ref
options:
users:
root:
password:
mpp-eval: root_password
key:
mpp-eval: root_ssh_key
- type: org.osbuild.fstab
options:
ostree:
deployment:
osname:
mpp-eval: osname
ref:
mpp-eval: ostree_ref
filesystems:
mpp-eval: fstab
- type: org.osbuild.ostree.selinux
options:
deployment:
osname:
mpp-eval: osname
ref:
mpp-eval: ostree_ref
- type: org.osbuild.grub2
options:
rootfs:
label: root
bootfs:
label: boot
uefi:
vendor:
mpp-eval: uefi_vendor
unified: true
install: true
legacy: false
write_defaults: false
greenboot: true
@@ -0,0 +1,79 @@
version: '2'
mpp-vars:
image_rpms:
mpp-join:
- mpp-eval: locals().get('extra_image_rpms', [])
- mpp-eval: boot_rpms
- mpp-eval: locals().get('extra_boot_rpms', [])
- - shim
pipelines:
- name: image-tree
build: name:build
stages:
mpp-join:
- - type: org.osbuild.copy
inputs:
tree:
type: org.osbuild.tree
origin: org.osbuild.pipeline
references:
- name:rootfs
extra-tree:
type: org.osbuild.tree
origin: org.osbuild.pipeline
references:
- name:extra-tree-content
options:
paths:
mpp-join:
- - from: input://tree/
to: tree:///
- mpp-eval: extra_tree_content
- type: org.osbuild.users
options:
users:
root:
password:
mpp-eval: root_password
key:
mpp-eval: root_ssh_key
- mpp-eval: target_stages
- - type: org.osbuild.dracut
options:
kernel:
- mpp-eval: rpms['rootfs'][kernel_rpm + '-core'].evra
add_modules:
mpp-eval: dracut_add_modules
omit_modules:
mpp-eval: dracut_omit_modules
add_drivers:
mpp-eval: dracut_add_drivers
filesystems:
mpp-eval: dracut_filesystems
install:
mpp-eval: dracut_install
- type: org.osbuild.fstab
options:
filesystems:
mpp-eval: fstab
- type: org.osbuild.grub2
options:
root_fs_uuid:
mpp-eval: rootfs_uuid
boot_fs_uuid:
mpp-eval: bootfs_uuid
kernel_opts:
mpp-eval: ''' '' .join(kernel_opts)'
uefi:
vendor:
mpp-eval: uefi_vendor
unified: true
legacy: false
write_defaults: false
greenboot: true
- type: org.osbuild.fix-bls
options:
prefix: /
- type: org.osbuild.selinux
options:
file_contexts: etc/selinux/targeted/contexts/files/file_contexts
+413
View File
@@ -0,0 +1,413 @@
version: '2'
mpp-vars:
extra_tree_content:
- mpp-if: use_luks and luks_auto_unlock
then:
from: input://extra-tree/luks-key
to: tree:///usr/.auto-unlock-key
dracut_install:
mpp-join:
- mpp-eval: dracut_install
- mpp-if: use_luks and luks_auto_unlock
then:
- /usr/.auto-unlock-key
kernel_opts:
mpp-join:
- - ro
- loglevel=$kernel_loglevel
- mpp-if: use_efi_runtime
then: efi=runtime
- mpp-eval: kernel_opts
- mpp-if: use_luks
then:
- rd.luks.uuid=$luks_uuid
- rd.luks.options=discard
- mpp-if: luks_auto_unlock
then: rd.luks.key=$luks_uuid=/usr/.auto-unlock-key
pipelines:
# Some variables need to be written to files, do that here
- name: extra-tree-content
build: name:build
stages:
- type: org.osbuild.copy
inputs:
inlinefile:
type: org.osbuild.files
origin: org.osbuild.source
mpp-embed:
id: luks-key
text: $luks_passphrase
options:
paths:
- from:
mpp-format-string: input://inlinefile/{embedded['luks-key']}
to: tree:///luks-key
- mpp-import-pipelines:
path: image-$image_type.ipp.yml
- name: image
build: name:build
stages:
- type: org.osbuild.truncate
options:
filename: disk.img
size:
mpp-eval: image.size
- type: org.osbuild.sfdisk
devices:
device:
type: org.osbuild.loopback
options:
filename: disk.img
options:
mpp-format-json: '{image.layout}'
- type: org.osbuild.mkfs.fat
devices:
device:
type: org.osbuild.loopback
options:
filename: disk.img
start:
mpp-eval: image.layout['efi'].start
size:
mpp-eval: image.layout['efi'].size
options:
label: ESP
volid: 7B7795E7
- type: org.osbuild.mkfs.ext4
devices:
device:
type: org.osbuild.loopback
options:
filename: disk.img
start:
mpp-eval: image.layout['boot'].start
size:
mpp-eval: image.layout['boot'].size
options:
uuid:
mpp-eval: bootfs_uuid
label: boot
- mpp-if: use_luks
then:
type: org.osbuild.luks2.format
devices:
device:
type: org.osbuild.loopback
options:
filename: disk.img
start:
mpp-eval: image.layout['root'].start
size:
mpp-eval: image.layout['root'].size
lock: true
options:
passphrase:
mpp-eval: luks_passphrase
uuid:
mpp-eval: luks_uuid
label: luks-rootfs
pbkdf:
method: argon2i
memory: 32
parallelism: 1
iterations: 4
integrity:
mpp-if: luks_use_integrity
then: hmac-sha256
- mpp-if: use_luks
then:
type: org.osbuild.lvm2.create
devices:
luks:
type: org.osbuild.loopback
options:
filename: disk.img
start:
mpp-eval: image.layout['root'].start
size:
mpp-eval: image.layout['root'].size
device:
type: org.osbuild.luks2
parent: luks
options:
passphrase:
mpp-eval: luks_passphrase
options:
volumes:
- name: root
extents: 100%FREE
- type: org.osbuild.mkfs.ext4
devices:
luks:
mpp-if: use_luks
then:
type: org.osbuild.loopback
options:
filename: disk.img
start:
mpp-eval: image.layout['root'].start
size:
mpp-eval: image.layout['root'].size
lvm:
mpp-if: use_luks
then:
type: org.osbuild.luks2
parent: luks
options:
passphrase:
mpp-eval: luks_passphrase
device:
mpp-if: use_luks
then:
type: org.osbuild.lvm2.lv
parent: lvm
options:
volume: root
else:
type: org.osbuild.loopback
options:
filename: disk.img
start:
mpp-eval: image.layout['root'].start
size:
mpp-eval: image.layout['root'].size
options:
uuid:
mpp-eval: rootfs_uuid
label: root
- type: org.osbuild.copy
inputs:
tree:
type: org.osbuild.tree
origin: org.osbuild.pipeline
references:
- name:image-tree
build-tree:
type: org.osbuild.tree
origin: org.osbuild.pipeline
references:
- name:build
extra-tree:
mpp-if: "'extra_image_source_' + image_type in locals()"
then:
type: org.osbuild.tree
origin: org.osbuild.pipeline
references:
- mpp-format-string: "name:{locals().get('extra_image_source_' + image_type)}"
options:
paths:
mpp-join:
- - from: input://tree/
to: mount://root/
- mpp-eval: locals().get('extra_image_copy_' + image_type, [])
devices:
efi:
type: org.osbuild.loopback
options:
filename: disk.img
start:
mpp-eval: image.layout['efi'].start
size:
mpp-eval: image.layout['efi'].size
boot:
type: org.osbuild.loopback
options:
filename: disk.img
start:
mpp-eval: image.layout['boot'].start
size:
mpp-eval: image.layout['boot'].size
root:
mpp-if: use_luks
then:
type: org.osbuild.lvm2.lv
parent: root-luks
options:
volume: root
else:
type: org.osbuild.loopback
options:
filename: disk.img
start:
mpp-eval: image.layout['root'].start
size:
mpp-eval: image.layout['root'].size
root-raw:
mpp-if: use_luks
then:
type: org.osbuild.loopback
options:
filename: disk.img
start:
mpp-eval: image.layout['root'].start
size:
mpp-eval: image.layout['root'].size
root-luks:
mpp-if: use_luks
then:
type: org.osbuild.luks2
parent: root-raw
options:
passphrase:
mpp-eval: luks_passphrase
mounts:
- name: root
type: org.osbuild.ext4
source: root
target: /
- name: boot
type: org.osbuild.ext4
source: boot
target: /boot
- name: efi
type: org.osbuild.fat
source: efi
target: /boot/efi
- mpp-if: use_luks
then:
type: org.osbuild.lvm2.metadata
devices:
luks:
type: org.osbuild.loopback
options:
filename: disk.img
start:
mpp-eval: image.layout['root'].start
size:
mpp-eval: image.layout['root'].size
device:
type: org.osbuild.luks2
parent: luks
options:
passphrase:
mpp-eval: luks_passphrase
options:
vg_name: osbuild
creation_host: osbuild
description: "Built with osbuild"
- name: qcow2
build: name:build
stages:
- type: org.osbuild.qemu
inputs:
image:
type: org.osbuild.files
origin: org.osbuild.pipeline
references:
name:image:
file: disk.img
options:
filename: disk.qcow2
format:
type: qcow2
compat: '1.1'
- name: container
build: name:build
stages:
- type: org.osbuild.oci-archive
inputs:
base:
type: org.osbuild.tree
origin: org.osbuild.pipeline
references:
- name:rootfs
options:
filename: container.tar
architecture: $arch
config:
Cmd:
- "/usr/bin/bash"
# We need a smaller fstab for the non-partitioned case
- name: ext4-fstab
build: name:build
stages:
# We copy /etc to get the right selinux context on the new file
- type: org.osbuild.copy
inputs:
image-tree:
type: org.osbuild.tree
origin: org.osbuild.pipeline
references:
- name:image-tree
options:
paths:
- from: input://image-tree/etc
to: tree:///etc
- type: org.osbuild.fstab
options:
filesystems:
- uuid:
mpp-eval: rootfs_uuid
vfs_type: ext4
path: /
- name: ext4
build: name:build
stages:
- type: org.osbuild.truncate
options:
filename: rootfs.ext4
size:
mpp-eval: image.size
- type: org.osbuild.mkfs.ext4
devices:
device:
type: org.osbuild.loopback
options:
filename: rootfs.ext4
start: 0
size:
mpp-format-int: "{int(image.size) // 512}"
options:
uuid:
mpp-eval: rootfs_uuid
label: root
- type: org.osbuild.copy
inputs:
tree:
type: org.osbuild.tree
origin: org.osbuild.pipeline
references:
- name:image-tree
fstab:
type: org.osbuild.tree
origin: org.osbuild.pipeline
references:
- name:ext4-fstab
options:
paths:
mpp-join:
- - from: input://tree/
to: mount://root/
- from: input://fstab/etc/fstab
to: mount://root/etc/fstab
- mpp-eval: locals().get('extra_image_copy_' + image_type, [])
devices:
root:
type: org.osbuild.loopback
options:
filename: rootfs.ext4
start: 0
size:
mpp-format-int: "{int(image.size) // 512}"
mounts:
- name: root
type: org.osbuild.ext4
source: root
target: /
- name: tar
build: name:build
stages:
- type: org.osbuild.tar
inputs:
tree:
type: org.osbuild.tree
origin: org.osbuild.pipeline
references:
- name:rootfs
options:
filename: rootfs.tar
root-node: omit
@@ -0,0 +1,76 @@
version: '2'
mpp-vars:
extra_image_rpms:
- openssh-server
- sudo
- tuned
- cloud-init
- cloud-utils-growpart
- gdisk
- NetworkManager-cloud-setup
- rsync
- qemu-guest-agent
extra_build_rpms:
- python3-pyyaml
target_stages:
- type: org.osbuild.sshd.config
options:
config:
PermitRootLogin:
mpp-eval: ssh_permit_root_login
- type: org.osbuild.systemd
options:
enabled_services:
- sshd
- NetworkManager
- nm-cloud-setup.service
- nm-cloud-setup.timer
- cloud-init
- cloud-init-local
- cloud-config
- cloud-final
- reboot.target
- tuned
default_target: multi-user.target
- type: org.osbuild.systemd-logind
options:
filename: 00-getty-fixes.conf
config:
Login:
NAutoVTs: 0
- type: org.osbuild.cloud-init
options:
filename: 00-cs-default-user.cfg
config:
system_info:
default_user:
name: ec2-user
- type: org.osbuild.systemd.unit
options:
unit: nm-cloud-setup.service
dropin: 10-enable-for-ec2.conf
config:
Service:
Environment: NM_CLOUD_SETUP_EC2=yes
- type: org.osbuild.locale
options:
language: en_US.UTF-8
- type: org.osbuild.timezone
options:
zone: UTC
- type: org.osbuild.chrony
options:
servers:
- hostname: 169.254.169.123
prefer: true
iburst: true
minpoll: 4
maxpoll: 4
leapsectz: ""
- type: org.osbuild.keymap
options:
keymap: us
x11-keymap:
layouts:
- us
pipelines: []
@@ -0,0 +1,2 @@
version: '2'
pipelines: []
@@ -0,0 +1,69 @@
version: '2'
mpp-vars:
extra_image_source_ostree: ostree-tree
extra_image_copy_ostree:
- from: input://extra-tree/lib/ostree-boot/efi/
to: mount://root/boot/efi/
rpi4_use_uefi: false
extra_image_source_directboot: rpi-direct-files
extra_image_copy_directboot:
mpp-if: not rpi4_use_uefi
then:
- from: input://extra-tree/
to: mount://root/boot/efi/
else: []
extra_image_rpms:
- pi4-firmware-blob
- pi_resize
dracut_add_drivers:
mpp-join:
- mpp-eval: dracut_add_drivers
- - bcm2835
- bcm2835-mailbox
- sdhci
partition_label: dos
target_repos:
- id: cs9-rpi4-fw
baseurl: https://download.copr.fedorainfracloud.org/results/alexl/cs9-rpi4-fw/centos-stream-9-aarch64/
rpi4_direct_cmdline_txt: console=serial0,115200 console=tty1 modprobe.blacklist=vc4
rpi4_direct_config_txt: |
kernel=EFI/Linux/linux.efi
initramfs EFI/Linux/initramfs.img followkernel
arm_64bit=1
enable_uart=1
uart_2ndstage=1
dtoverlay=miniuart-bt
display_auto_detect=1
dtoverlay=vc4-kms-v3d-pi4
max_framebuffers=2
disable_overscan=1
pipelines:
- name: rpi-direct-files
runner: org.osbuild.centos9
stages:
- type: org.osbuild.copy
inputs:
inlinefile:
type: org.osbuild.files
origin: org.osbuild.source
mpp-embed:
id: config.txt
text: $rpi4_direct_config_txt
options:
paths:
- from:
mpp-format-string: input://inlinefile/{embedded['config.txt']}
to: tree:///config.txt
- type: org.osbuild.copy
inputs:
inlinefile:
type: org.osbuild.files
origin: org.osbuild.source
mpp-embed:
id: cmdline.txt
text: $rpi4_direct_cmdline_txt
options:
paths:
- from:
mpp-format-string: input://inlinefile/{embedded['cmdline.txt']}
to: tree:///cmdline.txt
+394
View File
@@ -0,0 +1,394 @@
#!/usr/bin/python3
import argparse
import os
import platform
import select
import shlex
import socket
import subprocess
import sys
import tempfile
import threading
import time
import signal
import shutil
import json
BLOCK_SIZE = 64*1024
def read_manifest(path):
if path == "-":
manifest = sys.stdin.read()
else:
with open(path) as f:
manifest = f.read()
return manifest
def parse_arguments(sys_argv):
parser = argparse.ArgumentParser(description="Build operating system images")
parser.add_argument("manifest_path", metavar="MANIFEST",
help="json file containing the manifest that should be built, or a '-' to read from stdin")
parser.add_argument("--store", metavar="DIRECTORY", type=os.path.abspath,
default=".osbuild",
help="directory where intermediary os trees are stored")
parser.add_argument("--checkpoint", metavar="ID", action="append", type=str, default=None,
help="stage to commit to the object store during build (can be passed multiple times)")
parser.add_argument("--export", metavar="ID", action="append", type=str, default=None,
help="object to export, can be passed multiple times")
parser.add_argument("--output-directory", metavar="DIRECTORY", type=os.path.abspath,
help="directory where result objects are stored")
parser.add_argument("--arch", metavar="ARCH", type=str, default=platform.machine(),
help="Arch to build for")
return parser.parse_args(sys_argv[1:])
def local_osbuild(manifest, opts):
cmd = ['osbuild'] + opts + ['-']
try:
p = subprocess.run(cmd, check=True, input=manifest.encode("utf8"), capture_output=True )
except subprocess.CalledProcessError as e:
print(e.output)
sys.exit(e.returncode)
lines = p.stdout.decode("utf8").splitlines()
checkpoints = {}
for l in lines:
p = l.split()
checkpoint = p[0][:-1]
checkpoints[checkpoint] = p[1]
return checkpoints
def extract_dependencies(manifest):
j = json.loads(manifest)
version = j.get("version", None);
if version != '2':
print(f"Unsupported manifest version {version}, only version 2 supported")
sys.exit(1)
sources = j.get("sources", {});
curl = sources.get("org.osbuild.curl", {});
curl_items = curl.get("items", {});
shas = curl_items.keys()
return list(shas)
def find_images(arch):
base_image=f"osbuildvm-{arch}.img"
base_kernel=f"osbuildvm-{arch}.vmlinuz"
base_initrd=f"osbuildvm-{arch}.initramfs"
image_dir=None
image_dirs = [os.getcwd(), os.path.join(os.getcwd(), "_build"), "/usr/share/osbuildvm"]
for i in image_dirs:
if os.path.exists(os.path.join(i, base_image)):
image_dir = i
break
if not image_dir:
print(f"Unable to find {base_image}, tried: {image_dirs}", file=sys.stderr)
sys.exit(1)
image = os.path.join(image_dir, base_image)
kernel = os.path.join(image_dir, base_kernel)
initrd = os.path.join(image_dir, base_initrd)
return (image, kernel, initrd)
def qemu_img(*args):
res = subprocess.run(["qemu-img"] + [*args],
stdout=subprocess.PIPE,
check=True)
class QEmu(object):
def __init__(self, image1, image2, kernel, initrd, arch):
# This is where we store the sockets and the pidfile
self.tmpdir = tempfile.TemporaryDirectory(prefix="tmp-qemu-")
self.args = []
self.pid = 0
self.host_arch = platform.machine()
self.arch = arch
debug_serial = False
qemu_kvm_path = self.find_qemu()
self.args.append(qemu_kvm_path)
# Virtio serial ports
self.args.extend(["-device", "virtio-serial"])
out_socket_path = self.add_socket("output")
sync_socket_path = self.add_socket("sync")
stdout_socket_path = self.add_socket("stdout")
debug_cmdline="quiet loglevel=1"
if debug_serial:
self.args.extend(["-serial", "file:/dev/stdout"])
debug_cmdline=""
# Machine details
self.args.extend(["-m", "size=2G",
"-nodefaults",
"-vga", "none", "-vnc", "none"])
if self.kvm_supported():
self.args.extend(["-enable-kvm"])
if self.arch=="x86_64":
machine = "q35"
cpu = "qemu64"
if self.arch=="aarch64":
machine = "virt"
cpu = "cortex-a57"
if self.arch == self.host_arch:
cpu = "host"
self.args.extend(["-machine", machine,
"-cpu", cpu])
if self.arch=="aarch64":
self.args.extend(["-bios", "/usr/share/edk2/aarch64/QEMU_EFI.fd",
"-boot", "efi"])
pid_file = os.path.join(self.tmpdir.name, "qemu.pid")
self.args.extend(["-daemonize", "-pidfile" , pid_file,
"-kernel", kernel,
"-initrd", initrd,
"-append", f'root=/dev/vda console=ttyS0 init=/usr/bin/start.sh {debug_cmdline} ro',
"-drive", f"file={image1},index=0,media=disk,format=qcow2,snapshot=on,if=virtio",
"-drive", f"file={image2},index=1,media=disk,format=raw,if=virtio"])
p = subprocess.run(self.args, check=True)
with open(pid_file, "r") as f:
self.pid = int(f.read())
self.sock_out = self.connect_socket(out_socket_path)
self.sock_sync = self.connect_socket(sync_socket_path)
self.sock_stdout = self.connect_socket(stdout_socket_path)
def connect_socket(self, path):
sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
sock.connect(path)
return sock
def add_socket(self, id):
socket_path = os.path.join(self.tmpdir.name, id + ".sock")
self.args.extend(["-chardev", f"socket,path={socket_path},server=on,wait=off,id={id}",
"-device", f"virtserialport,chardev={id},name={id}"])
return socket_path
def find_qemu(self):
if self.arch == self.host_arch:
binary_name = "qemu-kvm"
else:
binary_name = f"qemu-system-{self.arch}"
for d in ["/usr/bin", "/usr/libexec"]:
p = os.path.join(d, binary_name)
if os.path.isfile(p):
return p
print(f"Can't find {binary_name}", file=sys.stderr)
sys.exit(1)
def kvm_supported(self):
return self.arch == self.host_arch and os.path.exists("/dev/kvm")
def copy_out(self, destination):
while True:
readable, writable, exceptional = select.select([self.sock_out, self.sock_sync, self.sock_stdout], [], [])
read_something = False
if self.sock_stdout in readable:
data = self.sock_stdout.recv(BLOCK_SIZE)
while len(data) > 0:
res = sys.stdout.buffer.write(data)
data = data[res:]
sys.stdout.flush()
read_something = True
if self.sock_out in readable:
data = self.sock_out.recv(BLOCK_SIZE)
while len(data) > 0:
res = destination.write(data)
data = data[res:]
read_something = True
if read_something:
continue # Don't exit until there is no more to read from sock or sock_stdout
# If we had no buffered data in sock and sync_sock is readable that means we copied everything and can exit
if self.sock_sync in readable:
data = self.sock_sync.recv(BLOCK_SIZE)
break
def kill(self):
if self.pid != 0:
os.kill(self.pid, signal.SIGTERM)
self.pid = 0
def __enter__(self):
return self
def __exit__(self, type, value, traceback):
self.kill()
self.tmpdir.cleanup()
def create_ext4_image(path, size, root_dir):
with open(path, "w") as f:
f.truncate(size)
cmd = ["mkfs.ext4", "-d", root_dir, "-E", "no_copy_xattrs,root_owner=0:0", "-O", "^has_journal", path]
try:
p = subprocess.run(cmd, check=True,capture_output=True)
except subprocess.CalledProcessError as e:
print(f"Unable to create ext4 work fs: {e}", file=sys.stderr)
sys.exit(e.returncode)
def link_or_copy_file(source_path, dest_path):
try:
os.link(source_path, dest_path)
except Exception as e:
shutil.copyfile(source_path, dest_path, follow_symlinks=False)
def make_work_rootfs(args, tmpdirname, manifest, digests, main_sh, checkpoint_ids):
rootdir = os.path.join(tmpdirname, "root")
os.makedirs(rootdir, exist_ok=True)
with open (os.open(os.path.join(rootdir, "main.sh"), os.O_CREAT | os.O_WRONLY, 0o775), "w") as mainsh:
mainsh.write(main_sh)
with open (os.path.join(rootdir, "image.json"), "w") as image_json:
image_json.write(manifest)
orig_sources_dir = os.path.join(args.store, "sources/org.osbuild.files")
root_sources_dir = os.path.join(rootdir, "osbuild_store/sources/org.osbuild.files")
os.makedirs(root_sources_dir, mode=0o777, exist_ok=True)
root_input_dir = os.path.join(rootdir, "input")
os.makedirs(root_input_dir, mode=0o777, exist_ok=True)
for digest in digests:
link_or_copy_file(os.path.join(orig_sources_dir, digest),
os.path.join(root_sources_dir, digest))
for cp, cp_id in checkpoint_ids.items():
source_path = os.path.join(args.store, "refs_tars/" + cp_id + ".tar.gz")
if os.path.isfile(source_path):
link_or_copy_file(source_path,
os.path.join(root_input_dir, cp_id + ".tar.gz"))
return rootdir
# Moves any files recursively in root_src_dir to root_dst_dir, replacing if needed
# Keeps old files and directories in root_dst_dir
def move_merged(root_src_dir, root_dst_dir):
root_src_dir = os.path.abspath(root_src_dir)
root_dst_dir = os.path.abspath(root_dst_dir)
for src_dir, dirs, files in os.walk(root_src_dir):
dst_dir = src_dir.replace(root_src_dir, root_dst_dir, 1)
if not os.path.exists(dst_dir):
os.makedirs(dst_dir)
for file_ in files:
src_file = os.path.join(src_dir, file_)
dst_file = os.path.join(dst_dir, file_)
if os.path.exists(dst_file):
os.remove(dst_file)
shutil.move(src_file, dst_dir)
def run_in_vm(args, manifest, digests, tmpdirname, shell_to_run, checkpoint_ids):
image,kernel,initrd = find_images(args.arch)
rootdir = make_work_rootfs(args, tmpdirname, manifest, digests, shell_to_run, checkpoint_ids)
work_image = os.path.join(tmpdirname, "work.img")
create_ext4_image(work_image, 100*1024*1024*1024, rootdir)
shutil.rmtree(rootdir)
output_path = args.output_directory
os.makedirs(output_path, exist_ok=True)
exit_status = 1
with tempfile.TemporaryDirectory(prefix="download-", dir=output_path) as output_tmpdir:
with QEmu(image, work_image, kernel, initrd, args.arch) as qemu:
with subprocess.Popen(["tar", "x", "-C", output_tmpdir], stdin=subprocess.PIPE) as proc:
qemu.copy_out(proc.stdin)
exit_status_path = os.path.join(output_tmpdir, "exit_status")
if os.path.isfile(exit_status_path):
with open(exit_status_path, "r") as f:
exit_status = int(f.read())
# Move osbuild outout to the real output dir
osbuild_output = os.path.join(output_tmpdir, "osbuild")
if os.path.isdir(osbuild_output):
move_merged(osbuild_output, output_path)
checkpoints_output = os.path.join(output_tmpdir, "checkpoints")
checkpoints_dest = os.path.join(args.store, "refs_tars")
if os.path.isdir(checkpoints_output):
os.makedirs(checkpoints_dest, exist_ok=True)
for tar in os.listdir(checkpoints_output):
if not os.path.isfile(os.path.join(checkpoints_dest, tar)):
shutil.move(os.path.join(checkpoints_output, tar),
checkpoints_dest)
sys.exit(exit_status)
def main():
args = parse_arguments(sys.argv)
manifest = read_manifest(args.manifest_path)
print("Running osbuild on host to download files")
checkpoint_ids = local_osbuild(manifest, ['--store', args.store])
digests = extract_dependencies(manifest)
mainsh_data = f'''\
#!/bin/bash
mkdir -p /work/osbuild_store
(
echo === Extracting checkpoints in vm ===
for tar in $(find /work/input/ -mindepth 1 -print ); do
echo extracting $(basename $tar)
tar xf $tar --acls --selinux --xattrs -C /work/osbuild_store
done
echo === Running osbuild in vm ===
osbuild --store /work/osbuild_store --output-directory /work/output/osbuild {' '.join(map(lambda e: "--export " + e, args.export))} {' '.join(map(lambda cp: "--checkpoint " + cp, args.checkpoint))} /work/image.json
RES=$?
echo $RES > /work/output/exit_status
echo === Osbuild exit status $RES ===
echo === Saving checkpoints ===
mkdir -p /work/output/checkpoints
for cp in $(find /work/osbuild_store/refs/ -mindepth 1 -printf "%f "); do
if test -f /work/input/$cp.tar.gz; then
continue
fi
obj=$(basename $(readlink /work/osbuild_store/refs/$cp))
tar cSf /work/output/checkpoints/$cp.tar.gz --acls --selinux --xattrs -C /work/osbuild_store/ refs/$cp objects/$obj
echo Saved $cp
done
) > /dev/virtio-ports/stdout 2>&1
tar cSf /dev/virtio-ports/output -C /work/output ./
# Signal output ended
sleep 3
echo DONE > /dev/virtio-ports/sync
# Block for it to be fully read
cat /dev/virtio-ports/sync
'''
tmpdir = os.path.join(args.store, "tmp")
os.makedirs(tmpdir, exist_ok=True)
with tempfile.TemporaryDirectory(prefix="osbuild-qemu-", dir=tmpdir) as tmpdirname:
run_in_vm(args, manifest, digests, tmpdirname, mainsh_data, checkpoint_ids)
if __name__ == "__main__":
main()
@@ -0,0 +1,229 @@
version: '2'
mpp-vars:
rootfs_uuid: 86a22bf4-f153-4541-b6c7-0332c0dfaead
rootfs_size: 2147483648
cs9_baseurl: http://mirror.stream.centos.org/9-stream
cs9_repos:
- id: baseos
baseurl: $cs9_baseurl/BaseOS/$arch/os/
- id: appstream
baseurl: $cs9_baseurl/AppStream/$arch/os/
centos_gpg_key: |
-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: GnuPG v2.0.22 (GNU/Linux)
mQINBFzMWxkBEADHrskpBgN9OphmhRkc7P/YrsAGSvvl7kfu+e9KAaU6f5MeAVyn
rIoM43syyGkgFyWgjZM8/rur7EMPY2yt+2q/1ZfLVCRn9856JqTIq0XRpDUe4nKQ
8BlA7wDVZoSDxUZkSuTIyExbDf0cpw89Tcf62Mxmi8jh74vRlPy1PgjWL5494b3X
5fxDidH4bqPZyxTBqPrUFuo+EfUVEqiGF94Ppq6ZUvrBGOVo1V1+Ifm9CGEK597c
aevcGc1RFlgxIgN84UpuDjPR9/zSndwJ7XsXYvZ6HXcKGagRKsfYDWGPkA5cOL/e
f+yObOnC43yPUvpggQ4KaNJ6+SMTZOKikM8yciyBwLqwrjo8FlJgkv8Vfag/2UR7
JINbyqHHoLUhQ2m6HXSwK4YjtwidF9EUkaBZWrrskYR3IRZLXlWqeOi/+ezYOW0m
vufrkcvsh+TKlVVnuwmEPjJ8mwUSpsLdfPJo1DHsd8FS03SCKPaXFdD7ePfEjiYk
nHpQaKE01aWVSLUiygn7F7rYemGqV9Vt7tBw5pz0vqSC72a5E3zFzIIuHx6aANry
Gat3aqU3qtBXOrA/dPkX9cWE+UR5wo/A2UdKJZLlGhM2WRJ3ltmGT48V9CeS6N9Y
m4CKdzvg7EWjlTlFrd/8WJ2KoqOE9leDPeXRPncubJfJ6LLIHyG09h9kKQARAQAB
tDpDZW50T1MgKENlbnRPUyBPZmZpY2lhbCBTaWduaW5nIEtleSkgPHNlY3VyaXR5
QGNlbnRvcy5vcmc+iQI3BBMBAgAhBQJczFsZAhsDBgsJCAcDAgYVCAIJCgsDFgIB
Ah4BAheAAAoJEAW1VbOEg8ZdjOsP/2ygSxH9jqffOU9SKyJDlraL2gIutqZ3B8pl
Gy/Qnb9QD1EJVb4ZxOEhcY2W9VJfIpnf3yBuAto7zvKe/G1nxH4Bt6WTJQCkUjcs
N3qPWsx1VslsAEz7bXGiHym6Ay4xF28bQ9XYIokIQXd0T2rD3/lNGxNtORZ2bKjD
vOzYzvh2idUIY1DgGWJ11gtHFIA9CvHcW+SMPEhkcKZJAO51ayFBqTSSpiorVwTq
a0cB+cgmCQOI4/MY+kIvzoexfG7xhkUqe0wxmph9RQQxlTbNQDCdaxSgwbF2T+gw
byaDvkS4xtR6Soj7BKjKAmcnf5fn4C5Or0KLUqMzBtDMbfQQihn62iZJN6ZZ/4dg
q4HTqyVpyuzMXsFpJ9L/FqH2DJ4exGGpBv00ba/Zauy7GsqOc5PnNBsYaHCply0X
407DRx51t9YwYI/ttValuehq9+gRJpOTTKp6AjZn/a5Yt3h6jDgpNfM/EyLFIY9z
V6CXqQQ/8JRvaik/JsGCf+eeLZOw4koIjZGEAg04iuyNTjhx0e/QHEVcYAqNLhXG
rCTTbCn3NSUO9qxEXC+K/1m1kaXoCGA0UWlVGZ1JSifbbMx0yxq/brpEZPUYm+32
o8XfbocBWljFUJ+6aljTvZ3LQLKTSPW7TFO+GXycAOmCGhlXh2tlc6iTc41PACqy
yy+mHmSv
=kkH7
-----END PGP PUBLIC KEY BLOCK-----
pipelines:
- runner: org.osbuild.centos9
name: build
stages:
- type: org.osbuild.rpm
inputs:
packages:
type: org.osbuild.files
origin: org.osbuild.source
mpp-depsolve:
architecture: $arch
module-platform-id: platform:el9
baseurl: $cs9_baseurl/BaseOS/$arch/os/
repos:
mpp-eval: cs9_repos
packages:
- dnf
- e2fsprogs
- policycoreutils
- python3-iniparse
- python39
- qemu-img
- selinux-policy-targeted
- tar
- xz
options:
gpgkeys:
- mpp-eval: centos_gpg_key
exclude:
docs: true
- type: org.osbuild.selinux
options:
file_contexts: etc/selinux/targeted/contexts/files/file_contexts
labels:
/usr/bin/cp: system_u:object_r:install_exec_t:s0
/usr/bin/tar: system_u:object_r:install_exec_t:s0
- name: rootfs
build: name:build
stages:
- type: org.osbuild.rpm
options:
gpgkeys:
- mpp-eval: centos_gpg_key
inputs:
packages:
type: org.osbuild.files
origin: org.osbuild.source
mpp-depsolve:
architecture: $arch
module-platform-id: platform:el9
baseurl: $cs9_baseurl/BaseOS/$arch/os/
repos:
mpp-join:
- mpp-eval: cs9_repos
- - id: osbuild
baseurl: https://download.copr.fedorainfracloud.org/results/@osbuild/osbuild/centos-stream-9-$arch
packages:
- bash
- dracut-config-generic
- kernel
- langpacks-en
- selinux-policy-targeted
- net-tools
- osbuild
- osbuild-tools
- osbuild-ostree
excludes:
- dracut-config-rescue
- type: org.osbuild.locale
options:
language: en_US.UTF-8
- type: org.osbuild.copy
inputs:
inlinefile:
type: org.osbuild.files
origin: org.osbuild.source
mpp-embed:
id: osbuilder.sh
text: |
#!/usr/bin/bash
function clean_up {
systemctl poweroff -f -f
}
trap clean_up EXIT
if grep -q "osbuilder_bash=1" /proc/cmdline; then bash; exit; fi
mount /dev/vdb /work
/work/main.sh
options:
paths:
- from:
mpp-format-string: input://inlinefile/{embedded['osbuilder.sh']}
to: tree:///usr/bin/start.sh
- type: org.osbuild.chmod
options:
items:
/usr/bin/start.sh:
mode: a+x
- type: org.osbuild.mkdir
options:
paths:
- path: /work
- type: org.osbuild.selinux
options:
file_contexts: etc/selinux/targeted/contexts/files/file_contexts
- type: org.osbuild.selinux
options:
file_contexts: etc/selinux/targeted/contexts/files/file_contexts
- name: image
build: name:build
stages:
- type: org.osbuild.truncate
options:
filename: disk.img
size:
mpp-format-string: '{rootfs_size}'
- type: org.osbuild.mkfs.ext4
devices:
device:
type: org.osbuild.loopback
options:
filename: disk.img
start: 0
size:
mpp-eval: rootfs_size
options:
uuid:
mpp-eval: rootfs_uuid
label: root
- type: org.osbuild.copy
inputs:
tree:
type: org.osbuild.tree
origin: org.osbuild.pipeline
references:
- name:rootfs
options:
paths:
- from: input://tree/
to: mount://root/
devices:
root:
type: org.osbuild.loopback
options:
filename: disk.img
start: 0
size:
mpp-eval: rootfs_size
mounts:
- name: root
type: org.osbuild.ext4
source: root
target: /
- name: osbuildvm
build: name:build
stages:
- type: org.osbuild.qemu
inputs:
image:
type: org.osbuild.files
origin: org.osbuild.pipeline
references:
name:image:
file: disk.img
options:
filename: disk.qcow2
format:
type: qcow2
compat: '1.1'
- type: org.osbuild.copy
inputs:
rootfs:
type: org.osbuild.tree
origin: org.osbuild.pipeline
references:
- name:rootfs
options:
paths:
- from:
mpp-format-string: input://rootfs/usr/lib/modules/{rpms['rootfs']['kernel-core'].evra}/vmlinuz
to: tree:///vmlinuz
- from:
mpp-format-string: input://rootfs/boot/initramfs-{rpms['rootfs']['kernel-core'].evra}.img
to: tree:///initramfs
- type: org.osbuild.chmod
options:
items:
/initramfs:
mode: a+r
+449
View File
@@ -0,0 +1,449 @@
#!/usr/bin/env python3
import argparse
import atexit
import binascii
import http.server
import os
import platform
import select
import shutil
import signal
import socket
import socketserver
import subprocess
import sys
import tempfile
import time
is_verbose = False
def print_verbose(s):
if is_verbose:
print(s)
def print_error(s):
print(s, file=sys.stderr)
def exit_error(s):
print_error(s)
sys.exit(1)
def bool_arg(val):
return "on" if val else "off"
def find_qemu(arch):
binary_names = [ f"qemu-system-{arch}" ]
if arch == platform.machine():
binary_names.append("qemu-kvm")
for binary_name in binary_names:
if "QEMU_BUILD_DIR" in os.environ:
p = os.path.join(os.environ["QEMU_BUILD_DIR"], binary_name)
if os.path.isfile(p):
return p
else:
exit_error(f"Can't find {binary_name}")
qemu_bin_dirs = ["/usr/bin", "/usr/libexec"]
if "PATH" in os.environ:
qemu_bin_dirs += os.environ["PATH"].split(":")
for d in qemu_bin_dirs:
p = os.path.join(d, binary_name)
if os.path.isfile(p):
return p
exit_error(f"Can't find {binary_name}")
def qemu_available_accels(qemu):
cmd = qemu + ' -accel help'
info = subprocess.check_output(cmd.split(" ")).decode('utf-8')
accel_list = []
for accel in ('kvm', 'xen', 'hvf', 'hax', 'tcg'):
if info.find(accel) > 0:
accel_list.append(accel)
return accel_list
def random_id():
return binascii.b2a_hex(os.urandom(8)).decode('utf8')
def machine_id():
try:
with open("/etc/machine-id", "r") as f:
mid = f.read().strip()
except FileNotFoundError:
if sys.platform == "darwin":
# for macOS
import plistlib
cmd = "ioreg -rd1 -c IOPlatformExpertDevice -a"
plist_data = subprocess.check_output(cmd.split(" "))
mid = plistlib.loads(plist_data)[0]["IOPlatformUUID"].replace("-","")
else:
# fallback for the other distros
hostname = socket.gethostname()
mid = ''.join(hex(ord(x))[2:] for x in (hostname*16)[:16])
return mid
def generate_mac_address():
# create a new mac address based on our machine id
data = machine_id()
maclst = ["FE"] + [data[x:x+2] for x in range(-12, -2, 2)]
return ":".join(maclst)
def run_http_server(path):
writer, reader = socket.socketpair(socket.AF_UNIX, socket.SOCK_STREAM)
child_pid = os.fork()
if child_pid == 0:
reader.close()
# Child
os.chdir(path)
class HTTPHandler(http.server.SimpleHTTPRequestHandler):
def log_message(self, format, *args):
pass # Silence logs
httpd = socketserver.TCPServer(("127.0.0.1", 0), HTTPHandler)
writer.send(str(httpd.server_address[1]).encode("utf8"))
writer.close()
httpd.serve_forever()
sys.exit(0)
# Parent
writer.close()
atexit.register(os.kill, child_pid,signal.SIGTERM)
http_port = int(reader.recv(128).decode("utf8"))
reader.close()
return http_port
def find_ovmf(args):
dirs = [
"~/.local/share/ovmf",
"/usr/share/OVMF",
"/usr/share/edk2/ovmf/"
]
if args.ovmf_dir:
dirs.append(args.ovmf_dir)
for d in dirs:
path = os.path.expanduser(d)
if os.path.exists(path):
return path
raise RuntimeError("Could not find OMVF")
# location can differ depending on how qemu is installed
def find_edk2():
dirs = [
"/usr/local/share/qemu",
"/opt/homebrew/share/qemu"
]
for d in dirs:
path = os.path.expanduser(d)
if os.path.exists(path):
return path
raise RuntimeError("Could not find edk2 directory")
def qemu_run_command(qmp_socket_path, command):
sock2 = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
sock2.connect(qmp_socket_path)
r = sock2.recv(1024)
sock2.send('{"execute":"qmp_capabilities"}\n'.encode("utf8"))
r = sock2.recv(1024)
sock2.send(f'{command}\n'.encode("utf8"))
r = sock2.recv(1024)
sock2.close()
def virtio_serial_connect(virtio_socket_path):
sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
while True:
time.sleep(0.1)
try:
sock.connect(virtio_socket_path)
return sock
except FileNotFoundError:
pass
def available_tcp_port(port_range_from = 1024):
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
port = port_range_from
port_range_to = port_range_from + 32 # limit for retry
while port < port_range_to:
try:
s.bind(('', port))
except OSError:
port += 1
continue
break
s.close()
return port
class WatchdogCommand:
START = 1
STOP = 2
def __init__(self, op, arg = None):
self.op = op
self.arg = arg
def parse_watchdog_commands(sock):
commands = []
data = sock.recv(16).decode("utf8")
for l in data.splitlines():
if l.startswith("START"):
try:
arg = int(l[5:])
except ValueError:
arg = 30 # Default if not specified
commands.append( WatchdogCommand(WatchdogCommand.START, arg) )
elif l.startswith("STOP"):
commands.append( WatchdogCommand(WatchdogCommand.STOP) )
else:
print_verbose(f"Unsupported watchdog command {l}")
return commands
def run_watchdog(watch_socket_path, qmp_socket_path):
sock = virtio_serial_connect(watch_socket_path)
p = select.poll()
p.register(sock, select.POLLIN)
watchdog_timeout = None
watchdog_delay = 30
while True:
timeout = None
if watchdog_timeout != None:
timeout = max(watchdog_timeout - time.time(), 0) * 1000
poll_res = p.poll(timeout)
if len(poll_res) > 0:
v = poll_res[0][1]
if v & select.POLLHUP:
sys.exit(0)
commands = parse_watchdog_commands(sock)
for cmd in commands:
if cmd.op == WatchdogCommand.START:
print_verbose(f"Starting watchdog for {cmd.arg} sec")
watchdog_timeout = time.time() + cmd.arg
if cmd.op == WatchdogCommand.STOP:
print_verbose(f"Stopped watchdog")
watchdog_timeout = None
if watchdog_timeout != None and time.time() >= watchdog_timeout:
print_verbose(f"Triggering watchdog")
qemu_run_command(qmp_socket_path, '{"execute": "system_reset"}')
# Queue a new timeout in case the next boot fails, until disabled
watchdog_timeout = time.time() + watchdog_delay
def main():
parser = argparse.ArgumentParser(description="Boot virtual machine images")
parser.add_argument("--verbose", default=False, action="store_true")
parser.add_argument("--arch", default=platform.machine(), action="store",
help=f"Arch to run for (default {platform.machine()})")
parser.add_argument("--publish-dir", action="store",
help=f"Publish the specified directory over http in the vm")
parser.add_argument("--memory", default="2G",
help=f"Memory size (default 2G)")
parser.add_argument("--nographics", default=False, action="store_true",
help=f"Run without graphics")
parser.add_argument("--watchdog", default=False, action="store_true",
help=f"Enable watchdog")
parser.add_argument("--tpm2", default=False, action="store_true",
help=f"Enable TPM2")
parser.add_argument("--snapshot", default=False, action="store_true",
help=f"Work on a snapshot of the image")
parser.add_argument("--ovmf-dir", action="store",
help="Specify directory for OVMF files (Open Virtual Machine Firmware)")
parser.add_argument("--secureboot", dest="secureboot", action="store_true", default=False,
help="Enable SecureBoot")
parser.add_argument("--ssh-port", type=int, default=2222,
help="SSH port forwarding to SSH_PORT (default 2222)")
parser.add_argument("--cdrom", action="store",
help="Specify .iso to load")
parser.add_argument("image", type=str, help="The image to boot")
parser.add_argument('extra_args', nargs=argparse.REMAINDER, metavar="...", help="extra qemu arguments")
args = parser.parse_args(sys.argv[1:])
global is_verbose
is_verbose = args.verbose
# arm64 is an alias for aarch64 on macOS
if args.arch == "arm64":
args.arch = "aarch64"
qemu = find_qemu(args.arch)
accel_list = qemu_available_accels(qemu)
qemu_args = [qemu]
if args.arch == "x86_64":
machine = "q35"
default_cpu = "qemu64,+ssse3,+sse4.1,+sse4.2,+popcnt"
ovmf = find_ovmf(args)
if args.secureboot:
qemu_args += [
"-drive", f"file={ovmf}/OVMF_CODE.secboot.fd,if=pflash,format=raw,unit=0,readonly=on",
"-drive", f"file={ovmf}/OVMF_VARS.secboot.fd,if=pflash,format=raw,unit=1,snapshot=on,readonly=off",
]
else:
qemu_args += [
"-drive", f"file={ovmf}/OVMF_CODE.fd,if=pflash,format=raw,unit=0,readonly=on",
"-drive", f"file={ovmf}/OVMF_VARS.fd,if=pflash,format=raw,unit=1,snapshot=on,readonly=off",
]
elif args.arch == "aarch64":
machine = "virt"
default_cpu = "cortex-a57"
if sys.platform == "darwin":
edk2 = find_edk2()
qemu_args += [
"-device", "virtio-gpu-pci", # for display
"-display", "default,show-cursor=on", # for display
"-device", "qemu-xhci", # for keyboard
"-device", "usb-kbd", # for keyboard
"-device", "usb-tablet", # for mouse
"-smp", str(os.cpu_count()), # for max cores
"-drive", f"file={edk2}/edk2-aarch64-code.fd,if=pflash,format=raw,unit=0,readonly=on",
"-drive", f"file={edk2}/edk2-arm-vars.fd,if=pflash,format=raw,unit=1,snapshot=on,readonly=off"
]
else:
qemu_args += [
"-bios", "/usr/share/edk2/aarch64/QEMU_EFI.fd",
"-boot", "efi"
]
else:
exit_error(f"unsupported architecture {args.arch}")
accel_enabled = True
if 'kvm' in accel_list and os.path.exists("/dev/kvm"):
qemu_args += ['-enable-kvm']
elif 'hvf' in accel_list:
qemu_args += ['-accel', 'hvf']
else:
accel_enabled = False
print_verbose("Acceleration: off")
qemu_args += [
"-m", str(args.memory),
"-machine", machine,
"-cpu", "host" if accel_enabled else default_cpu
]
guestfwds=""
if args.publish_dir:
if shutil.which("netcat") is None:
print("Command `netcat` not found in path, ignoring publish-dir")
else:
httpd_port = run_http_server(args.publish_dir)
guestfwds = f"guestfwd=tcp:10.0.2.100:80-cmd:netcat 127.0.0.1 {httpd_port},"
print_verbose(f"publishing {args.publish_dir} on http://10.0.2.100/")
portfwd = {
available_tcp_port(args.ssh_port): 22
}
for local, remote in portfwd.items():
print_verbose(f"port: {local} → {remote}")
fwds = [f"hostfwd=tcp::{h}-:{g}" for h, g in portfwd.items()]
macstr = generate_mac_address()
print_verbose(f"MAC: {macstr}")
qemu_args += [
"-device", f"virtio-net-pci,netdev=n0,mac={macstr}",
"-netdev", "user,id=n0,net=10.0.2.0/24," + guestfwds + ",".join(fwds),
]
if args.nographics:
qemu_args += ["-nographic"]
runvm_id = random_id()
tmpdir = tempfile.TemporaryDirectory(prefix=f"runvm-{runvm_id}")
watchdog_pid = 0
if args.watchdog:
qmp_socket_path = os.path.join(tmpdir.name, "qmp-socket")
watch_socket_path = os.path.join(tmpdir.name, "watch-socket")
qemu_args += [
"-qmp", f"unix:{qmp_socket_path},server=on,wait=off",
"-device", "virtio-serial", "-chardev", f"socket,path={watch_socket_path},server=on,wait=off,id=watchdog",
"-device", "virtserialport,chardev=watchdog,name=watchdog.0"
]
watchdog_pid = os.fork()
if watchdog_pid == 0:
run_watchdog(watch_socket_path, qmp_socket_path)
sys.exit(0)
if args.tpm2:
if shutil.which("swtpm") is None:
exit_error("Command `swtpm` not found in path, this is needed for tpm2 support")
tpm2_socket = os.path.join(tmpdir.name, "tpm-socket")
if args.snapshot:
tpm2_path = os.path.join(tmpdir.name, "tpm2_state")
else:
tpm2_path = ".tpm2_state"
os.makedirs(tpm2_path, exist_ok=True)
swtpm_args = ["swtpm", "socket", "--tpm2", "--tpmstate", f"dir={tpm2_path}", "--ctrl", f"type=unixio,path={tpm2_socket}" ]
res = subprocess.Popen(swtpm_args)
qemu_args += [
"-chardev", f"socket,id=chrtpm,path={tpm2_socket}",
"-tpmdev", "emulator,id=tpm0,chardev=chrtpm",
"-device", "tpm-tis,tpmdev=tpm0"
]
print_verbose(f"Image: {args.image}")
if args.image.endswith(".raw"):
qemu_args += [
"-drive", f"file={args.image},index=0,media=disk,format=raw,if=virtio,snapshot={bool_arg(args.snapshot)}",
]
else: # assume qcow2
qemu_args += [
"-drive", f"file={args.image},index=0,media=disk,format=qcow2,if=virtio,snapshot={bool_arg(args.snapshot)}",
]
if args.cdrom:
qemu_args += [
"-cdrom", args.cdrom,
"-boot", "d"
]
qemu_args += args.extra_args
print_verbose(f"Running: {' '.join(qemu_args)}")
try:
res = subprocess.run(qemu_args, check=False)
except KeyboardInterrupt:
exit_error("Aborted")
if watchdog_pid:
os.kill(watchdog_pid, signal.SIGTERM)
tmpdir.cleanup()
return res.returncode
if __name__ == "__main__":
sys.exit(main())
@@ -0,0 +1,18 @@
def intersect(x;y):
( (x|unique) + (y|unique) | sort) as $sorted
| reduce range(1; $sorted|length) as $i
([];
if $sorted[$i] == $sorted[$i-1] then . + [$sorted[$i]] else . end) ;
def difference($a; $b):
($a | unique) - $b;
{
cs9: {
common: ((intersect($aarch64;$x86_64)) | sort_by(ascii_downcase)),
arch: {
x86_64: (($x86_64 - $aarch64) | sort_by(ascii_downcase)),
aarch64: (($aarch64 - $x86_64) | sort_by(ascii_downcase))
}
}
}
+88
View File
@@ -0,0 +1,88 @@
#!/usr/bin/env bash
# SPDX-License-Identifier: MIT-0
set -e
[ "$DEBUG" == 'true' ] && set -x
ARGC=$#
if [ $ARGC -ne 3 ]; then
echo "USAGE: $(basename $0) <Image Path> <S3 Bucket Name> <AMI Image Size in GB>"
exit 1
fi
IMAGE_FILE_PATH=$1
IMPORT_BUCKET_NAME=$2
AMI_DISK_SIZE_GB=$3
declare -A ARCHS_MAP=( ["x86_64"]="x86_64" ["aarch64"]="arm64")
IMAGE_NAME="$(basename -- ${IMAGE_FILE_PATH})"
AMI_NAME="${IMAGE_NAME%.*}"
IMAGE_ARCH="${AMI_NAME##*.}"
TMPDIR=$(mktemp -d)
IMAGE_IMPORT_JSON_FILE="${TMPDIR}/image-import.json"
AMI_REGISTER_JSON_FILE="${TMPDIR}/register-ami.json"
aws s3 cp "${IMAGE_FILE_PATH}" "s3://${IMPORT_BUCKET_NAME}"
cat <<EOF > "${IMAGE_IMPORT_JSON_FILE}"
{
"Description": "CentOS Stream 9 with Container support",
"Format": "RAW",
"UserBucket": {
"S3Bucket": "${IMPORT_BUCKET_NAME}",
"S3Key": "${IMAGE_NAME}"
}
}
EOF
echo "Importing image file into snapshot "
IMPORT_TASK_ID=$(aws ec2 import-snapshot --disk-container "file://${IMAGE_IMPORT_JSON_FILE}" | jq -r '.ImportTaskId')
IMPORT_STATUS=$(aws ec2 describe-import-snapshot-tasks --import-task-ids $IMPORT_TASK_ID | jq -r '.ImportSnapshotTasks[].SnapshotTaskDetail.Status')
x=0
while [ "$IMPORT_STATUS" = "active" ] && [ $x -lt 120 ]
do
IMPORT_STATUS=$(aws ec2 describe-import-snapshot-tasks --import-task-ids $IMPORT_TASK_ID | jq -r '.ImportSnapshotTasks[].SnapshotTaskDetail.Status')
IMPORT_STATUS_MSG=$(aws ec2 describe-import-snapshot-tasks --import-task-ids $IMPORT_TASK_ID | jq -r '.ImportSnapshotTasks[].SnapshotTaskDetail.StatusMessage')
echo "Import Status: ${IMPORT_STATUS} / ${IMPORT_STATUS_MSG}"
x=$(( $x + 1 ))
sleep 15
done
if [ $x -eq 120 ]; then
echo "ERROR: Import task taking too long, exiting..."; exit 1;
elif [ "$IMPORT_STATUS" = "completed" ]; then
echo "Import completed Successfully"
else
echo "Import Failed, exiting"; exit 2;
fi
SNAPSHOT_ID=$(aws ec2 describe-import-snapshot-tasks --import-task-ids $IMPORT_TASK_ID | jq -r '.ImportSnapshotTasks[].SnapshotTaskDetail.SnapshotId')
aws ec2 wait snapshot-completed --snapshot-ids $SNAPSHOT_ID
echo "Registering AMI with Snapshot $SNAPSHOT_ID"
cat <<EOF > "${AMI_REGISTER_JSON_FILE}"
{
"Architecture": "${ARCHS_MAP[$IMAGE_ARCH]}",
"BlockDeviceMappings": [
{
"DeviceName": "/dev/sda1",
"Ebs": {
"DeleteOnTermination": true,
"SnapshotId": "${SNAPSHOT_ID}",
"VolumeSize": ${AMI_DISK_SIZE_GB},
"VolumeType": "gp2"
}
}
],
"Description": "CS9 image with container support for ${IMAGE_ARCH}",
"RootDeviceName": "/dev/sda1",
"BootMode": "uefi",
"VirtualizationType": "hvm",
"EnaSupport": true
}
EOF
aws ec2 register-image --name ${AMI_NAME} --cli-input-json="file://${AMI_REGISTER_JSON_FILE}"
echo "AMI name: "${AMI_NAME}
+19
View File
@@ -0,0 +1,19 @@
def basenames:
.path | split("/") | last;
def parseURL:
capture("^((?<scheme>[^:/?#]+):)?(//(?<authority>(?<domain>[^/?#:]*)(:(?<port>[0-9]*))?))?(?<path>[^?#]*)(\\?(?<query>([^#]*)))?(#(?<fragment>(.*)))?");
def splitRPM:
capture("(?<name>(.*))\\.(?<arch>[a-zA-Z0-9_]+).rpm");
def manifestUrls:
.sources["org.osbuild.curl"].items | to_entries[] | .value | parseURL;
def urlsToRpms:
basenames | splitRPM;
def mergeArches:
reduce .[] as $item ({}; .[$item.arch][$item.name] = true) | with_entries(.value = (.value | keys));
manifestUrls | select(.domain == "mirror.stream.centos.org") | urlsToRpms | .name
+50
View File
@@ -0,0 +1,50 @@
#!/usr/bin/bash
# Generates single-file from-scratch and delta update files for all or some of the
# refs in an OSTree repo.
#
# To use it run "generate-deltas REPODIR DESTDIR" which will look at all the refs in the
# repo and make updates to the latest version putting them in the DESTDIR directory.
# To apply these on a live system, do something like:
# $ ostree static-delta apply-offline cs9-x86_64-qemu-upgrade-demo-79da0b2f1b119e99137eaef9680fae9820a9edcd5cac4f6d7c23279498c578f6.update
# $ rpm-ostree rebase 79da0b2f1b119e99137eaef9680fae9820a9edcd5cac4f6d7c23279498c578f6
if [ "$#" -lt 2 ]; then
echo "Usage generate-deltas REPODIR DESTDIR [REFS..]"
exit 1
fi
REPO=$1
DIR=$2
shift 2
if [ "$#" -gt 0 ]; then
REFS="$@"
else
REFS=$(ostree --repo=$REPO refs)
fi
mkdir -p $DIR
NUM_DELTAS=3
for REF in $REFS; do
REF_AS_FILE=$(echo $REF | sed "s%/%-%g" )
HEAD=$(ostree --repo=$REPO rev-parse $REF)
# Generate full update for HEAD:
echo Generating non-delta update for $REF commit $HEAD
ostree static-delta generate --repo=$REPO --inline --min-fallback-size=0 --empty --filename=$DIR/$REF_AS_FILE-$HEAD.update $HEAD
# Generate deltas to HEAD from up to the last 3 parents
PARENT=$HEAD
for i in seq $NUM_DELTAS; do
if ! PARENT=$(ostree --repo=$REPO rev-parse $PARENT^ 2>/dev/null); then
break;
fi
echo Generating delta update for $REF commit $HEAD from commit $PARENT
ostree static-delta generate --repo=$REPO --inline --min-fallback-size=0 --from=$PARENT --filename=$DIR/$REF_AS_FILE-$PARENT-$HEAD.update $HEAD
done
done
+22
View File
@@ -0,0 +1,22 @@
#!/bin/bash
# This is a helper used by the makefile to handle the OSTREE_REPO mpp
# support. It creates a json dict mapping all the refs in the repo
# (if it exists) to the latest commit. This is then passed to osbuild-mpp
# as the ostree_parent_refs variable that is used by the manifests to pick
# the right parent commit.
REPOPATH=$1
FIRST=1
echo -n "{"
if test -d $REPOPATH; then
for ref in $(ostree refs --repo=$REPOPATH); do
if [ $FIRST == 1 ]; then
FIRST=0
else
echo -n ,
fi
echo -n \"$ref\":\"$(ostree rev-parse --repo=$REPOPATH $ref)\"
done
fi
echo -n "}"
+106
View File
@@ -0,0 +1,106 @@
#!/bin/bash
# This is a helper for the makefile rule to build a particular image
# from the preprocessed json manifest. It is a shellscript rather
# than just some make lines because some of the complexities just
# are painful to do in make.
#
# Features:
#
# * Knows what target to export based on the extensions.
# * Knows what the exported filename based on the extensions.
# * Supports building natively or in a VM via osbuildvm.
# * Runs only the minimal required commands as root, and
# chowns the resulting files to the user
# * Supports exporting an extra ostree commit and pulling that
# into an existing repo.
set -e
DEST="$1"
JSON="$2"
TARGET="$3"
IMAGETYPE="$4"
ARCH="$5"
EXTENSION="$6"
# Map extension => export pipeline name
declare -A EXPORT_BY_EXT
EXPORT_BY_EXT[img]=image
EXPORT_BY_EXT[oci.tar]=container
EXPORT_BY_EXT[qcow2]=qcow2
EXPORT_BY_EXT[repo]=ostree-commit
EXPORT_BY_EXT[rootfs]=rootfs
EXPORT_BY_EXT[ext4]=ext4
EXPORT_BY_EXT[tar]=tar
# Map extension to name of exported file by pipeline
declare -A EXPORT_FILE_BY_EXT
EXPORT_FILE_BY_EXT[img]=disk.img
EXPORT_FILE_BY_EXT[qcow2]=disk.qcow2
EXPORT_FILE_BY_EXT[oci.tar]=container.tar
EXPORT_FILE_BY_EXT[repo]=repo
EXPORT_FILE_BY_EXT[rootfs]=
EXPORT_FILE_BY_EXT[ext4]=rootfs.ext4
EXPORT_FILE_BY_EXT[tar]=rootfs.tar
EXPORT=${EXPORT_BY_EXT[${EXTENSION}]}
EXPORT_FILE=${EXPORT_FILE_BY_EXT[${EXTENSION}]}
HOST_ARCH=$(arch)
CURRENT_UIDGID="$(id -u):$(id -g)"
if [ $ARCH == $HOST_ARCH -a $VM == 0 ]; then
SUDO="sudo"
OSBUILD="sudo osbuild"
else
SUDO=
OSBUILD="osbuildvm/osbuildvm --arch=$ARCH"
fi
EXPORT_ARGS="--export $EXPORT"
CHECKPOINT_ARGS=
for CP in $CHECKPOINTS; do
CHECKPOINT_ARGS="${CHECKPOINT_ARGS} --checkpoint ${CP}"
done
CHOWNARGS=
if [ $EXTENSION == repo ]; then
CHOWNARGS=-R # Chown entire repo dir as it doesn't care about permissions
fi
EXPORTDIRS=$OUTPUTDIR/$EXPORT
# If OSTREE_REPO is set, and we're building an image that has an
# ostree commit, then we also export that commit to the repo specified
# by OSTREE_REPO.
ALSO_EXPORT_OSTREE=0
if [ "$OSTREE_REPO" != "" -a "$IMAGETYPE" == "ostree" ]; then
ALSO_EXPORT_OSTREE=1
if [ $EXPORT != "ostree-commit" ]; then
EXPORT_ARGS="$EXPORT_ARGS --export ostree-commit"
EXPORTDIRS="$EXPORTDIRS $OUTPUTDIR/ostree-commit"
fi
# Ensure we have a repo to export to
ostree init --repo=$OSTREE_REPO --mode archive
fi
set -x
$SUDO rm -rf $EXPORTDIRS
mkdir -p $EXPORTDIRS # Own export dirs by user, not root
$OSBUILD $CHECKPOINT_ARGS --store $STOREDIR --output-directory $OUTPUTDIR $EXPORT_ARGS $OSBUILD_ARGS $JSON
if [ $ALSO_EXPORT_OSTREE == "1" ]; then
ostree pull-local --repo=$OSTREE_REPO $OUTPUTDIR/ostree-commit/repo
fi
# Extract and chown exported file
rm -rf $DEST
$SUDO chown $CHOWNARGS $CURRENT_UIDGID $OUTPUTDIR/$EXPORT/$EXPORT_FILE
$SUDO mv $OUTPUTDIR/$EXPORT/$EXPORT_FILE $DEST
$SUDO rm -rf $EXPORTDIRS