Repository: osbuild/osbuild-composer
Pull request #1840 (2021-09-28 05:59:19)

Backport patches and release 33.2
Backported PRs:
- https://github.com/osbuild/osbuild-composer/pull/1706
- https://github.com/osbuild/osbuild-composer/pull/1711
- https://github.com/osbuild/osbuild-composer/pull/1729
- https://github.com/osbuild/osbuild-composer/pull/1798
- https://github.com/osbuild/osbuild-composer/pull/1791
- https://github.com/osbuild/osbuild-composer/pull/1759


Patch:
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 22e276a39..f811afbb8 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -136,6 +136,7 @@ OSTree:
     matrix:
       - RUNNER:
           - openstack/rhel-8.5-x86_64
+          - openstack/rhel-9.0-beta-nightly-x86_64
 
 New OSTree:
   stage: test
@@ -148,6 +149,17 @@ New OSTree:
       - RUNNER:
           - openstack/rhel-8.5-x86_64-large
 
+New OSTree (RHEL9-BETA):
+  stage: test
+  extends: OSTree
+  script:
+    - schutzbot/deploy.sh
+    - /usr/libexec/tests/osbuild-composer/ostree-ng-og.sh
+  parallel:
+    matrix:
+      - RUNNER:
+          - openstack/rhel-9.0-beta-nightly-x86_64
+
 OSTree simplified installer:
   stage: test
   extends: OSTree
@@ -279,6 +291,7 @@ Installer:
     matrix:
       - RUNNER:
           - openstack/rhel-8.5-x86_64
+          - openstack/rhel-9.0-beta-nightly-x86_64
 
 SCHEDULED_CLOUD_CLEANER:
   stage: cleanup
diff --git a/NEWS.md b/NEWS.md
index 03698be3a..b23f379bd 100644
--- a/NEWS.md
+++ b/NEWS.md
@@ -1,3 +1,17 @@
+## CHANGES WITH 33.2:
+
+  * Edge images for 8.5 now ship with bootloader set to none which fixes
+    deploying an update commit.
+  * Edge images for 9.0 have adjusted package sets. Before that, they
+    weren't buildable, or bootable.
+  * Image Installer for 9.0 has now a very similar package set as in 8.5,
+    which makes the image much more usable even with an empty blueprint.
+
+Contributions from: Achilleas Koutsou, Christian Kellner, Diaa Sami,
+                    Tomas Hozza, Yi He
+
+— Liberec, 2021-09-28
+
 ## CHANGES WITH 33.1:
 
   * Install docs in RHEL 8.5 and 9.0 images
diff --git a/internal/distro/rhel85/stage_options.go b/internal/distro/rhel85/stage_options.go
index ba4b02754..9ae5b64a9 100644
--- a/internal/distro/rhel85/stage_options.go
+++ b/internal/distro/rhel85/stage_options.go
@@ -566,7 +566,8 @@ func ostreeConfigStageOptions(repo string, readOnly bool) *osbuild.OSTreeConfigS
 		Repo: repo,
 		Config: &osbuild.OSTreeConfig{
 			Sysroot: &osbuild.SysrootOptions{
-				ReadOnly: common.BoolToPtr(readOnly),
+				ReadOnly:   common.BoolToPtr(readOnly),
+				Bootloader: "none",
 			},
 		},
 	}
diff --git a/internal/distro/rhel90/distro.go b/internal/distro/rhel90/distro.go
index da871a43b..5d915a36d 100644
--- a/internal/distro/rhel90/distro.go
+++ b/internal/distro/rhel90/distro.go
@@ -550,6 +550,9 @@ func newDistro(name, modulePlatformID, ostreeRef string) distro.Distro {
 	// Shared Services
 	edgeServices := []string{
 		"NetworkManager.service", "firewalld.service", "sshd.service",
+		"greenboot-grub2-set-counter", "greenboot-grub2-set-success", "greenboot-healthcheck",
+		"greenboot-rpm-ostree-grub2-check-fallback", "greenboot-status", "greenboot-task-runner",
+		"redboot-auto-reboot", "redboot-task-runner",
 	}
 
 	// Image Definitions
@@ -797,11 +800,8 @@ func newDistro(name, modulePlatformID, ostreeRef string) distro.Distro {
 		filename: "installer.iso",
 		mimeType: "application/x-iso9660-image",
 		packageSets: map[string]rpmmd.PackageSet{
-			buildPkgsKey: x8664InstallerBuildPackageSet(),
-			osPkgsKey: {
-				Include: []string{"lvm2", "policycoreutils", "selinux-policy-targeted"},
-				Exclude: []string{"rng-tools"},
-			},
+			buildPkgsKey:     x8664InstallerBuildPackageSet(),
+			osPkgsKey:        bareMetalPackageSet(),
 			installerPkgsKey: installerPackageSet(),
 		},
 		rpmOstree: false,
diff --git a/internal/distro/rhel90/package_sets.go b/internal/distro/rhel90/package_sets.go
index 25ac5c03c..7843a6fd0 100644
--- a/internal/distro/rhel90/package_sets.go
+++ b/internal/distro/rhel90/package_sets.go
@@ -233,7 +233,7 @@ func edgeCommitPackageSet() rpmmd.PackageSet {
 	return rpmmd.PackageSet{
 		Include: []string{
 			"redhat-release", "glibc", "glibc-minimal-langpack",
-			/*"nss-altfiles", see rhbz#1916260 */ "dracut-config-generic", "dracut-network",
+			"nss-altfiles", "dracut-config-generic", "dracut-network",
 			"basesystem", "bash", "platform-python", "shadow-utils", "chrony",
 			"setup", "shadow-utils", "sudo", "systemd", "coreutils",
 			"util-linux", "curl", "vim-minimal", "rpm", "rpm-ostree", "polkit",
@@ -279,21 +279,6 @@ func aarch64EdgeCommitPackageSet() rpmmd.PackageSet {
 // INSTALLER PACKAGE SET
 func installerPackageSet() rpmmd.PackageSet {
 	// TODO: simplify
-	/* TODO: These packages were temporarily removed because they don't
-	  exist in RHEL 9:
-		- dump
-		- gfs2-utils
-		- iwl3945-firmware
-		- iwl4965-firmware
-		- iwl6000-firmware
-		- libertas-sd8686-firmware
-		- libertas-sd8787-firmware
-		- libertas-usb8388-firmware
-		- libertas-usb8388-olpc-firmware
-		- libreport-rhel-anaconda-bugzilla
-		- metacity
-		- system-storage-manager
-	*/
 	return rpmmd.PackageSet{
 		Include: []string{
 			"aajohan-comfortaa-fonts", "abattis-cantarell-fonts",
@@ -304,7 +289,7 @@ func installerPackageSet() rpmmd.PackageSet {
 			"dejavu-sans-mono-fonts", "device-mapper-persistent-data",
 			"dmidecode", "dnf", "dracut-config-generic", "dracut-network",
 			/*"dump",*/ "efibootmgr", "ethtool", "ftp", "gdb-gdbserver", "gdisk",
-			/*"gfs2-utils",*/ "glibc-all-langpacks",
+			/*"gfs2-utils",*/ "glibc-all-langpacks", "gnome-kiosk",
 			"google-noto-sans-cjk-ttc-fonts", "grub2-efi-ia32-cdboot",
 			"grub2-efi-x64-cdboot", "grub2-tools", "grub2-tools-efi",
 			"grub2-tools-extra", "grub2-tools-minimal", "grubby",
@@ -356,30 +341,30 @@ func edgeInstallerPackageSet() rpmmd.PackageSet {
 			"bzip2", "cryptsetup", "curl", "dbus-x11", "dejavu-sans-fonts",
 			"dejavu-sans-mono-fonts", "device-mapper-persistent-data",
 			"dmidecode", "dnf", "dracut-config-generic", "dracut-network",
-			"dump", "efibootmgr", "ethtool", "ftp", "gdb-gdbserver", "gdisk",
-			"gfs2-utils", "glibc-all-langpacks",
+			/*"dump",*/ "efibootmgr", "ethtool", "ftp", "gdb-gdbserver", "gdisk",
+			/*"gfs2-utils",*/ "glibc-all-langpacks", "gnome-kiosk",
 			"google-noto-sans-cjk-ttc-fonts", "grub2-efi-ia32-cdboot",
 			"grub2-efi-x64-cdboot", "grub2-tools", "grub2-tools-efi",
 			"grub2-tools-extra", "grub2-tools-minimal", "grubby",
 			"gsettings-desktop-schemas", "hdparm", "hexedit", "hostname",
 			"initscripts", "ipmitool", "iwl1000-firmware", "iwl100-firmware",
 			"iwl105-firmware", "iwl135-firmware", "iwl2000-firmware",
-			"iwl2030-firmware", "iwl3160-firmware", "iwl3945-firmware",
-			"iwl4965-firmware", "iwl5000-firmware", "iwl5150-firmware",
+			"iwl2030-firmware", "iwl3160-firmware", /*"iwl3945-firmware",*/
+			/*"iwl4965-firmware",*/ "iwl5000-firmware", "iwl5150-firmware",
 			"iwl6000g2a-firmware", "iwl6000g2b-firmware",
 			"iwl6050-firmware", "iwl7260-firmware", "jomolhari-fonts",
 			"kacst-farsi-fonts", "kacst-qurn-fonts", "kbd", "kbd-misc",
 			"kdump-anaconda-addon", "kernel", "khmeros-base-fonts", "less",
-			"libblockdev-lvm-dbus", "libertas-sd8686-firmware",
-			"libertas-sd8787-firmware", "libertas-usb8388-firmware",
-			"libertas-usb8388-olpc-firmware", "libibverbs",
+			"libblockdev-lvm-dbus", /*"libertas-sd8686-firmware",*/
+			/*"libertas-sd8787-firmware",*/ /*"libertas-usb8388-firmware",*/
+			/*"libertas-usb8388-olpc-firmware",*/ "libibverbs",
 			"libreport-plugin-bugzilla", "libreport-plugin-reportuploader",
-			"libreport-rhel-anaconda-bugzilla", "librsvg2", "linux-firmware",
+			/*"libreport-rhel-anaconda-bugzilla",*/ "librsvg2", "linux-firmware",
 			"lklug-fonts", "lohit-assamese-fonts", "lohit-bengali-fonts",
 			"lohit-devanagari-fonts", "lohit-gujarati-fonts",
 			"lohit-gurmukhi-fonts", "lohit-kannada-fonts", "lohit-odia-fonts",
 			"lohit-tamil-fonts", "lohit-telugu-fonts", "lsof", "madan-fonts",
-			"memtest86+", "metacity", "mtr", "mt-st", "net-tools", "nfs-utils",
+			"memtest86+" /*"metacity",*/, "mtr", "mt-st", "net-tools", "nfs-utils",
 			"nmap-ncat", "nm-connection-editor", "nss-tools",
 			"openssh-clients", "openssh-server", "oscap-anaconda-addon",
 			"ostree", "pciutils", "perl-interpreter", "pigz", "plymouth",
@@ -389,7 +374,7 @@ func edgeInstallerPackageSet() rpmmd.PackageSet {
 			"shim-ia32", "shim-x64", "sil-abyssinica-fonts",
 			"sil-padauk-fonts", "sil-scheherazade-fonts", "smartmontools",
 			"smc-meera-fonts", "spice-vdagent", "strace", "syslinux",
-			"systemd", "system-storage-manager", "tar",
+			"systemd" /*"system-storage-manager",*/, "tar",
 			"thai-scalable-waree-fonts", "tigervnc-server-minimal",
 			"tigervnc-server-module", "udisks2", "udisks2-iscsi", "usbutils",
 			"vim-minimal", "volume_key", "wget", "xfsdump", "xfsprogs",
@@ -399,3 +384,23 @@ func edgeInstallerPackageSet() rpmmd.PackageSet {
 		Exclude: nil,
 	}
 }
+
+func bareMetalPackageSet() rpmmd.PackageSet {
+	return rpmmd.PackageSet{
+		Include: []string{
+			"authselect-compat", "chrony", "cockpit-system", "cockpit-ws",
+			"@core", "dhcp-client", "dnf", "dnf-utils", "dosfstools",
+			"insights-client", "iwl1000-firmware", "iwl100-firmware",
+			"iwl105-firmware", "iwl135-firmware", "iwl2000-firmware",
+			"iwl2030-firmware", "iwl3160-firmware", "iwl5000-firmware",
+			"iwl5150-firmware", "iwl6000g2a-firmware", "iwl6000g2b-firmware",
+			"iwl6050-firmware", "iwl7260-firmware", "lvm2", "net-tools",
+			"NetworkManager", "nfs-utils", "oddjob", "oddjob-mkhomedir",
+			"policycoreutils", "psmisc", "python3-jsonschema",
+			"qemu-guest-agent", "redhat-release", "redhat-release-eula",
+			"rsync", "selinux-policy-targeted", "subscription-manager-cockpit",
+			"tar", "tcpdump", "yum",
+		},
+		Exclude: nil,
+	}
+}
diff --git a/internal/osbuild2/ostree_config_stage.go b/internal/osbuild2/ostree_config_stage.go
index ead325685..3a45b570b 100644
--- a/internal/osbuild2/ostree_config_stage.go
+++ b/internal/osbuild2/ostree_config_stage.go
@@ -16,10 +16,11 @@ type OSTreeConfig struct {
 }
 
 type SysrootOptions struct {
-	ReadOnly *bool `json:"readonly,omitempty"`
+	ReadOnly   *bool  `json:"readonly,omitempty"`
+	Bootloader string `json:"bootloader,omitempty"`
 }
 
-// A new org.osbuild.ostree.init stage to create an OSTree repository
+// A new org.osbuild.ostree.config stage to configure an OSTree repository
 func NewOSTreeConfigStage(options *OSTreeConfigStageOptions) *Stage {
 	return &Stage{
 		Type:    "org.osbuild.ostree.config",
diff --git a/osbuild-composer.spec b/osbuild-composer.spec
index 02a17d3af..ebf54ecf3 100644
--- a/osbuild-composer.spec
+++ b/osbuild-composer.spec
@@ -4,7 +4,7 @@
 
 %global goipath         github.com/osbuild/osbuild-composer
 
-Version:        33.1
+Version:        33.2
 
 %gometa
 
@@ -378,6 +378,7 @@ Requires:   python3-lxml
 Requires:   httpd
 Requires:   mod_ssl
 Requires:   openssl
+Requires:   firewalld
 # see https://bugzilla.redhat.com/show_bug.cgi?id=1986333
 %if 0%{?rhel} && 0%{?rhel} != 9
 Requires:   podman-plugins
diff --git a/tools/provision.sh b/tools/provision.sh
index ec4bb8021..25badacc8 100755
--- a/tools/provision.sh
+++ b/tools/provision.sh
@@ -20,7 +20,12 @@ elif [[ $ID == rhel || $ID == centos ]] && [[ ${VERSION_ID%.*} == 9 ]]; then
     sudo dnf install -y ./redhat-internal-cert-install-0.1-23.el7.csb.noarch.rpm dnf-plugins-core
     sudo dnf copr enable -y copr.devel.redhat.com/osbuild-team/epel-el9 "rhel-9.dev-$ARCH"
     # koji is not available yet apparently
-    sudo dnf install -y ansible
+    # jmespath required for json_query
+    sudo dnf install -y ansible python3-jmespath
+
+    # json_query filter, used in our ansible playbooks, was moved to the
+    # 'community.general' collection
+    sudo ansible-galaxy collection install community.general
 fi
 
 sudo mkdir -p /etc/osbuild-composer


Test patch:
diff --git a/test/cases/installers.sh b/test/cases/installers.sh
index 50f875072..c19c91007 100755
--- a/test/cases/installers.sh
+++ b/test/cases/installers.sh
@@ -115,6 +115,10 @@ SSH_USER="admin"
 IMAGE_KEY="osbuild-composer-installer-test-${TEST_UUID}"
 GUEST_ADDRESS=192.168.100.50
 
+if [[ ${WORKSPACE:-empty} == empty ]]; then
+    WORKSPACE=$(mktemp -d)
+fi
+
 # Set up temporary files.
 TEMPDIR=$(mktemp -d)
 BLUEPRINT_FILE=${TEMPDIR}/blueprint.toml
@@ -166,13 +170,21 @@ build_image() {
     # Start the compose.
     greenprint "🚀 Starting compose"
     sudo composer-cli --json compose start "$blueprint_name" "$image_type" | tee "$COMPOSE_START"
-    COMPOSE_ID=$(jq -r '.build_id' "$COMPOSE_START")
+    if rpm -q --quiet weldr-client; then
+        COMPOSE_ID=$(jq -r '.body.build_id' "$COMPOSE_START")
+    else
+        COMPOSE_ID=$(jq -r '.build_id' "$COMPOSE_START")
+    fi
 
     # Wait for the compose to finish.
     greenprint "⏱ Waiting for compose to finish: ${COMPOSE_ID}"
     while true; do
         sudo composer-cli --json compose info "${COMPOSE_ID}" | tee "$COMPOSE_INFO" > /dev/null
-        COMPOSE_STATUS=$(jq -r '.queue_status' "$COMPOSE_INFO")
+        if rpm -q --quiet weldr-client; then
+            COMPOSE_STATUS=$(jq -r '.body.queue_status' "$COMPOSE_INFO")
+        else
+            COMPOSE_STATUS=$(jq -r '.queue_status' "$COMPOSE_INFO")
+        fi
 
         # Is the compose finished?
         if [[ $COMPOSE_STATUS != RUNNING ]] && [[ $COMPOSE_STATUS != WAITING ]]; then
@@ -267,7 +279,7 @@ name = "openssh-server"
 version = "*"
 
 [[packages]]
-name = "python36"
+name = "python3"
 version = "*"
 
 [[customizations.user]]
@@ -371,7 +383,7 @@ ansible_ssh_common_args="-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/
 EOF
 
 # Test OS
-sudo ANSIBLE_STDOUT_CALLBACK=debug ansible-playbook -v -i "${TEMPDIR}"/inventory /usr/share/tests/osbuild-composer/ansible/check_install.yaml || RESULTS=0
+sudo ansible-playbook -v -i "${TEMPDIR}"/inventory /usr/share/tests/osbuild-composer/ansible/check_install.yaml || RESULTS=0
 check_result
 
 # Final success clean up
diff --git a/test/cases/ostree-ng-og.sh b/test/cases/ostree-ng-og.sh
new file mode 100644
index 000000000..975f5947e
--- /dev/null
+++ b/test/cases/ostree-ng-og.sh
@@ -0,0 +1,648 @@
+#!/bin/bash
+set -euo pipefail
+
+# Provision the software under test.
+/usr/libexec/osbuild-composer-test/provision.sh
+
+# Get OS data.
+source /etc/os-release
+ARCH=$(uname -m)
+
+# Colorful output.
+function greenprint {
+    echo -e "\033[1;32m${1}\033[0m"
+}
+
+# Start libvirtd and test it.
+greenprint "🚀 Starting libvirt daemon"
+sudo systemctl start libvirtd
+sudo virsh list --all > /dev/null
+
+# Set a customized dnsmasq configuration for libvirt so we always get the
+# same address on bootup.
+sudo tee /tmp/integration.xml > /dev/null << EOF
+<network>
+  <name>integration</name>
+  <uuid>1c8fe98c-b53a-4ca4-bbdb-deb0f26b3579</uuid>
+  <forward mode='nat'>
+    <nat>
+      <port start='1024' end='65535'/>
+    </nat>
+  </forward>
+  <bridge name='integration' stp='on' delay='0'/>
+  <mac address='52:54:00:36:46:ef'/>
+  <ip address='192.168.100.1' netmask='255.255.255.0'>
+    <dhcp>
+      <range start='192.168.100.2' end='192.168.100.254'/>
+      <host mac='34:49:22:B0:83:30' name='vm-bios' ip='192.168.100.50'/>
+      <host mac='34:49:22:B0:83:31' name='vm-uefi' ip='192.168.100.51'/>
+    </dhcp>
+  </ip>
+</network>
+EOF
+if ! sudo virsh net-info integration > /dev/null 2>&1; then
+    sudo virsh net-define /tmp/integration.xml
+fi
+if [[ $(sudo virsh net-info integration | grep 'Active' | awk '{print $2}') == 'no' ]]; then
+    sudo virsh net-start integration
+fi
+
+# Allow anyone in the wheel group to talk to libvirt.
+greenprint "🚪 Allowing users in wheel group to talk to libvirt"
+sudo tee /etc/polkit-1/rules.d/50-libvirt.rules > /dev/null << EOF
+polkit.addRule(function(action, subject) {
+    if (action.id == "org.libvirt.unix.manage" &&
+        subject.isInGroup("adm")) {
+            return polkit.Result.YES;
+    }
+});
+EOF
+
+# Set up variables.
+OSTREE_REF="test/rhel/9/${ARCH}/edge"
+OS_VARIANT="rhel9-unknown"
+TEST_UUID=$(uuidgen)
+IMAGE_KEY="osbuild-composer-ostree-test-${TEST_UUID}"
+BIOS_GUEST_ADDRESS=192.168.100.50
+UEFI_GUEST_ADDRESS=192.168.100.51
+PROD_REPO_URL=http://192.168.100.1/repo
+PROD_REPO=/var/www/html/repo
+STAGE_REPO_ADDRESS=192.168.200.1
+STAGE_REPO_URL="http://${STAGE_REPO_ADDRESS}/repo/"
+QUAY_REPO_URL="docker://quay.io/osbuild/testing-rhel-edge-push"
+QUAY_REPO_TAG=$(tr -dc a-z0-9 < /dev/urandom | head -c 4 ; echo '')
+ARTIFACTS="ci-artifacts"
+mkdir -p "${ARTIFACTS}"
+
+# Set up temporary files.
+TEMPDIR=$(mktemp -d)
+BLUEPRINT_FILE=${TEMPDIR}/blueprint.toml
+KS_FILE=${TEMPDIR}/ks.cfg
+COMPOSE_START=${TEMPDIR}/compose-start-${IMAGE_KEY}.json
+COMPOSE_INFO=${TEMPDIR}/compose-info-${IMAGE_KEY}.json
+
+# SSH setup.
+SSH_OPTIONS=(-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o ConnectTimeout=5)
+SSH_DATA_DIR=$(/usr/libexec/osbuild-composer-test/gen-ssh.sh)
+SSH_KEY=${SSH_DATA_DIR}/id_rsa
+SSH_KEY_PUB=$(cat "${SSH_KEY}".pub)
+
+if [[ "${ID}-${VERSION_ID}" != "rhel-9.0" ]]; then
+        echo "unsupported distro: ${ID}-${VERSION_ID}"
+        exit 1
+fi
+
+CONTAINER_TYPE=edge-container
+CONTAINER_FILENAME=container.tar
+INSTALLER_TYPE=edge-installer
+INSTALLER_FILENAME=installer.iso
+
+
+# Get the compose log.
+get_compose_log () {
+    COMPOSE_ID=$1
+    LOG_FILE=${ARTIFACTS}/osbuild-${ID}-${VERSION_ID}-${COMPOSE_ID}.log
+
+    # Download the logs.
+    sudo composer-cli compose log "$COMPOSE_ID" | tee "$LOG_FILE" > /dev/null
+}
+
+# Get the compose metadata.
+get_compose_metadata () {
+    COMPOSE_ID=$1
+    METADATA_FILE=${ARTIFACTS}/osbuild-${ID}-${VERSION_ID}-${COMPOSE_ID}.json
+
+    # Download the metadata.
+    sudo composer-cli compose metadata "$COMPOSE_ID" > /dev/null
+
+    # Find the tarball and extract it.
+    TARBALL=$(basename "$(find . -maxdepth 1 -type f -name "*-metadata.tar")")
+    tar -xf "$TARBALL" -C "${TEMPDIR}"
+    rm -f "$TARBALL"
+
+    # Move the JSON file into place.
+    cat "${TEMPDIR}"/"${COMPOSE_ID}".json | jq -M '.' | tee "$METADATA_FILE" > /dev/null
+}
+
+# Build ostree image.
+build_image() {
+    blueprint_name=$1
+    image_type=$2
+
+    # Get worker unit file so we can watch the journal.
+    WORKER_UNIT=$(sudo systemctl list-units | grep -o -E "osbuild.*worker.*\.service")
+    sudo journalctl -af -n 1 -u "${WORKER_UNIT}" &
+    WORKER_JOURNAL_PID=$!
+    # Stop watching the worker journal when exiting.
+    trap 'sudo pkill -P ${WORKER_JOURNAL_PID}' EXIT
+
+    # Start the compose.
+    greenprint "🚀 Starting compose"
+    if [ $# -eq 3 ]; then
+        repo_url=$3
+        sudo composer-cli --json compose start-ostree --ref "$OSTREE_REF" --url "$repo_url" "$blueprint_name" "$image_type" | tee "$COMPOSE_START"
+    else
+        sudo composer-cli --json compose start-ostree --ref "$OSTREE_REF" "$blueprint_name" "$image_type" | tee "$COMPOSE_START"
+    fi
+    COMPOSE_ID=$(jq -r '.body.build_id' "$COMPOSE_START")
+
+    # Wait for the compose to finish.
+    greenprint "⏱ Waiting for compose to finish: ${COMPOSE_ID}"
+    while true; do
+        sudo composer-cli --json compose info "${COMPOSE_ID}" | tee "$COMPOSE_INFO" > /dev/null
+        COMPOSE_STATUS=$(jq -r '.body.queue_status' "$COMPOSE_INFO")
+
+        # Is the compose finished?
+        if [[ $COMPOSE_STATUS != RUNNING ]] && [[ $COMPOSE_STATUS != WAITING ]]; then
+            break
+        fi
+
+        # Wait 30 seconds and try again.
+        sleep 5
+    done
+
+    # Capture the compose logs from osbuild.
+    greenprint "💬 Getting compose log and metadata"
+    get_compose_log "$COMPOSE_ID"
+    get_compose_metadata "$COMPOSE_ID"
+
+    # Kill the journal monitor immediately and remove the trap
+    sudo pkill -P ${WORKER_JOURNAL_PID}
+    trap - EXIT
+
+    # Did the compose finish with success?
+    if [[ $COMPOSE_STATUS != FINISHED ]]; then
+        echo "Something went wrong with the compose. 😢"
+        exit 1
+    fi
+}
+
+# Wait for the ssh server up to be.
+wait_for_ssh_up () {
+    SSH_STATUS=$(sudo ssh "${SSH_OPTIONS[@]}" -i "${SSH_KEY}" admin@"${1}" '/bin/bash -c "echo -n READY"')
+    if [[ $SSH_STATUS == READY ]]; then
+        echo 1
+    else
+        echo 0
+    fi
+}
+
+# Clean up our mess.
+clean_up () {
+    greenprint "🧼 Cleaning up"
+    # Remove tag from quay.io repo
+    skopeo delete --creds "${QUAY_USERNAME}:${QUAY_PASSWORD}" "${QUAY_REPO_URL}:${QUAY_REPO_TAG}"
+
+    # Clear vm
+    if [[ $(sudo virsh domstate "${IMAGE_KEY}-uefi") == "running" ]]; then
+        sudo virsh destroy "${IMAGE_KEY}-uefi"
+    fi
+    sudo virsh undefine "${IMAGE_KEY}-uefi" --nvram
+    # Remove qcow2 file.
+    sudo rm -f "$LIBVIRT_UEFI_IMAGE_PATH"
+
+    # Remove any status containers if exist
+    sudo podman ps -a -q --format "{{.ID}}" | sudo xargs --no-run-if-empty podman rm -f
+    # Remove all images
+    sudo podman rmi -f -a
+
+    # Remove prod repo
+    sudo rm -rf "$PROD_REPO"
+
+    # Remomve tmp dir.
+    sudo rm -rf "$TEMPDIR"
+
+    # Stop prod repo http service
+    sudo systemctl disable --now httpd
+}
+
+# Test result checking
+check_result () {
+    greenprint "🎏 Checking for test result"
+    if [[ $RESULTS == 1 ]]; then
+        greenprint "💚 Success"
+    else
+        greenprint "❌ Failed"
+        clean_up
+        exit 1
+    fi
+}
+
+###########################################################
+##
+## Prepare edge prod and stage repo
+##
+###########################################################
+greenprint "🔧 Prepare edge prod repo"
+# Start prod repo web service
+# osbuild-composer-tests have mod_ssl as a dependency. The package installs
+# an example configuration which automatically enabled httpd on port 443, but
+# that one is already in use. Remove the default configuration as it is useless
+# anyway.
+sudo rm -f /etc/httpd/conf.d/ssl.conf
+sudo systemctl enable --now httpd.service
+
+# Have a clean prod repo
+sudo rm -rf "$PROD_REPO"
+sudo mkdir -p "$PROD_REPO"
+sudo ostree --repo="$PROD_REPO" init --mode=archive
+sudo ostree --repo="$PROD_REPO" remote add --no-gpg-verify edge-stage "$STAGE_REPO_URL"
+
+# Prepare stage repo network
+greenprint "🔧 Prepare stage repo network"
+sudo podman network inspect edge >/dev/null 2>&1 || sudo podman network create --driver=bridge --subnet=192.168.200.0/24 --ip-range=192.168.200.0/24 --gateway=192.168.200.254 edge
+
+##########################################################
+##
+## edge container image for building installer image
+##
+##########################################################
+
+# Write a blueprint for ostree image.
+tee "$BLUEPRINT_FILE" > /dev/null << EOF
+name = "container"
+description = "A base rhel-edge container image"
+version = "0.0.1"
+modules = []
+groups = []
+
+[[packages]]
+name = "python3"
+version = "*"
+
+[[customizations.user]]
+name = "admin"
+description = "Administrator account"
+password = "\$6\$GRmb7S0p8vsYmXzH\$o0E020S.9JQGaHkszoog4ha4AQVs3sk8q0DvLjSMxoxHBKnB2FBXGQ/OkwZQfW/76ktHd0NX5nls2LPxPuUdl."
+key = "${SSH_KEY_PUB}"
+home = "/home/admin/"
+groups = ["wheel"]
+EOF
+
+greenprint "📄 container blueprint"
+cat "$BLUEPRINT_FILE"
+
+# Prepare the blueprint for the compose.
+greenprint "📋 Preparing container blueprint"
+sudo composer-cli blueprints push "$BLUEPRINT_FILE"
+sudo composer-cli blueprints depsolve container
+
+# Build container image.
+build_image container "${CONTAINER_TYPE}"
+
+# Download the image
+greenprint "📥 Downloading the container image"
+sudo composer-cli compose image "${COMPOSE_ID}" > /dev/null
+
+# Clear stage repo running env
+greenprint "🧹 Clearing stage repo running env"
+# Remove any status containers if exist
+sudo podman ps -a -q --format "{{.ID}}" | sudo xargs --no-run-if-empty podman rm -f
+# Remove all images
+sudo podman rmi -f -a
+
+# Deal with stage repo image
+greenprint "🗜 Pushing image to quay.io"
+IMAGE_FILENAME="${COMPOSE_ID}-${CONTAINER_FILENAME}"
+skopeo copy --dest-creds "${QUAY_USERNAME}:${QUAY_PASSWORD}" "oci-archive:${IMAGE_FILENAME}" "${QUAY_REPO_URL}:${QUAY_REPO_TAG}"
+greenprint "Downloading image from quay.io"
+sudo podman login quay.io --username "${QUAY_USERNAME}" --password "${QUAY_PASSWORD}"
+sudo podman pull "${QUAY_REPO_URL}:${QUAY_REPO_TAG}"
+sudo podman images
+greenprint "🗜 Running the image"
+sudo podman run -d --name rhel-edge --network edge --ip "$STAGE_REPO_ADDRESS" "${QUAY_REPO_URL}:${QUAY_REPO_TAG}"
+# Clear image file
+sudo rm -f "$IMAGE_FILENAME"
+
+# Wait for container to be running
+until [ "$(sudo podman inspect -f '{{.State.Running}}' rhel-edge)" == "true" ]; do
+    sleep 1;
+done;
+
+# Sync installer edge content
+greenprint "📡 Sync installer content from stage repo"
+sudo ostree --repo="$PROD_REPO" pull --mirror edge-stage "$OSTREE_REF"
+
+# Clean compose and blueprints.
+greenprint "🧽 Clean up container blueprint and compose"
+sudo composer-cli compose delete "${COMPOSE_ID}" > /dev/null
+sudo composer-cli blueprints delete container > /dev/null
+
+########################################################
+##
+## rhel-edge installer image building from container image
+##
+########################################################
+
+# Write a blueprint for installer image.
+tee "$BLUEPRINT_FILE" > /dev/null << EOF
+name = "installer"
+description = "A rhel-edge installer image"
+version = "0.0.1"
+modules = []
+groups = []
+EOF
+
+greenprint "📄 installer blueprint"
+cat "$BLUEPRINT_FILE"
+
+# Prepare the blueprint for the compose.
+greenprint "📋 Preparing installer blueprint"
+sudo composer-cli blueprints push "$BLUEPRINT_FILE"
+sudo composer-cli blueprints depsolve installer
+
+# Build installer image.
+# Test --url arg following by URL with tailling slash for bz#1942029
+build_image installer "${INSTALLER_TYPE}" "${PROD_REPO_URL}/"
+
+# Download the image
+greenprint "📥 Downloading the installer image"
+sudo composer-cli compose image "${COMPOSE_ID}" > /dev/null
+ISO_FILENAME="${COMPOSE_ID}-${INSTALLER_FILENAME}"
+sudo mv "${ISO_FILENAME}" /var/lib/libvirt/images
+
+# Clean compose and blueprints.
+greenprint "🧹 Clean up installer blueprint and compose"
+sudo composer-cli compose delete "${COMPOSE_ID}" > /dev/null
+sudo composer-cli blueprints delete installer > /dev/null
+
+########################################################
+##
+## install rhel-edge image with installer(ISO)
+##
+########################################################
+
+# Ensure SELinux is happy with our new images.
+greenprint "👿 Running restorecon on image directory"
+sudo restorecon -Rv /var/lib/libvirt/images/
+
+# Create qcow2 file for virt install.
+greenprint "🖥 Create qcow2 file for virt install"
+LIBVIRT_BIOS_IMAGE_PATH=/var/lib/libvirt/images/${IMAGE_KEY}-bios.qcow2
+LIBVIRT_UEFI_IMAGE_PATH=/var/lib/libvirt/images/${IMAGE_KEY}-uefi.qcow2
+sudo qemu-img create -f qcow2 "${LIBVIRT_BIOS_IMAGE_PATH}" 20G
+sudo qemu-img create -f qcow2 "${LIBVIRT_UEFI_IMAGE_PATH}" 20G
+
+# Write kickstart file for ostree image installation.
+greenprint "📑 Generate kickstart file"
+tee "$KS_FILE" > /dev/null << STOPHERE
+text
+network --bootproto=dhcp --device=link --activate --onboot=on
+
+zerombr
+clearpart --all --initlabel --disklabel=msdos
+autopart --nohome --noswap --type=plain
+ostreesetup --nogpg --osname=rhel-edge --remote=rhel-edge --url=file:///ostree/repo --ref=${OSTREE_REF}
+poweroff
+
+%post --log=/var/log/anaconda/post-install.log --erroronfail
+
+# no sudo password for user admin
+echo -e 'admin\tALL=(ALL)\tNOPASSWD: ALL' >> /etc/sudoers
+
+# delete local ostree repo and add external prod edge repo
+ostree remote delete rhel-edge
+ostree remote add --no-gpg-verify --no-sign-verify rhel-edge ${PROD_REPO_URL}
+%end
+STOPHERE
+
+##################################################
+##
+## Install and test Edge image on BIOS VM
+##
+##################################################
+# Install ostree image via anaconda.
+greenprint "💿 Install ostree image via installer(ISO) on BIOS VM"
+sudo virt-install  --initrd-inject="${KS_FILE}" \
+                   --extra-args="inst.ks=file:/ks.cfg console=ttyS0,115200" \
+                   --name="${IMAGE_KEY}-bios" \
+                   --disk path="${LIBVIRT_BIOS_IMAGE_PATH}",format=qcow2 \
+                   --ram 3072 \
+                   --vcpus 2 \
+                   --network network=integration,mac=34:49:22:B0:83:30 \
+                   --os-type linux \
+                   --os-variant ${OS_VARIANT} \
+                   --location "/var/lib/libvirt/images/${ISO_FILENAME}" \
+                   --nographics \
+                   --noautoconsole \
+                   --wait=-1 \
+                   --noreboot
+
+# Start VM.
+greenprint "📟 Start BIOS VM"
+sudo virsh start "${IMAGE_KEY}-bios"
+
+# Check for ssh ready to go.
+greenprint "🛃 Checking for SSH is ready to go"
+for LOOP_COUNTER in $(seq 0 30); do
+    RESULTS="$(wait_for_ssh_up $BIOS_GUEST_ADDRESS)"
+    if [[ $RESULTS == 1 ]]; then
+        echo "SSH is ready now! 🥳"
+        break
+    fi
+    sleep 10
+done
+
+# Check image installation result
+check_result
+
+# Get ostree commit value.
+greenprint "🕹 Get ostree install commit value"
+INSTALL_HASH=$(curl "${PROD_REPO_URL}/refs/heads/${OSTREE_REF}")
+
+# Run Edge test on BIOS VM
+# Add instance IP address into /etc/ansible/hosts
+sudo tee "${TEMPDIR}"/inventory > /dev/null << EOF
+[ostree_guest]
+${BIOS_GUEST_ADDRESS}
+
+[ostree_guest:vars]
+ansible_python_interpreter=/usr/bin/python3
+ansible_user=admin
+ansible_private_key_file=${SSH_KEY}
+ansible_ssh_common_args="-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null"
+EOF
+
+# Test IoT/Edge OS
+greenprint "📼 Run Edge tests on BIOS VM"
+sudo ansible-playbook -v -i "${TEMPDIR}"/inventory -e image_type=rhel-edge -e ostree_commit="${INSTALL_HASH}" /usr/share/tests/osbuild-composer/ansible/check_ostree.yaml || RESULTS=0
+check_result
+
+# Clean up BIOS VM
+greenprint "🧹 Clean up BIOS VM"
+if [[ $(sudo virsh domstate "${IMAGE_KEY}-bios") == "running" ]]; then
+    sudo virsh destroy "${IMAGE_KEY}-bios"
+fi
+sudo virsh undefine "${IMAGE_KEY}-bios"
+sudo rm -f "$LIBVIRT_BIOS_IMAGE_PATH"
+
+##################################################
+##
+## Install, upgrade and test Edge image on UEFI VM
+##
+##################################################
+# Install ostree image via anaconda.
+greenprint "💿 Install ostree image via installer(ISO) on UEFI VM"
+sudo virt-install  --initrd-inject="${KS_FILE}" \
+                   --extra-args="inst.ks=file:/ks.cfg console=ttyS0,115200" \
+                   --name="${IMAGE_KEY}-uefi"\
+                   --disk path="${LIBVIRT_UEFI_IMAGE_PATH}",format=qcow2 \
+                   --ram 3072 \
+                   --vcpus 2 \
+                   --network network=integration,mac=34:49:22:B0:83:31 \
+                   --os-type linux \
+                   --os-variant ${OS_VARIANT} \
+                   --location "/var/lib/libvirt/images/${ISO_FILENAME}" \
+                   --boot uefi,loader_ro=yes,loader_type=pflash,nvram_template=/usr/share/edk2/ovmf/OVMF_VARS.fd,loader_secure=no \
+                   --nographics \
+                   --noautoconsole \
+                   --wait=-1 \
+                   --noreboot
+
+# Start VM.
+greenprint "💻 Start UEFI VM"
+sudo virsh start "${IMAGE_KEY}-uefi"
+
+# Check for ssh ready to go.
+greenprint "🛃 Checking for SSH is ready to go"
+for LOOP_COUNTER in $(seq 0 30); do
+    RESULTS="$(wait_for_ssh_up $UEFI_GUEST_ADDRESS)"
+    if [[ $RESULTS == 1 ]]; then
+        echo "SSH is ready now! 🥳"
+        break
+    fi
+    sleep 10
+done
+
+# Check image installation result
+check_result
+
+##################################################
+##
+## upgrade rhel-edge with new upgrade commit
+##
+##################################################
+
+# Write a blueprint for ostree image.
+tee "$BLUEPRINT_FILE" > /dev/null << EOF
+name = "upgrade"
+description = "An upgrade rhel-edge container image"
+version = "0.0.2"
+modules = []
+groups = []
+
+[[packages]]
+name = "python3"
+version = "*"
+
+[[packages]]
+name = "wget"
+version = "*"
+
+[[customizations.user]]
+name = "admin"
+description = "Administrator account"
+password = "\$6\$GRmb7S0p8vsYmXzH\$o0E020S.9JQGaHkszoog4ha4AQVs3sk8q0DvLjSMxoxHBKnB2FBXGQ/OkwZQfW/76ktHd0NX5nls2LPxPuUdl."
+key = "${SSH_KEY_PUB}"
+home = "/home/admin/"
+groups = ["wheel"]
+EOF
+
+greenprint "📄 upgrade blueprint"
+cat "$BLUEPRINT_FILE"
+
+# Prepare the blueprint for the compose.
+greenprint "📋 Preparing upgrade blueprint"
+sudo composer-cli blueprints push "$BLUEPRINT_FILE"
+sudo composer-cli blueprints depsolve upgrade
+
+# Build upgrade image.
+build_image upgrade  "${CONTAINER_TYPE}" "$PROD_REPO_URL"
+
+# Download the image
+greenprint "📥 Downloading the upgrade image"
+sudo composer-cli compose image "${COMPOSE_ID}" > /dev/null
+
+# Clear stage repo running env
+greenprint "🧹 Clearing stage repo running env"
+# Remove any status containers if exist
+sudo podman ps -a -q --format "{{.ID}}" | sudo xargs --no-run-if-empty podman rm -f
+# Remove all images
+sudo podman rmi -f -a
+
+# Deal with stage repo container
+greenprint "🗜 Extracting image"
+IMAGE_FILENAME="${COMPOSE_ID}-${CONTAINER_FILENAME}"
+sudo podman pull "oci-archive:${IMAGE_FILENAME}"
+sudo podman images
+# Clear image file
+sudo rm -f "$IMAGE_FILENAME"
+
+# Run edge stage repo
+greenprint "🛰 Running edge stage repo"
+# Get image id to run image
+EDGE_IMAGE_ID=$(sudo podman images --filter "dangling=true" --format "{{.ID}}")
+sudo podman run -d --name rhel-edge --network edge --ip "$STAGE_REPO_ADDRESS" "$EDGE_IMAGE_ID"
+# Wait for container to be running
+until [ "$(sudo podman inspect -f '{{.State.Running}}' rhel-edge)" == "true" ]; do
+    sleep 1;
+done;
+
+# Pull upgrade to prod mirror
+greenprint "⛓ Pull upgrade to prod mirror"
+sudo ostree --repo="$PROD_REPO" pull --mirror edge-stage "$OSTREE_REF"
+sudo ostree --repo="$PROD_REPO" static-delta generate "$OSTREE_REF"
+sudo ostree --repo="$PROD_REPO" summary -u
+
+# Get ostree commit value.
+greenprint "🕹 Get ostree upgrade commit value"
+UPGRADE_HASH=$(curl "${PROD_REPO_URL}/refs/heads/${OSTREE_REF}")
+
+# Clean compose and blueprints.
+greenprint "🧽 Clean up upgrade blueprint and compose"
+sudo composer-cli compose delete "${COMPOSE_ID}" > /dev/null
+sudo composer-cli blueprints delete upgrade > /dev/null
+
+# Upgrade image/commit.
+greenprint "🗳 Upgrade ostree image/commit"
+sudo ssh "${SSH_OPTIONS[@]}" -i "${SSH_KEY}" admin@${UEFI_GUEST_ADDRESS} 'sudo rpm-ostree upgrade'
+sudo ssh "${SSH_OPTIONS[@]}" -i "${SSH_KEY}" admin@${UEFI_GUEST_ADDRESS} 'nohup sudo systemctl reboot &>/dev/null & exit'
+
+# Sleep 10 seconds here to make sure vm restarted already
+sleep 10
+
+# Check for ssh ready to go.
+greenprint "🛃 Checking for SSH is ready to go"
+# shellcheck disable=SC2034  # Unused variables left for readability
+for LOOP_COUNTER in $(seq 0 30); do
+    RESULTS="$(wait_for_ssh_up $UEFI_GUEST_ADDRESS)"
+    if [[ $RESULTS == 1 ]]; then
+        echo "SSH is ready now! 🥳"
+        break
+    fi
+    sleep 10
+done
+
+# Check ostree upgrade result
+check_result
+
+# Add instance IP address into /etc/ansible/hosts
+sudo tee "${TEMPDIR}"/inventory > /dev/null << EOF
+[ostree_guest]
+${UEFI_GUEST_ADDRESS}
+
+[ostree_guest:vars]
+ansible_python_interpreter=/usr/bin/python3
+ansible_user=admin
+ansible_private_key_file=${SSH_KEY}
+ansible_ssh_common_args="-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null"
+EOF
+
+# Test IoT/Edge OS
+sudo ansible-playbook -v -i "${TEMPDIR}"/inventory -e image_type=rhel-edge -e ostree_commit="${UPGRADE_HASH}" /usr/share/tests/osbuild-composer/ansible/check_ostree_nort.yaml || RESULTS=0
+check_result
+
+# Final success clean up
+clean_up
+
+exit 0
diff --git a/test/cases/ostree-ng.sh b/test/cases/ostree-ng.sh
index 96f6966c3..48da470a0 100755
--- a/test/cases/ostree-ng.sh
+++ b/test/cases/ostree-ng.sh
@@ -500,7 +500,7 @@ EOF
 
 # Test IoT/Edge OS
 greenprint "📼 Run Edge tests on BIOS VM"
-sudo ANSIBLE_STDOUT_CALLBACK=debug ansible-playbook -v -i "${TEMPDIR}"/inventory -e image_type=rhel-edge -e ostree_commit="${INSTALL_HASH}" /usr/share/tests/osbuild-composer/ansible/check_ostree.yaml || RESULTS=0
+sudo ansible-playbook -v -i "${TEMPDIR}"/inventory -e image_type=rhel-edge -e ostree_commit="${INSTALL_HASH}" /usr/share/tests/osbuild-composer/ansible/check_ostree.yaml || RESULTS=0
 check_result
 
 # Clean up BIOS VM
@@ -682,7 +682,7 @@ ansible_ssh_common_args="-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/
 EOF
 
 # Test IoT/Edge OS
-sudo ANSIBLE_STDOUT_CALLBACK=debug ansible-playbook -v -i "${TEMPDIR}"/inventory -e image_type=rhel-edge -e ostree_commit="${UPGRADE_HASH}" /usr/share/tests/osbuild-composer/ansible/check_ostree.yaml || RESULTS=0
+sudo ansible-playbook -v -i "${TEMPDIR}"/inventory -e image_type=rhel-edge -e ostree_commit="${UPGRADE_HASH}" /usr/share/tests/osbuild-composer/ansible/check_ostree.yaml || RESULTS=0
 check_result
 
 # Final success clean up
diff --git a/test/cases/ostree-raw-image.sh b/test/cases/ostree-raw-image.sh
index 5c76dbef3..e5863cdc9 100755
--- a/test/cases/ostree-raw-image.sh
+++ b/test/cases/ostree-raw-image.sh
@@ -63,6 +63,7 @@ OSTREE_REF="rhel/8/${ARCH}/edge"
 OS_VARIANT="rhel8-unknown"
 TEST_UUID=$(uuidgen)
 IMAGE_KEY="edge-${TEST_UUID}"
+BIOS_GUEST_ADDRESS=192.168.100.50
 UEFI_GUEST_ADDRESS=192.168.100.51
 PROD_REPO_URL=http://192.168.100.1/repo
 PROD_REPO=/var/www/html/repo
@@ -367,9 +368,7 @@ ISO_FILENAME="${COMPOSE_ID}-${INSTALLER_FILENAME}"
 
 greenprint "Extracting and converting the raw image to a qcow2 file"
 sudo xz -d "${ISO_FILENAME}"
-sudo qemu-img convert -f raw "${COMPOSE_ID}-image.raw" -O qcow2 "${IMAGE_KEY}-uefi.qcow2"
-sudo mv "${IMAGE_KEY}-uefi.qcow2" /var/lib/libvirt/images/
-LIBVIRT_IMAGE_PATH=/var/lib/libvirt/images/${IMAGE_KEY}-uefi.qcow2
+sudo qemu-img convert -f raw "${COMPOSE_ID}-image.raw" -O qcow2 "${IMAGE_KEY}.qcow2"
 
 # Clean compose and blueprints.
 greenprint "🧹 Clean up installer blueprint and compose"
@@ -378,10 +377,86 @@ sudo composer-cli blueprints delete installer > /dev/null
 
 ##################################################################
 ##
-## Install and test edge vm with edge-raw-image (UEFI)
+## Install and test edge vm with edge-raw-image (BIOS)
 ##
 ##################################################################
+# Prepare qcow2 file for BIOS
+sudo cp "${IMAGE_KEY}.qcow2" /var/lib/libvirt/images/
+LIBVIRT_IMAGE_PATH=/var/lib/libvirt/images/${IMAGE_KEY}.qcow2
+
+# Ensure SELinux is happy with our new images.
+greenprint "👿 Running restorecon on image directory"
+sudo restorecon -Rv /var/lib/libvirt/images/
+
+greenprint "💿 Installing raw image on BIOS VM"
+sudo virt-install  --name="${IMAGE_KEY}-bios"\
+                   --disk path="${LIBVIRT_IMAGE_PATH}",format=qcow2 \
+                   --ram 3072 \
+                   --vcpus 2 \
+                   --network network=integration,mac=34:49:22:B0:83:30 \
+                   --import \
+                   --os-type linux \
+                   --os-variant ${OS_VARIANT} \
+                   --nographics \
+                   --noautoconsole \
+                   --wait=-1 \
+                   --noreboot
 
+# Start VM.
+greenprint "💻 Start BIOS VM"
+sudo virsh start "${IMAGE_KEY}-bios"
+
+# Check for ssh ready to go.
+greenprint "🛃 Checking for SSH is ready to go"
+for LOOP_COUNTER in $(seq 0 30); do
+    RESULTS="$(wait_for_ssh_up $BIOS_GUEST_ADDRESS)"
+    if [[ $RESULTS == 1 ]]; then
+        echo "SSH is ready now! 🥳"
+        break
+    fi
+    sleep 10
+done
+
+# Check image installation result
+check_result
+
+greenprint "🕹 Get ostree install commit value"
+INSTALL_HASH=$(curl "${PROD_REPO_URL}/refs/heads/${OSTREE_REF}")
+
+# Add instance IP address into /etc/ansible/hosts
+sudo tee "${TEMPDIR}"/inventory > /dev/null << EOF
+[ostree_guest]
+${BIOS_GUEST_ADDRESS}
+
+[ostree_guest:vars]
+ansible_python_interpreter=/usr/bin/python3
+ansible_user=admin
+ansible_private_key_file=${SSH_KEY}
+ansible_ssh_common_args="-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null"
+ansible_become=yes 
+ansible_become_method=sudo
+ansible_become_pass=${EDGE_USER_PASSWORD}
+EOF
+
+# Test IoT/Edge OS
+sudo ansible-playbook -v -i "${TEMPDIR}"/inventory -e image_type=redhat -e ostree_commit="${INSTALL_HASH}" /usr/share/tests/osbuild-composer/ansible/check_ostree.yaml || RESULTS=0
+check_result
+
+# Clean up BIOS VM
+greenprint "🧹 Clean up BIOS VM"
+if [[ $(sudo virsh domstate "${IMAGE_KEY}-bios") == "running" ]]; then
+    sudo virsh destroy "${IMAGE_KEY}-bios"
+fi
+sudo virsh undefine "${IMAGE_KEY}-bios"
+sudo rm -fr LIBVIRT_IMAGE_PATH
+
+##################################################################
+##
+## Install and test edge vm with edge-raw-image (UEFI)
+##
+##################################################################
+# Prepare qcow2 file for UEFI
+sudo cp "${IMAGE_KEY}.qcow2" /var/lib/libvirt/images/
 # Ensure SELinux is happy with our new images.
 greenprint "👿 Running restorecon on image directory"
 sudo restorecon -Rv /var/lib/libvirt/images/
@@ -437,7 +512,7 @@ ansible_become_pass=${EDGE_USER_PASSWORD}
 EOF
 
 # Test IoT/Edge OS
-sudo ANSIBLE_STDOUT_CALLBACK=debug ansible-playbook -v -i "${TEMPDIR}"/inventory -e image_type=redhat -e ostree_commit="${INSTALL_HASH}" /usr/share/tests/osbuild-composer/ansible/check_ostree.yaml || RESULTS=0
+sudo ansible-playbook -v -i "${TEMPDIR}"/inventory -e image_type=redhat -e ostree_commit="${INSTALL_HASH}" /usr/share/tests/osbuild-composer/ansible/check_ostree.yaml || RESULTS=0
 check_result
 
 ##################################################################
@@ -573,7 +648,7 @@ ansible_become_pass=${EDGE_USER_PASSWORD}
 EOF
 
 # Test IoT/Edge OS
-sudo ANSIBLE_STDOUT_CALLBACK=debug ansible-playbook -v -i "${TEMPDIR}"/inventory -e image_type=redhat -e ostree_commit="${UPGRADE_HASH}" /usr/share/tests/osbuild-composer/ansible/check_ostree.yaml || RESULTS=0
+sudo ansible-playbook -v -i "${TEMPDIR}"/inventory -e image_type=redhat -e ostree_commit="${UPGRADE_HASH}" /usr/share/tests/osbuild-composer/ansible/check_ostree.yaml || RESULTS=0
 check_result
 
 # Final success clean up
diff --git a/test/cases/ostree-simplified-installer.sh b/test/cases/ostree-simplified-installer.sh
index c1daa58bb..9b42f89ad 100755
--- a/test/cases/ostree-simplified-installer.sh
+++ b/test/cases/ostree-simplified-installer.sh
@@ -13,6 +13,9 @@ function greenprint {
     echo -e "\033[1;32m${1}\033[0m"
 }
 
+# Start firewalld
+sudo systemctl enable --now firewalld
+
 # Start libvirtd and test it.
 greenprint "🚀 Starting libvirt daemon"
 sudo systemctl start libvirtd
@@ -21,7 +24,7 @@ sudo virsh list --all > /dev/null
 # Set a customized dnsmasq configuration for libvirt so we always get the
 # same address on bootup.
 sudo tee /tmp/integration.xml > /dev/null << EOF
-<network>
+<network xmlns:dnsmasq='http://libvirt.org/schemas/network/dnsmasq/1.0'>
   <name>integration</name>
   <uuid>1c8fe98c-b53a-4ca4-bbdb-deb0f26b3579</uuid>
   <forward mode='nat'>
@@ -29,17 +32,23 @@ sudo tee /tmp/integration.xml > /dev/null << EOF
       <port start='1024' end='65535'/>
     </nat>
   </forward>
-  <bridge name='integration' stp='on' delay='0'/>
+  <bridge name='integration' zone='trusted' stp='on' delay='0'/>
   <mac address='52:54:00:36:46:ef'/>
   <ip address='192.168.100.1' netmask='255.255.255.0'>
     <dhcp>
       <range start='192.168.100.2' end='192.168.100.254'/>
-      <host mac='34:49:22:B0:83:30' name='vm-bios' ip='192.168.100.50'/>
+      <host mac='34:49:22:B0:83:30' name='vm-httpboot' ip='192.168.100.50'/>
       <host mac='34:49:22:B0:83:31' name='vm-uefi' ip='192.168.100.51'/>
     </dhcp>
   </ip>
+  <dnsmasq:options>
+    <dnsmasq:option value='dhcp-vendorclass=set:efi-http,HTTPClient:Arch:00016'/>
+    <dnsmasq:option value='dhcp-option-force=tag:efi-http,60,HTTPClient'/>
+    <dnsmasq:option value='dhcp-boot=tag:efi-http,&quot;http://192.168.100.1/httpboot/EFI/BOOT/BOOTX64.EFI&quot;'/>
+  </dnsmasq:options>
 </network>
 EOF
+
 if ! sudo virsh net-info integration > /dev/null 2>&1; then
     sudo virsh net-define /tmp/integration.xml
 fi
@@ -63,6 +72,7 @@ OSTREE_REF="rhel/8/${ARCH}/edge"
 OS_VARIANT="rhel8-unknown"
 TEST_UUID=$(uuidgen)
 IMAGE_KEY="edge-${TEST_UUID}"
+HTTP_GUEST_ADDRESS=192.168.100.50
 UEFI_GUEST_ADDRESS=192.168.100.51
 PROD_REPO_URL=http://192.168.100.1/repo
 PROD_REPO=/var/www/html/repo
@@ -367,7 +377,7 @@ build_image installer "${INSTALLER_TYPE}" "${PROD_REPO_URL}/"
 greenprint "📥 Downloading the installer image"
 sudo composer-cli compose image "${COMPOSE_ID}" > /dev/null
 ISO_FILENAME="${COMPOSE_ID}-${INSTALLER_FILENAME}"
-sudo mv "${ISO_FILENAME}" /var/lib/libvirt/images
+sudo cp "${ISO_FILENAME}" /var/lib/libvirt/images
 
 # Clean compose and blueprints.
 greenprint "🧹 Clean up installer blueprint and compose"
@@ -376,7 +386,97 @@ sudo composer-cli blueprints delete installer > /dev/null
 
 ##################################################################
 ##
-## Install and test edge vm with edge-simplified-installer (UEFI)
+## Install edge vm with edge-simplified-installer (http boot)
+##
+##################################################################
+
+HTTPD_PATH="/var/www/html"
+GRUB_CFG=${HTTPD_PATH}/httpboot/EFI/BOOT/grub.cfg
+
+greenprint "📋 Mount simplified installer iso and copy content to webserver/httpboot"
+sudo mkdir -p ${HTTPD_PATH}/httpboot
+sudo mkdir /mnt/installer
+sudo mount -o loop "${ISO_FILENAME}" /mnt/installer
+sudo cp -R /mnt/installer/* ${HTTPD_PATH}/httpboot/
+sudo chmod -R +r ${HTTPD_PATH}/httpboot/*
+
+greenprint "📋 Update grub.cfg file for http boot"
+sudo sed -i 's/timeout=60/timeout=10/' "${GRUB_CFG}"
+sudo sed -i 's/coreos.inst.install_dev=\/dev\/sda/coreos.inst.install_dev=\/dev\/vda/' "${GRUB_CFG}"
+sudo sed -i 's/linux \/images\/pxeboot\/vmlinuz/linuxefi \/httpboot\/images\/pxeboot\/vmlinuz/' "${GRUB_CFG}"
+sudo sed -i 's/initrd \/images\/pxeboot\/initrd.img/initrdefi \/httpboot\/images\/pxeboot\/initrd.img/' "${GRUB_CFG}"
+sudo sed -i 's/coreos.inst.image_file=\/run\/media\/iso\/disk.img.xz/coreos.inst.image_url=http:\/\/192.168.100.1\/httpboot\/disk.img.xz/' "${GRUB_CFG}"
+
+greenprint "📋 Create libvirt image disk"
+LIBVIRT_IMAGE_PATH=/var/lib/libvirt/images/${IMAGE_KEY}.qcow2
+sudo qemu-img create -f qcow2 "${LIBVIRT_IMAGE_PATH}" 20G
+
+greenprint "📋 Install edge vm via http boot"
+sudo virt-install --name="${IMAGE_KEY}-http"\
+                  --disk path="${LIBVIRT_IMAGE_PATH}",format=qcow2 \
+                  --ram 3072 \
+                  --vcpus 2 \
+                  --network network=integration,mac=34:49:22:B0:83:30 \
+                  --os-type linux \
+                  --os-variant rhel8-unknown \
+                  --pxe \
+                  --boot uefi,loader_ro=yes,loader_type=pflash,nvram_template=/usr/share/edk2/ovmf/OVMF_VARS.fd,loader_secure=no \
+                  --nographics \
+                  --noautoconsole \
+                  --wait=-1 \
+                  --noreboot
+
+# Start VM.
+greenprint "💻 Start HTTP BOOT VM"
+sudo virsh start "${IMAGE_KEY}-http"
+
+# Check for ssh ready to go.
+greenprint "🛃 Checking for SSH is ready to go"
+for LOOP_COUNTER in $(seq 0 30); do
+    RESULTS="$(wait_for_ssh_up $HTTP_GUEST_ADDRESS)"
+    if [[ $RESULTS == 1 ]]; then
+        echo "SSH is ready now! 🥳"
+        break
+    fi
+    sleep 10
+done
+
+# Check image installation result
+check_result
+
+greenprint "🕹 Get ostree install commit value"
+INSTALL_HASH=$(curl "${PROD_REPO_URL}/refs/heads/${OSTREE_REF}")
+
+# Add instance IP address into /etc/ansible/hosts
+sudo tee "${TEMPDIR}"/inventory > /dev/null << EOF
+[ostree_guest]
+${HTTP_GUEST_ADDRESS}
+
+[ostree_guest:vars]
+ansible_python_interpreter=/usr/bin/python3
+ansible_user=admin
+ansible_private_key_file=${SSH_KEY}
+ansible_ssh_common_args="-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null"
+ansible_become=yes 
+ansible_become_method=sudo
+ansible_become_pass=${EDGE_USER_PASSWORD}
+EOF
+
+# Test IoT/Edge OS
+sudo ansible-playbook -v -i "${TEMPDIR}"/inventory -e image_type=redhat -e ostree_commit="${INSTALL_HASH}" /usr/share/tests/osbuild-composer/ansible/check_ostree.yaml || RESULTS=0
+check_result
+
+# Clean up BIOS VM
+greenprint "🧹 Clean up BIOS VM"
+if [[ $(sudo virsh domstate "${IMAGE_KEY}-http") == "running" ]]; then
+    sudo virsh destroy "${IMAGE_KEY}-http"
+fi
+sudo virsh undefine "${IMAGE_KEY}-http" --nvram
+sudo rm -f "$LIBVIRT_IMAGE_PATH"
+
+##################################################################
+##
+## Install edge vm with edge-simplified-installer (UEFI)
 ##
 ##################################################################
 
@@ -386,7 +486,6 @@ sudo restorecon -Rv /var/lib/libvirt/images/
 
 # Create qcow2 file for virt install.
 greenprint "🖥 Create qcow2 file for virt install"
-LIBVIRT_IMAGE_PATH=/var/lib/libvirt/images/${IMAGE_KEY}-uefi.qcow2
 sudo qemu-img create -f qcow2 "${LIBVIRT_IMAGE_PATH}" 20G
 
 greenprint "💿 Install ostree image via installer(ISO) on UEFI VM"
@@ -441,7 +540,7 @@ ansible_become_pass=${EDGE_USER_PASSWORD}
 EOF
 
 # Test IoT/Edge OS
-sudo ANSIBLE_STDOUT_CALLBACK=debug ansible-playbook -v -i "${TEMPDIR}"/inventory -e image_type=redhat -e ostree_commit="${INSTALL_HASH}" /usr/share/tests/osbuild-composer/ansible/check_ostree.yaml || RESULTS=0
+sudo ansible-playbook -v -i "${TEMPDIR}"/inventory -e image_type=redhat -e ostree_commit="${INSTALL_HASH}" /usr/share/tests/osbuild-composer/ansible/check_ostree.yaml || RESULTS=0
 check_result
 
 ##################################################################
@@ -542,8 +641,6 @@ greenprint "🗳 Upgrade ostree image/commit"
 sudo ssh "${SSH_OPTIONS[@]}" -i "${SSH_KEY}" admin@${UEFI_GUEST_ADDRESS} "echo ${EDGE_USER_PASSWORD} |sudo -S rpm-ostree upgrade"
 sudo ssh "${SSH_OPTIONS[@]}" -i "${SSH_KEY}" admin@${UEFI_GUEST_ADDRESS} "echo ${EDGE_USER_PASSWORD} |nohup sudo -S systemctl reboot &>/dev/null & exit"
 
-
-
 # Sleep 10 seconds here to make sure vm restarted already
 sleep 10
 
@@ -578,7 +675,7 @@ ansible_become_pass=${EDGE_USER_PASSWORD}
 EOF
 
 # Test IoT/Edge OS
-sudo ANSIBLE_STDOUT_CALLBACK=debug ansible-playbook -v -i "${TEMPDIR}"/inventory -e image_type=redhat -e ostree_commit="${UPGRADE_HASH}" /usr/share/tests/osbuild-composer/ansible/check_ostree.yaml || RESULTS=0
+sudo ansible-playbook -v -i "${TEMPDIR}"/inventory -e image_type=redhat -e ostree_commit="${UPGRADE_HASH}" /usr/share/tests/osbuild-composer/ansible/check_ostree.yaml || RESULTS=0
 check_result
 
 # Final success clean up
diff --git a/test/cases/ostree.sh b/test/cases/ostree.sh
index e20301993..14527c028 100755
--- a/test/cases/ostree.sh
+++ b/test/cases/ostree.sh
@@ -53,6 +53,15 @@ function greenprint {
     echo -e "\033[1;32m${1}\033[0m"
 }
 
+function get_build_info() {
+    key="$1"
+    fname="$2"
+    if rpm -q --quiet weldr-client; then
+        key=".body${key}"
+    fi
+    jq -r "${key}" "${fname}"
+}
+
 # Start libvirtd and test it.
 greenprint "🚀 Starting libvirt daemon"
 sudo systemctl start libvirtd
@@ -170,13 +179,13 @@ build_image() {
     else
         sudo composer-cli --json compose start "$blueprint_name" $IMAGE_TYPE | tee "$COMPOSE_START"
     fi
-    COMPOSE_ID=$(jq -r '.build_id' "$COMPOSE_START")
+    COMPOSE_ID=$(get_build_info ".build_id" "$COMPOSE_START")
 
     # Wait for the compose to finish.
     greenprint "⏱ Waiting for compose to finish: ${COMPOSE_ID}"
     while true; do
         sudo composer-cli --json compose info "${COMPOSE_ID}" | tee "$COMPOSE_INFO" > /dev/null
-        COMPOSE_STATUS=$(jq -r '.queue_status' "$COMPOSE_INFO")
+        COMPOSE_STATUS=$(get_build_info ".queue_status" "$COMPOSE_INFO")
 
         # Is the compose finished?
         if [[ $COMPOSE_STATUS != RUNNING ]] && [[ $COMPOSE_STATUS != WAITING ]]; then
@@ -261,7 +270,7 @@ modules = []
 groups = []
 
 [[packages]]
-name = "python36"
+name = "python3"
 version = "*"
 EOF
 
@@ -426,7 +435,7 @@ modules = []
 groups = []
 
 [[packages]]
-name = "python36"
+name = "python3"
 version = "*"
 
 [[packages]]
diff --git a/test/data/ansible/check_ostree_nort.yaml b/test/data/ansible/check_ostree_nort.yaml
new file mode 100644
index 000000000..cb0803fcb
--- /dev/null
+++ b/test/data/ansible/check_ostree_nort.yaml
@@ -0,0 +1,530 @@
+---
+- hosts: ostree_guest
+  become: no
+  vars:
+    workspace: "{{ lookup('env', 'WORKSPACE') }}"
+    total_counter: "0"
+    failed_counter: "0"
+
+  tasks:
+    # current target host's IP address
+    - debug: var=ansible_all_ipv4_addresses
+
+    # default kernel or rt kernel
+    - name: check installed kernel
+      command: uname -r
+      register: result_kernel
+
+    # first installed or upgraded
+    # first installed has one commit, but upgraded has two
+    - name: determin which stage the checking is running on
+      shell: rpm-ostree status --json | jq '.deployments | length'
+      register: result_stage
+
+    - set_fact:
+        checking_stage: "{{ result_stage.stdout }}"
+
+    # case: check ostree commit correctly updated
+    - name: get deployed ostree commit
+      command: rpm-ostree status --json
+      register: result_commit
+
+    - name: make a json result
+      set_fact:
+        deploy_commit: "{{ result_commit.stdout | from_json | json_query('deployments[0].checksum') }}"
+
+    - name: check commit deployed and built
+      block:
+        - assert:
+            that:
+              - deploy_commit == ostree_commit
+            fail_msg: "deployed ostree commit is not commit built by osbuild-composer"
+            success_msg: "successful building and deployment"
+      always:
+        - set_fact:
+            total_counter: "{{ total_counter | int + 1 }}"
+      rescue:
+        - name: failed count + 1
+          set_fact:
+            failed_counter: "{{ failed_counter | int + 1 }}"
+
+    # case from bug: https://bugzilla.redhat.com/show_bug.cgi?id=1848453
+    - name: check ostree-remount status
+      command: systemctl is-active ostree-remount.service
+      register: result_remount
+
+    - name: ostree-remount should be started
+      block:
+        - assert:
+            that:
+              - result_remount.stdout == "active"
+            fail_msg: "ostree-remount is not started by default"
+            success_msg: "starting ostree-remount successful"
+      always:
+        - set_fact:
+            total_counter: "{{ total_counter | int + 1 }}"
+      rescue:
+        - name: failed count + 1
+          set_fact:
+            failed_counter: "{{ failed_counter | int + 1 }}"
+
+    # bios or uefi
+    - name: bios or uefi
+      stat:
+        path: /sys/firmware/efi
+      register: result_uefi
+
+    - set_fact:
+        device_name: /dev/vda2
+
+    - set_fact:
+        device_name: /dev/vda3
+      when: result_uefi.stat.exists
+
+    # for edge-simplified-installer and edge-raw-image, /sysroot is mounted at /dev/vda4, need to set device_name to /dev/vda4
+    - name: check if it is simplified-installer or raw-image
+      command: df -h
+      register: result_df
+    
+    - set_fact:
+        device_name: /dev/vda4
+      when: "'/dev/vda4' in result_df.stdout"
+
+    # case: check /sysroot moutn point
+    - name: check /sysroot mount point
+      command: findmnt -r -o SOURCE -n /sysroot
+      register: result_sysroot_mount_point
+
+    - name: "/sysroot should be mounted on {{ device_name }}"
+      block:
+        - assert:
+            that:
+              - result_sysroot_mount_point.stdout == "{{ device_name }}"
+            fail_msg: "/var does not mount on {{ device_name }}"
+            success_msg: "/var mounts on {{ device_name }}"
+      always:
+        - set_fact:
+            total_counter: "{{ total_counter | int + 1 }}"
+      rescue:
+        - name: failed count + 1
+          set_fact:
+            failed_counter: "{{ failed_counter | int + 1 }}"
+
+    # case: check /sysroot mount status
+    - name: check /sysroot mount status
+      shell: findmnt -r -o OPTIONS -n /sysroot | awk -F "," '{print $1}'
+      register: result_sysroot_mount_status
+
+    - name: /sysroot should be mount with rw permission
+      block:
+        - assert:
+            that:
+              - result_sysroot_mount_status.stdout == "rw"
+            fail_msg: "/sysroot is not mounted with rw permission"
+            success_msg: "/sysroot is mounted with rw permission"
+      always:
+        - set_fact:
+            total_counter: "{{ total_counter | int + 1 }}"
+      rescue:
+        - name: failed count + 1
+          set_fact:
+            failed_counter: "{{ failed_counter | int + 1 }}"
+
+    # case: check /var mount point
+    - name: check /var mount point
+      command: findmnt -r -o SOURCE -n /var
+      register: result_var_mount_point
+
+    - name: "/var should be mounted on {{ device_name }}[/ostree/deploy/{{ image_type }}/var]"
+      block:
+        - assert:
+            that:
+              - result_var_mount_point.stdout == "{{ device_name }}[/ostree/deploy/{{ image_type }}/var]"
+            fail_msg: "/var does not mount on {{ device_name }}[/ostree/deploy/{{ image_type }}/var]"
+            success_msg: "/var mounts on {{ device_name }}[/ostree/deploy/{{ image_type }}/var]"
+      always:
+        - set_fact:
+            total_counter: "{{ total_counter | int + 1 }}"
+      rescue:
+        - name: failed count + 1
+          set_fact:
+            failed_counter: "{{ failed_counter | int + 1 }}"
+
+    # case: check /var mount status
+    - name: check /var mount status
+      shell: findmnt -r -o OPTIONS -n /var | awk -F "," '{print $1}'
+      register: result_var_mount_status
+
+    - name: /var should be mount with rw permission
+      block:
+        - assert:
+            that:
+              - result_var_mount_status.stdout == "rw"
+            fail_msg: "/var is not mounted with rw permission"
+            success_msg: "/var is mounted with rw permission"
+      always:
+        - set_fact:
+            total_counter: "{{ total_counter | int + 1 }}"
+      rescue:
+        - name: failed count + 1
+          set_fact:
+            failed_counter: "{{ failed_counter | int + 1 }}"
+
+    # case: check /usr mount point
+    - name: check /usr mount point
+      command: findmnt -r -o SOURCE -n /usr
+      register: result_usr_mount_point
+
+    - name: "/usr should be mounted on {{ device_name }}[/ostree/deploy/{{ image_type }}/deploy/{{ deploy_commit }}.0/usr]"
+      block:
+        - assert:
+            that:
+              - result_usr_mount_point.stdout == "{{ device_name }}[/ostree/deploy/{{ image_type }}/deploy/{{ deploy_commit }}.0/usr]"
+            fail_msg: "/usr does not mount on {{ device_name }}[/ostree/deploy/{{ image_type }}/deploy/{{ deploy_commit }}.0/usr]"
+            success_msg: "/usr mounts on {{ device_name }}[/ostree/deploy/{{ image_type }}/deploy/{{ deploy_commit }}.0/usr]"
+      always:
+        - set_fact:
+            total_counter: "{{ total_counter | int + 1 }}"
+      rescue:
+        - name: failed count + 1
+          set_fact:
+            failed_counter: "{{ failed_counter | int + 1 }}"
+
+    # case: check /usr mount status
+    - name: check /usr mount status
+      shell: findmnt -r -o OPTIONS -n /usr | awk -F "," '{print $1}'
+      register: result_usr_mount_status
+
+    - name: /usr should be mount with rw permission
+      block:
+        - assert:
+            that:
+              - result_usr_mount_status.stdout == "ro"
+            fail_msg: "/usr is not mounted with ro permission"
+            success_msg: "/usr is mounted with ro permission"
+      always:
+        - set_fact:
+            total_counter: "{{ total_counter | int + 1 }}"
+      rescue:
+        - name: failed count + 1
+          set_fact:
+            failed_counter: "{{ failed_counter | int + 1 }}"
+
+    - name: get the first 10 chars in commit hash
+      set_fact:
+        commit_log: "{{ deploy_commit[:11] }}"
+
+    # case: check wget installed after upgrade
+    - name: check installed package
+      shell: rpm -qa | sort
+      register: result_packages
+
+    - name: check wget installed
+      block:
+        - assert:
+            that:
+              - "'wget' in result_packages.stdout"
+            fail_msg: "wget not installed, ostree upgrade might be failed"
+            success_msg: "wget installed in ostree upgrade"
+      always:
+        - set_fact:
+            total_counter: "{{ total_counter | int + 1 }}"
+      rescue:
+        - name: failed count + 1
+          set_fact:
+            failed_counter: "{{ failed_counter | int + 1 }}"
+      when: checking_stage == "2"
+
+    - name: save installed package to log file
+      copy:
+        content: "{{ result_packages.stdout }}"
+        dest: "{{ workspace }}/{{ commit_log }}.installed.ostree.log"
+      delegate_to: localhost
+
+    # case: check ostree-remount mount log
+    - name: check ostree-remount mount log
+      command: journalctl -u ostree-remount
+      register: result_remount_jounalctl
+
+    - name: ostree-remount should remount /var and /sysroot
+      block:
+        - assert:
+            that:
+              - "'/sysroot' in result_remount_jounalctl.stdout"
+              - "'/var' in result_remount_jounalctl.stdout"
+            fail_msg: "/sysroot or /var are not remounted by ostree-remount"
+            success_msg: "/sysroot and /var are remount"
+      always:
+        - set_fact:
+            total_counter: "{{ total_counter | int + 1 }}"
+      rescue:
+        - name: failed count + 1
+          set_fact:
+            failed_counter: "{{ failed_counter | int + 1 }}"
+
+    # case: check dmesg error and failed log
+    - name: check dmesg output
+      command: dmesg
+      register: result_dmesg
+
+    - name: save dmesg output to log file
+      copy:
+        content: "{{ result_dmesg.stdout }}"
+        dest: "{{ workspace }}/{{ commit_log }}.dmesg.ostree.log"
+      delegate_to: localhost
+
+    - name: check dmesg error and fail log
+      shell: dmesg --notime | grep -i "error\|fail" || true
+      register: result_dmesg_error
+
+    # case: check running container with podman
+    - name: run ubi8 image
+      command: podman run registry.access.redhat.com/ubi8/ubi-minimal:latest cat /etc/redhat-release
+      register: podman_result
+      become: yes
+      ignore_errors: yes  # due to https://bugzilla.redhat.com/show_bug.cgi?id=1903983
+
+    - name: run container test
+      block:
+        - assert:
+            that:
+              - podman_result is succeeded
+              - "'Red Hat Enterprise Linux release' in podman_result.stdout"
+            fail_msg: "failed run container with podman"
+            success_msg: "running container with podman successed"
+      always:
+        - set_fact:
+            total_counter: "{{ total_counter | int + 1 }}"
+      rescue:
+        - name: failed count + 1
+          set_fact:
+            failed_counter: "{{ failed_counter | int + 1 }}"
+
+    # case: check dnf package and it should not be installed
+    # https://github.com/osbuild/osbuild-composer/blob/master/internal/distro/rhel8/distro.go#L642
+    - name: dnf should not be installed
+      block:
+        - name: dnf should not be installed
+          shell: rpm -qa | grep dnf || echo -n PASS
+          register: result_dnf
+
+        - assert:
+            that:
+              - result_dnf.stdout == "PASS"
+            fail_msg: "dnf is installed"
+            success_msg: "No dnf installed"
+      always:
+        - set_fact:
+            total_counter: "{{ total_counter | int + 1 }}"
+      rescue:
+        - name: failed count + 1
+          set_fact:
+            failed_counter: "{{ failed_counter | int + 1 }}"
+      when: ansible_facts['distribution'] != 'RedHat' and ansible_facts ['distribution_version'] != '8.5'
+
+    # case: check installed greenboot packages
+    # https://github.com/osbuild/osbuild-composer/blob/master/internal/distro/rhel8/distro.go#L634
+    - name: greenboot and it's related packages should be installed
+      block:
+        - name: greenboot and it's related packages should be installed
+          shell: rpm -qa | grep greenboot
+          register: result_greenboot_packages
+
+        - assert:
+            that:
+              - "'greenboot-0' in result_greenboot_packages.stdout"
+              - "'greenboot-grub2' in result_greenboot_packages.stdout"
+              - "'greenboot-rpm-ostree-grub2' in result_greenboot_packages.stdout"
+              - "'greenboot-reboot' in result_greenboot_packages.stdout"
+              - "'greenboot-status' in result_greenboot_packages.stdout"
+            fail_msg: "Some of greenboot and its related packages are not installed"
+            success_msg: "All greenboot and its related packages are installed"
+      always:
+        - set_fact:
+            total_counter: "{{ total_counter | int + 1 }}"
+      rescue:
+        - name: failed count + 1
+          set_fact:
+            failed_counter: "{{ failed_counter | int + 1 }}"
+
+    # case: check greenboot* services
+    - name: a list of greenboot* service should be enabled
+      block:
+        - name: a list of greenboot* service should be enabled
+          command: systemctl is-enabled greenboot-grub2-set-counter greenboot-grub2-set-success greenboot-healthcheck greenboot-rpm-ostree-grub2-check-fallback greenboot-status greenboot-task-runner redboot-auto-reboot redboot-task-runner
+          register: result_greenboot_service
+
+        - assert:
+            that:
+              - result_greenboot_service.stdout == 'enabled\nenabled\nenabled\nenabled\nenabled\nenabled\nenabled\nenabled'
+            fail_msg: "Some of greenboot* services are not enabled"
+            success_msg: "All greenboot* services are enabled"
+      always:
+        - set_fact:
+            total_counter: "{{ total_counter | int + 1 }}"
+      rescue:
+        - name: failed count + 1
+          set_fact:
+            failed_counter: "{{ failed_counter | int + 1 }}"
+
+    # case: check greenboot* services log
+    - name: all greenboot* service should run without error
+      block:
+        - name: all greenboot* service should run without error
+          command: journalctl -b -0 -u boot-complete.target -u greenboot -u greenboot-healthcheck -u greenboot-rpm-ostree-grub2-check-fallback -u greenboot-grub2-set-counter -u greenboot-grub2-set-success -u greenboot-status -u redboot -u redboot-auto-reboot -u redboot.target
+          register: result_greenboot_log
+
+        - assert:
+            that:
+              - "'Script \\'00_required_scripts_start.sh\\' SUCCESS' in result_greenboot_log.stdout"
+              - "'Script \\'00_wanted_scripts_start.sh\\' SUCCESS' in result_greenboot_log.stdout"
+              - "'greenboot Health Checks Runner' in result_greenboot_log.stdout"
+              - "'Reached target Boot Completion Check' in result_greenboot_log.stdout"
+              - "'Mark boot as successful in grubenv' in result_greenboot_log.stdout"
+              - "'Boot Status is GREEN - Health Check SUCCESS' in result_greenboot_log.stdout"
+              - "'greenboot MotD Generator' in result_greenboot_log.stdout"
+            fail_msg: "Some errors happened in service boot"
+            success_msg: "All greenboot services booted success"
+
+      always:
+        - set_fact:
+            total_counter: "{{ total_counter | int + 1 }}"
+      rescue:
+        - name: failed count + 1
+          set_fact:
+            failed_counter: "{{ failed_counter | int + 1 }}"
+
+    # case: check grubenv variables
+    - name: grubenv variables should contain boot_success=1
+      block:
+        - name: grubenv variables should contain boot_success=1
+          command: grub2-editenv list
+          register: result_grubenv
+          become: yes
+
+        - assert:
+            that:
+              - "'boot_success=1' in result_grubenv.stdout"
+            fail_msg: "Not found boot_success=1"
+            success_msg: "Found boot_success=1"
+      always:
+        - set_fact:
+            total_counter: "{{ total_counter | int + 1 }}"
+      rescue:
+        - name: failed count + 1
+          set_fact:
+            failed_counter: "{{ failed_counter | int + 1 }}"
+
+    # case: check rollback function if boot error found
+    - name: install sanely failing health check unit to test red boot status behavior
+      block:
+        - name: install sanely failing health check unit to test red boot status behavior
+          command: rpm-ostree install http://file-server-virt-qe-3rd.apps.ocp4.prod.psi.redhat.com/greenboot-failing-unit-1.0-1.el8.noarch.rpm
+          become: yes
+
+        - name: reboot to deploy new ostree commit
+          reboot:
+          become: yes
+
+        - name: waits until instance is reachable
+          wait_for:
+            host: "{{ ansible_all_ipv4_addresses[0] }}"
+            port: 22
+            search_regex: OpenSSH
+            delay: 10
+          register: result_rollback
+
+        - assert:
+            that:
+              - result_rollback is succeeded
+            fail_msg: "Rollback failed"
+            success_msg: "Rollback success"
+      always:
+        - set_fact:
+            total_counter: "{{ total_counter | int + 1 }}"
+      rescue:
+        - name: failed count + 1
+          set_fact:
+            failed_counter: "{{ failed_counter | int + 1 }}"
+
+    # case: check ostree commit after rollback
+    - name: check ostree commit after rollback
+      block:
+        - name: check ostree commit after rollback
+          command: rpm-ostree status --json
+          register: result_commit
+
+        - name: make a json result
+          set_fact:
+            deploy_commit: "{{ result_commit.stdout | from_json | json_query('deployments[0].checksum') }}"
+
+        - assert:
+            that:
+              - deploy_commit == ostree_commit
+            fail_msg: "Not rollback to last commit"
+            success_msg: "Rollback success"
+      always:
+        - set_fact:
+            total_counter: "{{ total_counter | int + 1 }}"
+      rescue:
+        - name: failed count + 1
+          set_fact:
+            failed_counter: "{{ failed_counter | int + 1 }}"
+      when: result_rollback is succeeded
+
+    # case: check greenboot* services log again
+    - name: fallback log should be found here
+      block:
+        - name: fallback log should be found here
+          command: journalctl -b -0 -u boot-complete.target -u greenboot -u greenboot-healthcheck -u greenboot-rpm-ostree-grub2-check-fallback -u greenboot-grub2-set-counter -u greenboot-grub2-set-success -u greenboot-status -u redboot -u redboot-auto-reboot -u redboot.target
+          register: result_greenboot_log
+
+        - assert:
+            that:
+              - "'FALLBACK BOOT DETECTED! Default rpm-ostree deployment has been rolled back' in result_greenboot_log.stdout"
+              - "'Script \\'00_required_scripts_start.sh\\' SUCCESS' in result_greenboot_log.stdout"
+              - "'Script \\'00_wanted_scripts_start.sh\\' SUCCESS' in result_greenboot_log.stdout"
+              - "'greenboot Health Checks Runner' in result_greenboot_log.stdout"
+              - "'Reached target Boot Completion Check' in result_greenboot_log.stdout"
+              - "'Mark boot as successful in grubenv' in result_greenboot_log.stdout"
+              - "'Boot Status is GREEN - Health Check SUCCESS' in result_greenboot_log.stdout"
+              - "'greenboot MotD Generator' in result_greenboot_log.stdout"
+            fail_msg: "Fallback log not found"
+            success_msg: "Found fallback log"
+
+      always:
+        - set_fact:
+            total_counter: "{{ total_counter | int + 1 }}"
+      rescue:
+        - name: failed count + 1
+          set_fact:
+            failed_counter: "{{ failed_counter | int + 1 }}"
+      when: result_rollback is succeeded
+
+    # case: check grubenv variables again
+    - name: grubenv variables should contain boot_success=1
+      block:
+        - name: grubenv variables should contain boot_success=1
+          command: grub2-editenv list
+          register: result_grubenv
+          become: yes
+
+        - assert:
+            that:
+              - "'boot_success=1' in result_grubenv.stdout"
+            fail_msg: "Not found boot_success=1"
+            success_msg: "Found boot_success=1"
+      always:
+        - set_fact:
+            total_counter: "{{ total_counter | int + 1 }}"
+      rescue:
+        - name: failed count + 1
+          set_fact:
+            failed_counter: "{{ failed_counter | int + 1 }}"
+      when: result_rollback is succeeded
+
+    - assert:
+        that:
+          - failed_counter == "0"
+        fail_msg: "Run {{ total_counter }} tests, but {{ failed_counter }} of them failed"
+        success_msg: "Totally {{ total_counter }} test passed"
diff --git a/test/data/manifests/rhel_90-aarch64-edge_commit-boot.json b/test/data/manifests/rhel_90-aarch64-edge_commit-boot.json
index 4149fd0fe..b932d3ddb 100644
--- a/test/data/manifests/rhel_90-aarch64-edge_commit-boot.json
+++ b/test/data/manifests/rhel_90-aarch64-edge_commit-boot.json
@@ -615,6 +615,7 @@
                   "sha256:48f54283e14169425e68b87180435123af1906bd12c6631895d48106f5e841c9",
                   "sha256:7f3874f19f5af6867d7d9ff0a34442f4d92c153c139a1c0a058c7e3ae4ce1e7a",
                   "sha256:8a46cffbaee57de4881ef8c746195cb4da090ae0544bf90cf346dcfe3f322f4d",
+                  "sha256:d12649d69a0a7088ee0663735ce9aa6f05ae710aefe1391004cb1cb424dbdf40",
                   "sha256:785dba3e8f6c225e5a6eb5ae410c03e19c890573d010a368b754bb83e606ce94",
                   "sha256:2a399fa929245800ed68c8febee80ca2e1c20a08e92f9cd8c73e2cdd3aa04490",
                   "sha256:0f72fb02c99abc767b209829f3ebba2fe62c908a5d58317d3243f17ebd183709",
@@ -781,7 +782,15 @@
               "enabled_services": [
                 "NetworkManager.service",
                 "firewalld.service",
-                "sshd.service"
+                "sshd.service",
+                "greenboot-grub2-set-counter",
+                "greenboot-grub2-set-success",
+                "greenboot-healthcheck",
+                "greenboot-rpm-ostree-grub2-check-fallback",
+                "greenboot-status",
+                "greenboot-task-runner",
+                "redboot-auto-reboot",
+                "redboot-task-runner"
               ]
             }
           },
@@ -1831,6 +1840,9 @@
           "sha256:d0b15c7dbe30b7890b86d77dcde6034409c9604809ff103ab54597f4a09aff28": {
             "url": "https://rpmrepo.osbuild.org/v2/mirror/rhvpn/el9/el9-aarch64-appstream-n9.0-20210827/Packages/libblockdev-fs-2.25-7.el9.aarch64.rpm"
           },
+          "sha256:d12649d69a0a7088ee0663735ce9aa6f05ae710aefe1391004cb1cb424dbdf40": {
+            "url": "https://rpmrepo.osbuild.org/v2/mirror/rhvpn/el9/el9-aarch64-appstream-n9.0-20210827/Packages/nss-altfiles-2.18.1-20.el9.aarch64.rpm"
+          },
           "sha256:d165d14d89664d4e60cadc3625d5a76735a8c47043d9da3e3808ed44a90aeeeb": {
             "url": "https://rpmrepo.osbuild.org/v2/mirror/rhvpn/el9/el9-aarch64-baseos-n9.0-20210827/Packages/python3-libs-3.9.6-6.el9.aarch64.rpm"
           },
@@ -7949,6 +7961,15 @@
         "remote_location": "https://rpmrepo.osbuild.org/v2/mirror/rhvpn/el9/el9-aarch64-appstream-n9.0-20210827/Packages/nss-3.67.0-8.el9.aarch64.rpm",
         "checksum": "sha256:8a46cffbaee57de4881ef8c746195cb4da090ae0544bf90cf346dcfe3f322f4d"
       },
+      {
+        "name": "nss-altfiles",
+        "epoch": 0,
+        "version": "2.18.1",
+        "release": "20.el9",
+        "arch": "aarch64",
+        "remote_location": "https://rpmrepo.osbuild.org/v2/mirror/rhvpn/el9/el9-aarch64-appstream-n9.0-20210827/Packages/nss-altfiles-2.18.1-20.el9.aarch64.rpm",
+        "checksum": "sha256:d12649d69a0a7088ee0663735ce9aa6f05ae710aefe1391004cb1cb424dbdf40"
+      },
       {
         "name": "nss-softokn",
         "epoch": 0,
@@ -8575,6 +8596,7 @@
       "npth-1.6-8.el9.aarch64",
       "nspr-4.31.0-5.el9.aarch64",
       "nss-3.67.0-8.el9.aarch64",
+      "nss-altfiles-2.18.1-20.el9.aarch64",
       "nss-softokn-3.67.0-8.el9.aarch64",
       "nss-softokn-freebl-3.67.0-8.el9.aarch64",
       "nss-sysinit-3.67.0-8.el9.aarch64",
@@ -8715,6 +8737,31 @@
           "actual": "system_u:object_r:mnt_t:s0",
           "expected": "system_u:object_r:default_t:s0",
           "filename": "/proc"
+        },
+        {
+          "actual": "system_u:object_r:unlabeled_t:s0",
+          "expected": "system_u:object_r:container_runtime_exec_t:s0",
+          "filename": "/usr/bin/crun"
+        },
+        {
+          "actual": "system_u:object_r:unlabeled_t:s0",
+          "expected": "system_u:object_r:container_runtime_exec_t:s0",
+          "filename": "/usr/bin/podman"
+        },
+        {
+          "actual": "system_u:object_r:unlabeled_t:s0",
+          "expected": "system_u:object_r:container_runtime_exec_t:s0",
+          "filename": "/usr/bin/runc"
+        },
+        {
+          "actual": "system_u:object_r:unlabeled_t:s0",
+          "expected": "system_u:object_r:usbguard_unit_file_t:s0",
+          "filename": "/usr/lib/systemd/system/usbguard.service"
+        },
+        {
+          "actual": "system_u:object_r:unlabeled_t:s0",
+          "expected": "system_u:object_r:usbguard_exec_t:s0",
+          "filename": "/usr/sbin/usbguard-daemon"
         }
       ],
       "policy": {
@@ -8732,12 +8779,6 @@
       "exit.target",
       "fstrim.timer",
       "fwupd-refresh.timer",
-      "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",
       "halt.target",
       "kexec.target",
       "mdcheck_continue.timer",
@@ -8754,8 +8795,6 @@
       "proc-sys-fs-binfmt_misc.mount",
       "raid-check.timer",
       "rdisc.service",
-      "redboot-auto-reboot.service",
-      "redboot-task-runner.service",
       "remote-cryptsetup.target",
       "remote-veritysetup.target",
       "rpm-ostree-bootstatus.service",
@@ -8791,6 +8830,12 @@
       "dm-event.socket",
       "firewalld.service",
       "getty@.service",
+      "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",
       "import-state.service",
       "loadmodules.service",
       "lvm2-lvmpolld.socket",
@@ -8799,6 +8844,8 @@
       "nis-domainname.service",
       "ostree-remount.service",
       "reboot.target",
+      "redboot-auto-reboot.service",
+      "redboot-task-runner.service",
       "remote-fs.target",
       "runlevel6.target",
       "selinux-autorelabel-mark.service",
diff --git a/test/data/manifests/rhel_90-aarch64-edge_container-boot.json b/test/data/manifests/rhel_90-aarch64-edge_container-boot.json
index 190608e13..5771f1111 100644
--- a/test/data/manifests/rhel_90-aarch64-edge_container-boot.json
+++ b/test/data/manifests/rhel_90-aarch64-edge_container-boot.json
@@ -615,6 +615,7 @@
                   "sha256:48f54283e14169425e68b87180435123af1906bd12c6631895d48106f5e841c9",
                   "sha256:7f3874f19f5af6867d7d9ff0a34442f4d92c153c139a1c0a058c7e3ae4ce1e7a",
                   "sha256:8a46cffbaee57de4881ef8c746195cb4da090ae0544bf90cf346dcfe3f322f4d",
+                  "sha256:d12649d69a0a7088ee0663735ce9aa6f05ae710aefe1391004cb1cb424dbdf40",
                   "sha256:785dba3e8f6c225e5a6eb5ae410c03e19c890573d010a368b754bb83e606ce94",
                   "sha256:2a399fa929245800ed68c8febee80ca2e1c20a08e92f9cd8c73e2cdd3aa04490",
                   "sha256:0f72fb02c99abc767b209829f3ebba2fe62c908a5d58317d3243f17ebd183709",
@@ -781,7 +782,15 @@
               "enabled_services": [
                 "NetworkManager.service",
                 "firewalld.service",
-                "sshd.service"
+                "sshd.service",
+                "greenboot-grub2-set-counter",
+                "greenboot-grub2-set-success",
+                "greenboot-healthcheck",
+                "greenboot-rpm-ostree-grub2-check-fallback",
+                "greenboot-status",
+                "greenboot-task-runner",
+                "redboot-auto-reboot",
+                "redboot-task-runner"
               ]
             }
           },
@@ -2019,6 +2028,9 @@
           "sha256:d0b15c7dbe30b7890b86d77dcde6034409c9604809ff103ab54597f4a09aff28": {
             "url": "https://rpmrepo.osbuild.org/v2/mirror/rhvpn/el9/el9-aarch64-appstream-n9.0-20210827/Packages/libblockdev-fs-2.25-7.el9.aarch64.rpm"
           },
+          "sha256:d12649d69a0a7088ee0663735ce9aa6f05ae710aefe1391004cb1cb424dbdf40": {
+            "url": "https://rpmrepo.osbuild.org/v2/mirror/rhvpn/el9/el9-aarch64-appstream-n9.0-20210827/Packages/nss-altfiles-2.18.1-20.el9.aarch64.rpm"
+          },
           "sha256:d165d14d89664d4e60cadc3625d5a76735a8c47043d9da3e3808ed44a90aeeeb": {
             "url": "https://rpmrepo.osbuild.org/v2/mirror/rhvpn/el9/el9-aarch64-baseos-n9.0-20210827/Packages/python3-libs-3.9.6-6.el9.aarch64.rpm"
           },
@@ -9027,6 +9039,15 @@
         "remote_location": "https://rpmrepo.osbuild.org/v2/mirror/rhvpn/el9/el9-aarch64-appstream-n9.0-20210827/Packages/nss-3.67.0-8.el9.aarch64.rpm",
         "checksum": "sha256:8a46cffbaee57de4881ef8c746195cb4da090ae0544bf90cf346dcfe3f322f4d"
       },
+      {
+        "name": "nss-altfiles",
+        "epoch": 0,
+        "version": "2.18.1",
+        "release": "20.el9",
+        "arch": "aarch64",
+        "remote_location": "https://rpmrepo.osbuild.org/v2/mirror/rhvpn/el9/el9-aarch64-appstream-n9.0-20210827/Packages/nss-altfiles-2.18.1-20.el9.aarch64.rpm",
+        "checksum": "sha256:d12649d69a0a7088ee0663735ce9aa6f05ae710aefe1391004cb1cb424dbdf40"
+      },
       {
         "name": "nss-softokn",
         "epoch": 0,
diff --git a/test/data/manifests/rhel_90-x86_64-edge_commit-boot.json b/test/data/manifests/rhel_90-x86_64-edge_commit-boot.json
index 34b7b7cae..b028104b0 100644
--- a/test/data/manifests/rhel_90-x86_64-edge_commit-boot.json
+++ b/test/data/manifests/rhel_90-x86_64-edge_commit-boot.json
@@ -650,6 +650,7 @@
                   "sha256:731b91b14eb7bc79961d02940db4fe2f8644c6c5d5005bd3c62cc3830443b692",
                   "sha256:22bee502caf00522d7e3733699502e9d109d1a884c3006ee212e900101b07231",
                   "sha256:ad91a2693eae9b8159810a59526a22e0f9518d79d4845f81531331dd6cbac36d",
+                  "sha256:0178538e8a7935d1418e78f74c58880239ad3e8eab94638af562a128ad133e20",
                   "sha256:f31d17d77b9b35e6907b1803e47cede1d3d552d5cb45d46d940d4bd57d28dac5",
                   "sha256:925973b321b7f87ddba9ca957f75ba6585d95a1b2604fe880a05ef1d3621c50a",
                   "sha256:6e5a2b51da0bfecbbc0f11fc023eb17f4fcaf70f23ada1294ba4be8b33bda125",
@@ -816,7 +817,15 @@
               "enabled_services": [
                 "NetworkManager.service",
                 "firewalld.service",
-                "sshd.service"
+                "sshd.service",
+                "greenboot-grub2-set-counter",
+                "greenboot-grub2-set-success",
+                "greenboot-healthcheck",
+                "greenboot-rpm-ostree-grub2-check-fallback",
+                "greenboot-status",
+                "greenboot-task-runner",
+                "redboot-auto-reboot",
+                "redboot-task-runner"
               ]
             }
           },
@@ -915,6 +924,9 @@
           "sha256:01619e0b96181bff3b990016a5857b9d8859b7a4887d8c120b6f60c688bac526": {
             "url": "https://rpmrepo.osbuild.org/v2/mirror/rhvpn/el9/el9-x86_64-baseos-n9.0-20210827/Packages/npth-1.6-8.el9.x86_64.rpm"
           },
+          "sha256:0178538e8a7935d1418e78f74c58880239ad3e8eab94638af562a128ad133e20": {
+            "url": "https://rpmrepo.osbuild.org/v2/mirror/rhvpn/el9/el9-x86_64-appstream-n9.0-20210827/Packages/nss-altfiles-2.18.1-20.el9.x86_64.rpm"
+          },
           "sha256:02c6622480af52421fc2e54be42b8dd1ce6502e237c9a4e8231ae587b49767e3": {
             "url": "https://rpmrepo.osbuild.org/v2/mirror/rhvpn/el9/el9-x86_64-baseos-n9.0-20210827/Packages/zlib-1.2.11-31.el9.x86_64.rpm"
           },
@@ -8299,6 +8311,15 @@
         "remote_location": "https://rpmrepo.osbuild.org/v2/mirror/rhvpn/el9/el9-x86_64-appstream-n9.0-20210827/Packages/nss-3.67.0-8.el9.x86_64.rpm",
         "checksum": "sha256:ad91a2693eae9b8159810a59526a22e0f9518d79d4845f81531331dd6cbac36d"
       },
+      {
+        "name": "nss-altfiles",
+        "epoch": 0,
+        "version": "2.18.1",
+        "release": "20.el9",
+        "arch": "x86_64",
+        "remote_location": "https://rpmrepo.osbuild.org/v2/mirror/rhvpn/el9/el9-x86_64-appstream-n9.0-20210827/Packages/nss-altfiles-2.18.1-20.el9.x86_64.rpm",
+        "checksum": "sha256:0178538e8a7935d1418e78f74c58880239ad3e8eab94638af562a128ad133e20"
+      },
       {
         "name": "nss-softokn",
         "epoch": 0,
@@ -8931,6 +8952,7 @@
       "npth-1.6-8.el9.x86_64",
       "nspr-4.31.0-5.el9.x86_64",
       "nss-3.67.0-8.el9.x86_64",
+      "nss-altfiles-2.18.1-20.el9.x86_64",
       "nss-softokn-3.67.0-8.el9.x86_64",
       "nss-softokn-freebl-3.67.0-8.el9.x86_64",
       "nss-sysinit-3.67.0-8.el9.x86_64",
@@ -9071,6 +9093,16 @@
           "actual": "system_u:object_r:mnt_t:s0",
           "expected": "system_u:object_r:default_t:s0",
           "filename": "/proc"
+        },
+        {
+          "actual": "system_u:object_r:unlabeled_t:s0",
+          "expected": "system_u:object_r:usbguard_unit_file_t:s0",
+          "filename": "/usr/lib/systemd/system/usbguard.service"
+        },
+        {
+          "actual": "system_u:object_r:unlabeled_t:s0",
+          "expected": "system_u:object_r:usbguard_exec_t:s0",
+          "filename": "/usr/sbin/usbguard-daemon"
         }
       ],
       "policy": {
@@ -9088,12 +9120,6 @@
       "exit.target",
       "fstrim.timer",
       "fwupd-refresh.timer",
-      "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",
       "halt.target",
       "kexec.target",
       "mdcheck_continue.timer",
@@ -9110,8 +9136,6 @@
       "proc-sys-fs-binfmt_misc.mount",
       "raid-check.timer",
       "rdisc.service",
-      "redboot-auto-reboot.service",
-      "redboot-task-runner.service",
       "remote-cryptsetup.target",
       "remote-veritysetup.target",
       "rpm-ostree-bootstatus.service",
@@ -9147,6 +9171,12 @@
       "dm-event.socket",
       "firewalld.service",
       "getty@.service",
+      "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",
       "import-state.service",
       "loadmodules.service",
       "lvm2-lvmpolld.socket",
@@ -9156,6 +9186,8 @@
       "nis-domainname.service",
       "ostree-remount.service",
       "reboot.target",
+      "redboot-auto-reboot.service",
+      "redboot-task-runner.service",
       "remote-fs.target",
       "runlevel6.target",
       "selinux-autorelabel-mark.service",
diff --git a/test/data/manifests/rhel_90-x86_64-edge_commit_rt-boot.json b/test/data/manifests/rhel_90-x86_64-edge_commit_rt-boot.json
index c5e75e3fd..9a1becf58 100644
--- a/test/data/manifests/rhel_90-x86_64-edge_commit_rt-boot.json
+++ b/test/data/manifests/rhel_90-x86_64-edge_commit_rt-boot.json
@@ -29,6 +29,9 @@
       }
     }
   },
+  "supported_arches": [
+    "x86_64"
+  ],
   "manifest": {
     "version": "2",
     "pipelines": [
@@ -703,6 +706,7 @@
                   "sha256:731b91b14eb7bc79961d02940db4fe2f8644c6c5d5005bd3c62cc3830443b692",
                   "sha256:22bee502caf00522d7e3733699502e9d109d1a884c3006ee212e900101b07231",
                   "sha256:ad91a2693eae9b8159810a59526a22e0f9518d79d4845f81531331dd6cbac36d",
+                  "sha256:0178538e8a7935d1418e78f74c58880239ad3e8eab94638af562a128ad133e20",
                   "sha256:f31d17d77b9b35e6907b1803e47cede1d3d552d5cb45d46d940d4bd57d28dac5",
                   "sha256:925973b321b7f87ddba9ca957f75ba6585d95a1b2604fe880a05ef1d3621c50a",
                   "sha256:6e5a2b51da0bfecbbc0f11fc023eb17f4fcaf70f23ada1294ba4be8b33bda125",
@@ -1021,7 +1025,15 @@
               "enabled_services": [
                 "NetworkManager.service",
                 "firewalld.service",
-                "sshd.service"
+                "sshd.service",
+                "greenboot-grub2-set-counter",
+                "greenboot-grub2-set-success",
+                "greenboot-healthcheck",
+                "greenboot-rpm-ostree-grub2-check-fallback",
+                "greenboot-status",
+                "greenboot-task-runner",
+                "redboot-auto-reboot",
+                "redboot-task-runner"
               ]
             }
           },
@@ -1120,6 +1132,9 @@
           "sha256:01619e0b96181bff3b990016a5857b9d8859b7a4887d8c120b6f60c688bac526": {
             "url": "https://rpmrepo.osbuild.org/v2/mirror/rhvpn/el9/el9-x86_64-baseos-n9.0-20210827/Packages/npth-1.6-8.el9.x86_64.rpm"
           },
+          "sha256:0178538e8a7935d1418e78f74c58880239ad3e8eab94638af562a128ad133e20": {
+            "url": "https://rpmrepo.osbuild.org/v2/mirror/rhvpn/el9/el9-x86_64-appstream-n9.0-20210827/Packages/nss-altfiles-2.18.1-20.el9.x86_64.rpm"
+          },
           "sha256:02c6622480af52421fc2e54be42b8dd1ce6502e237c9a4e8231ae587b49767e3": {
             "url": "https://rpmrepo.osbuild.org/v2/mirror/rhvpn/el9/el9-x86_64-baseos-n9.0-20210827/Packages/zlib-1.2.11-31.el9.x86_64.rpm"
           },
@@ -10304,6 +10319,15 @@
         "remote_location": "https://rpmrepo.osbuild.org/v2/mirror/rhvpn/el9/el9-x86_64-appstream-n9.0-20210827/Packages/nss-3.67.0-8.el9.x86_64.rpm",
         "checksum": "sha256:ad91a2693eae9b8159810a59526a22e0f9518d79d4845f81531331dd6cbac36d"
       },
+      {
+        "name": "nss-altfiles",
+        "epoch": 0,
+        "version": "2.18.1",
+        "release": "20.el9",
+        "arch": "x86_64",
+        "remote_location": "https://rpmrepo.osbuild.org/v2/mirror/rhvpn/el9/el9-x86_64-appstream-n9.0-20210827/Packages/nss-altfiles-2.18.1-20.el9.x86_64.rpm",
+        "checksum": "sha256:0178538e8a7935d1418e78f74c58880239ad3e8eab94638af562a128ad133e20"
+      },
       {
         "name": "nss-softokn",
         "epoch": 0,
@@ -11068,6 +11092,7 @@
       "npth-1.6-8.el9.x86_64",
       "nspr-4.31.0-5.el9.x86_64",
       "nss-3.67.0-8.el9.x86_64",
+      "nss-altfiles-2.18.1-20.el9.x86_64",
       "nss-softokn-3.67.0-8.el9.x86_64",
       "nss-softokn-freebl-3.67.0-8.el9.x86_64",
       "nss-sysinit-3.67.0-8.el9.x86_64",
@@ -11305,6 +11330,16 @@
           "actual": "system_u:object_r:mnt_t:s0",
           "expected": "system_u:object_r:default_t:s0",
           "filename": "/proc"
+        },
+        {
+          "actual": "system_u:object_r:unlabeled_t:s0",
+          "expected": "system_u:object_r:usbguard_unit_file_t:s0",
+          "filename": "/usr/lib/systemd/system/usbguard.service"
+        },
+        {
+          "actual": "system_u:object_r:unlabeled_t:s0",
+          "expected": "system_u:object_r:usbguard_exec_t:s0",
+          "filename": "/usr/sbin/usbguard-daemon"
         }
       ],
       "policy": {
@@ -11323,12 +11358,6 @@
       "exit.target",
       "fstrim.timer",
       "fwupd-refresh.timer",
-      "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",
       "halt.target",
       "kexec.target",
       "kvm_stat.service",
@@ -11348,8 +11377,6 @@
       "rdisc.service",
       "realtime-entsk.service",
       "realtime-setup.service",
-      "redboot-auto-reboot.service",
-      "redboot-task-runner.service",
       "remote-cryptsetup.target",
       "remote-veritysetup.target",
       "rhsm-facts.service",
@@ -11388,6 +11415,12 @@
       "dnf-makecache.timer",
       "firewalld.service",
       "getty@.service",
+      "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",
       "import-state.service",
       "kdump.service",
       "loadmodules.service",
@@ -11398,6 +11431,8 @@
       "nis-domainname.service",
       "ostree-remount.service",
       "reboot.target",
+      "redboot-auto-reboot.service",
+      "redboot-task-runner.service",
       "remote-fs.target",
       "rhsmcertd.service",
       "runlevel6.target",
diff --git a/test/data/manifests/rhel_90-x86_64-edge_container-boot.json b/test/data/manifests/rhel_90-x86_64-edge_container-boot.json
index 56e4e2018..42b433657 100644
--- a/test/data/manifests/rhel_90-x86_64-edge_container-boot.json
+++ b/test/data/manifests/rhel_90-x86_64-edge_container-boot.json
@@ -650,6 +650,7 @@
                   "sha256:731b91b14eb7bc79961d02940db4fe2f8644c6c5d5005bd3c62cc3830443b692",
                   "sha256:22bee502caf00522d7e3733699502e9d109d1a884c3006ee212e900101b07231",
                   "sha256:ad91a2693eae9b8159810a59526a22e0f9518d79d4845f81531331dd6cbac36d",
+                  "sha256:0178538e8a7935d1418e78f74c58880239ad3e8eab94638af562a128ad133e20",
                   "sha256:f31d17d77b9b35e6907b1803e47cede1d3d552d5cb45d46d940d4bd57d28dac5",
                   "sha256:925973b321b7f87ddba9ca957f75ba6585d95a1b2604fe880a05ef1d3621c50a",
                   "sha256:6e5a2b51da0bfecbbc0f11fc023eb17f4fcaf70f23ada1294ba4be8b33bda125",
@@ -816,7 +817,15 @@
               "enabled_services": [
                 "NetworkManager.service",
                 "firewalld.service",
-                "sshd.service"
+                "sshd.service",
+                "greenboot-grub2-set-counter",
+                "greenboot-grub2-set-success",
+                "greenboot-healthcheck",
+                "greenboot-rpm-ostree-grub2-check-fallback",
+                "greenboot-status",
+                "greenboot-task-runner",
+                "redboot-auto-reboot",
+                "redboot-task-runner"
               ]
             }
           },
@@ -1077,6 +1086,9 @@
           "sha256:01619e0b96181bff3b990016a5857b9d8859b7a4887d8c120b6f60c688bac526": {
             "url": "https://rpmrepo.osbuild.org/v2/mirror/rhvpn/el9/el9-x86_64-baseos-n9.0-20210827/Packages/npth-1.6-8.el9.x86_64.rpm"
           },
+          "sha256:0178538e8a7935d1418e78f74c58880239ad3e8eab94638af562a128ad133e20": {
+            "url": "https://rpmrepo.osbuild.org/v2/mirror/rhvpn/el9/el9-x86_64-appstream-n9.0-20210827/Packages/nss-altfiles-2.18.1-20.el9.x86_64.rpm"
+          },
           "sha256:02c6622480af52421fc2e54be42b8dd1ce6502e237c9a4e8231ae587b49767e3": {
             "url": "https://rpmrepo.osbuild.org/v2/mirror/rhvpn/el9/el9-x86_64-baseos-n9.0-20210827/Packages/zlib-1.2.11-31.el9.x86_64.rpm"
           },
@@ -9378,6 +9390,15 @@
         "remote_location": "https://rpmrepo.osbuild.org/v2/mirror/rhvpn/el9/el9-x86_64-appstream-n9.0-20210827/Packages/nss-3.67.0-8.el9.x86_64.rpm",
         "checksum": "sha256:ad91a2693eae9b8159810a59526a22e0f9518d79d4845f81531331dd6cbac36d"
       },
+      {
+        "name": "nss-altfiles",
+        "epoch": 0,
+        "version": "2.18.1",
+        "release": "20.el9",
+        "arch": "x86_64",
+        "remote_location": "https://rpmrepo.osbuild.org/v2/mirror/rhvpn/el9/el9-x86_64-appstream-n9.0-20210827/Packages/nss-altfiles-2.18.1-20.el9.x86_64.rpm",
+        "checksum": "sha256:0178538e8a7935d1418e78f74c58880239ad3e8eab94638af562a128ad133e20"
+      },
       {
         "name": "nss-softokn",
         "epoch": 0,
@@ -9649,6 +9670,5 @@
         "checksum": "sha256:b6b91777247881481f67ca222ca83e18c5649194e00f40fca8a6297d191bb261"
       }
     ]
-  },
-  "image-info": {}
+  }
 }