diff --git a/.github/actions/test/integration/build/action.yml b/.github/actions/test/integration/build/action.yml
index adcf018c..447de18c 100644
--- a/.github/actions/test/integration/build/action.yml
+++ b/.github/actions/test/integration/build/action.yml
@@ -11,7 +11,7 @@ runs:
- name: Set ENV
shell: bash
env:
- REPO: ghcr.io/gardenlinux/gardenlinux-ccloud
+ REPO: ghcr.io/gardenlinux/gardenlinux-sci
TAG: ${{ inputs.image_tag }}
ESP_SIZE: 2 # GiB
DISK_SIZE: 8 # GiB
@@ -99,12 +99,21 @@ runs:
chmod 600 /opt/ssh_host_ed25519_key
SSH_KEY=$(cat /opt/ssh_host_ed25519_key.pub)
echo "SSH_KEY=$SSH_KEY" >> $GITHUB_ENV
- sed -i "s|SSH_KEY_GOES_HERE|$SSH_KEY|g" ./.github/actions/test/integration/build/dev-user-butane.yaml
+ cp ./.github/actions/test/integration/build/dev-user-butane.yaml ./.github/actions/test/integration/build/dev-user-butane-hv1.yaml
+ yq '.storage.files += load("./.github/actions/test/integration/build/root-hints.yaml")' ./.github/actions/test/integration/build/dev-user-butane.yaml > ./.github/actions/test/integration/build/dev-user-butane-hv2.yaml
+
+ sed -i "s|SSH_KEY_GOES_HERE|$SSH_KEY|g" ./.github/actions/test/integration/build/dev-user-butane-hv1.yaml
+ sed -i "s|SSH_KEY_GOES_HERE|$SSH_KEY|g" ./.github/actions/test/integration/build/dev-user-butane-hv2.yaml
+
PASSWORD=$(openssl passwd "password")
echo "PASSWORD=$PASSWORD" >> $GITHUB_ENV
- sed -i "s|PASSWORD_GOES_HERE|$PASSWORD|g" ./.github/actions/test/integration/build/dev-user-butane.yaml
- sed -i "s|TAG_GOES_HERE|${{ inputs.image_tag }}|g" ./.github/actions/test/integration/build/dev-user-butane.yaml
- butane --pretty --strict ./.github/actions/test/integration/build/dev-user-butane.yaml > "/opt/${TAG}.ign"
+ sed -i "s|PASSWORD_GOES_HERE|$PASSWORD|g" ./.github/actions/test/integration/build/dev-user-butane-hv1.yaml
+ sed -i "s|PASSWORD_GOES_HERE|$PASSWORD|g" ./.github/actions/test/integration/build/dev-user-butane-hv2.yaml
+ sed -i "s|TAG_GOES_HERE|${{ inputs.image_tag }}|g" ./.github/actions/test/integration/build/dev-user-butane-hv1.yaml
+ sed -i "s|TAG_GOES_HERE|${{ inputs.image_tag }}|g" ./.github/actions/test/integration/build/dev-user-butane-hv2.yaml
+
+ butane --pretty --strict ./.github/actions/test/integration/build/dev-user-butane-hv1.yaml > "/opt/${TAG}-hv1.ign"
+ butane --pretty --strict ./.github/actions/test/integration/build/dev-user-butane-hv2.yaml > "/opt/${TAG}-hv2.ign"
- name: Download ubuntu cloud image
shell: bash
@@ -126,7 +135,7 @@ runs:
# - name: Upload artifacts
# uses: actions/upload-artifact@v4
# with:
- # name: gardenlinux-ccloud-${{ inputs.image_tag }}
+ # name: gardenlinux-sci-${{ inputs.image_tag }}
# path: /opt/${{ inputs.image_tag }}.*
# retention-days: 1
# overwrite: true
diff --git a/.github/actions/test/integration/build/dev-user-butane.yaml b/.github/actions/test/integration/build/dev-user-butane.yaml
index b8486454..ac08d4a1 100644
--- a/.github/actions/test/integration/build/dev-user-butane.yaml
+++ b/.github/actions/test/integration/build/dev-user-butane.yaml
@@ -1,5 +1,5 @@
variant: fcos
-version: 1.3.0
+version: 1.7.0
passwd:
users:
- name: root
@@ -37,12 +37,6 @@ storage:
# custom
192.168.122.2 hv1
192.168.122.3 hv2
- - path: /opt/persist/root-hints.yaml
- mode: 0644
- contents:
- inline: |
- hints:
- - size: lt 500G
# turn off hugepages, not required for this test
# also SIGNIFICANTLY reduces test runtime
- path: /opt/persist/hugepages.env
@@ -55,7 +49,7 @@ storage:
contents:
inline: |
# pull the image from GHCR instead of keppel
- OCI_REPO=ghcr.io/gardenlinux/gardenlinux-ccloud
+ OCI_REPO=ghcr.io/gardenlinux/gardenlinux-sci
# point to a custom tag to download for the persist step
OCI_TAG=TAG_GOES_HERE
# Enable unlimited core dumps for all systemd services
@@ -85,3 +79,10 @@ storage:
kernel.core_pattern=|/usr/lib/systemd/systemd-coredump %P %u %g %s %t %c %h
kernel.core_pipe_limit=16
fs.suid_dumpable=2
+# Disable libvirt sockets not required for CI tests
+systemd:
+ units:
+ - name: libvirtd-tls.socket
+ mask: true
+ - name: libvirtd-tcp.socket
+ mask: true
diff --git a/.github/actions/test/integration/build/root-hints.yaml b/.github/actions/test/integration/build/root-hints.yaml
new file mode 100644
index 00000000..59159664
--- /dev/null
+++ b/.github/actions/test/integration/build/root-hints.yaml
@@ -0,0 +1,6 @@
+- path: /opt/persist/root-hints.yaml
+ mode: 0644
+ contents:
+ inline: |
+ hints:
+ - size: lt 500G
diff --git a/.github/actions/test/integration/dependencies/action.yml b/.github/actions/test/integration/dependencies/action.yml
index e1923df9..65fb700c 100644
--- a/.github/actions/test/integration/dependencies/action.yml
+++ b/.github/actions/test/integration/dependencies/action.yml
@@ -34,7 +34,7 @@ runs:
- name: butane
shell: bash
run: |
- BUTANE_VERSION="0.24.0"
+ BUTANE_VERSION="0.27.0"
curl -LO "https://github.com/coreos/butane/releases/download/v${BUTANE_VERSION}/butane-x86_64-unknown-linux-gnu"
chmod +x "butane-x86_64-unknown-linux-gnu"
sudo mv "butane-x86_64-unknown-linux-gnu" /usr/local/bin/butane
diff --git a/.github/actions/test/integration/setup/action.yml b/.github/actions/test/integration/setup/action.yml
index 915b282b..1b8b1bea 100644
--- a/.github/actions/test/integration/setup/action.yml
+++ b/.github/actions/test/integration/setup/action.yml
@@ -15,7 +15,8 @@ runs:
- name: Copy ignition file
shell: bash
run: |
- sudo cp "/opt/${TAG}.ign" /var/lib/libvirt/images/hv.ign
+ sudo cp "/opt/${TAG}-hv1.ign" /var/lib/libvirt/images/HV1.ign
+ sudo cp "/opt/${TAG}-hv2.ign" /var/lib/libvirt/images/HV2.ign
- name: Create HyperVisor 1
shell: bash
diff --git a/.github/actions/test/integration/setup/hv.xml b/.github/actions/test/integration/setup/hv.xml
index 90ab559f..c8f6f0d8 100644
--- a/.github/actions/test/integration/setup/hv.xml
+++ b/.github/actions/test/integration/setup/hv.xml
@@ -15,7 +15,7 @@
-
+
@@ -32,6 +32,6 @@
-
+
diff --git a/.github/actions/test/integration/test/qemu/vm.xml b/.github/actions/test/integration/test/qemu/vm.xml
index 3626dc12..1fe453b8 100644
--- a/.github/actions/test/integration/test/qemu/vm.xml
+++ b/.github/actions/test/integration/test/qemu/vm.xml
@@ -15,12 +15,12 @@
-
+
-
+
-
+
diff --git a/.github/scripts/compute-image-tag.sh b/.github/scripts/compute-image-tag.sh
new file mode 100755
index 00000000..d0c9c389
--- /dev/null
+++ b/.github/scripts/compute-image-tag.sh
@@ -0,0 +1,45 @@
+#!/bin/bash
+# Computes the OCI image tag for Garden Linux ccloud images
+#
+# This script centralizes the image tag format computation to ensure consistency
+# across all workflows (nightly, dev, upload_oci).
+#
+# Usage:
+# ./compute-image-tag.sh [flavor]
+#
+# Arguments:
+# version - The version for the tag (e.g., "1877.10.1", "pr-123")
+# flavor - The image flavor (e.g., "metal-sci-usi-amd64"). Defaults to "metal-sci-usi-amd64".
+#
+# Environment:
+# GITHUB_SHA - Git commit SHA (required, set automatically by GitHub Actions)
+#
+# Output:
+# Prints the computed image tag to stdout
+#
+# Tag format:
+# {version}-{flavor}-{dashed_version}-{commit_sha_short}
+#
+# Examples:
+# ./compute-image-tag.sh "1877.10.1"
+# # Output: 1877.10.1-metal-sci-usi-amd64-1877-10-1-abcd1234
+#
+# ./compute-image-tag.sh "pr-123" "metal-capi-amd64"
+# # Output: pr-123-metal-capi-amd64-pr-123-abcd1234
+
+set -euo pipefail
+
+VERSION="${1:?Error: VERSION argument required}"
+FLAVOR="${2:-metal-sci-usi-amd64}"
+
+if [ -z "${GITHUB_SHA:-}" ]; then
+ echo "Error: GITHUB_SHA environment variable is required" >&2
+ exit 1
+fi
+
+COMMIT_SHA="${GITHUB_SHA::8}"
+DASHED_VERSION="${VERSION//./-}"
+
+IMAGE_TAG="${VERSION}-${FLAVOR}-${DASHED_VERSION}-${COMMIT_SHA}"
+
+echo "$IMAGE_TAG"
diff --git a/.github/workflows/dev.yml b/.github/workflows/dev.yml
index 6dc97a4b..9fff5f5b 100644
--- a/.github/workflows/dev.yml
+++ b/.github/workflows/dev.yml
@@ -3,6 +3,7 @@ on:
push:
branches:
- main
+ - rel-1877-dev
paths-ignore:
- "**/README.md"
- "docs/**"
@@ -11,6 +12,13 @@ on:
paths-ignore:
- "**/README.md"
- "docs/**"
+
+# Cancel any in-progress PR workflow runs when PR is closed
+# Used to ensure cleanup runs after any PR build are uploaded (or aborts before the upload)
+concurrency:
+ group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
+ cancel-in-progress: ${{ github.event.action == 'closed' }}
+
jobs:
set_version:
if: ${{ github.event_name != 'pull_request' || github.event.action != 'closed' }}
@@ -19,30 +27,25 @@ jobs:
VERSION: ${{ steps.version.outputs.VERSION }}
steps:
- name: Checkout repository
- uses: actions/checkout@v4
+ uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
with:
submodules: recursive
- name: use VERSION file to support dev build on rel-branch
id: version
run: |
- if [ "${{ github.event_name }}" = "pull_request" ]; then
- echo "VERSION=today" >> $GITHUB_OUTPUT
- else
- echo "VERSION=$(cat VERSION)" >> $GITHUB_OUTPUT
- fi
+ echo "VERSION=$(cat VERSION)" >> $GITHUB_OUTPUT
build:
needs: [set_version]
if: ${{ github.event_name != 'pull_request' || github.event.action != 'closed' }}
- uses: gardenlinux/gardenlinux/.github/workflows/build.yml@40e7dfa820cb8bd5e0317779f818d31464c18c63
+ uses: gardenlinux/gardenlinux/.github/workflows/build.yml@409e9b640087ade203321a8d63bd1651f4677205
with:
version: ${{ needs.set_version.outputs.VERSION }}
# to set target to "release" or "nightly" we need proper KMS secrets
# have a look at gardenlinux/.github/workflows/github.mjs
target: dev
fail_fast: true
- platform_test_build: false
# secrets:
# aws_region: ${{ secrets.AWS_REGION }}
# aws_kms_role: ${{ secrets.KMS_SIGNING_IAM_ROLE }}
@@ -55,16 +58,18 @@ jobs:
runs-on: ubuntu-latest
outputs:
UPLOAD_VERSION: ${{ steps.meta.outputs.upload_version }}
- COMMIT_SHA: ${{ steps.meta.outputs.sha }}
+ image_tag: ${{ steps.meta.outputs.image_tag }}
steps:
- - name: Derive image version
+ - name: Checkout
+ uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
+ - name: Compute image metadata
id: meta
run: |
PR_NUMBER=${{ github.event.pull_request.number }}
UPLOAD_VERSION="pr-${PR_NUMBER}"
echo "upload_version=${UPLOAD_VERSION}" >> $GITHUB_OUTPUT
- SHA="${GITHUB_SHA::8}"
- echo "sha=${SHA}" >> $GITHUB_OUTPUT
+ IMAGE_TAG=$(.github/scripts/compute-image-tag.sh "${UPLOAD_VERSION}")
+ echo "image_tag=${IMAGE_TAG}" >> $GITHUB_OUTPUT
upload:
name: Upload PR image to OCI
@@ -83,7 +88,7 @@ jobs:
if: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository && github.event.action != 'closed' }}
uses: ./.github/workflows/test.yml
with:
- image_tag: "${{ needs.meta.outputs.UPLOAD_VERSION }}-metal-sci-usi-amd64-${{ needs.meta.outputs.UPLOAD_VERSION }}-${{ needs.meta.outputs.COMMIT_SHA }}"
+ image_tag: ${{ needs.meta.outputs.image_tag }}
cleanup_images:
name: Cleanup PR images
@@ -104,7 +109,7 @@ jobs:
response=$(curl -s -H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" \
-H "Accept: application/vnd.github+json" \
-H "X-GitHub-Api-Version: 2022-11-28" \
- "https://api.github.com/orgs/gardenlinux/packages/container/gardenlinux-ccloud/versions?per_page=$page_size&page=$page")
+ "https://api.github.com/orgs/gardenlinux/packages/container/gardenlinux-sci/versions?per_page=$page_size&page=$page")
page_ids=$(echo "$response" | jq -r --arg prefix "${UPLOAD_VERSION}" '
.[] | select(.metadata.container.tags[]? | test("^" + $prefix + "(-.*)?$")) | .id
@@ -133,7 +138,7 @@ jobs:
-H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" \
-H "Accept: application/vnd.github+json" \
-H "X-GitHub-Api-Version: 2022-11-28" \
- "https://api.github.com/orgs/gardenlinux/packages/container/gardenlinux-ccloud/versions/$version_id")
+ "https://api.github.com/orgs/gardenlinux/packages/container/gardenlinux-sci/versions/$version_id")
if [ "$http_code" != "204" ]; then
echo "Failed to delete version $version_id (HTTP $http_code)"
fi
diff --git a/.github/workflows/nightly.yaml b/.github/workflows/nightly.yaml
index 546d6f74..c6480aa6 100644
--- a/.github/workflows/nightly.yaml
+++ b/.github/workflows/nightly.yaml
@@ -14,29 +14,49 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
- uses: actions/checkout@v4
+ uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
with:
submodules: recursive
build:
needs: [checkout]
- uses: gardenlinux/gardenlinux/.github/workflows/build.yml@40e7dfa820cb8bd5e0317779f818d31464c18c63
+ uses: gardenlinux/gardenlinux/.github/workflows/build.yml@409e9b640087ade203321a8d63bd1651f4677205
with:
version: ${{ inputs.version || 'now' }}
# to set target to "release" or "nightly" we need proper KMS secrets
- # have a look at gardenlinux/.github/workflows/github.mjs
+ # have a look at gardenlinux/.github/workflows/github.mjs
target: dev
fail_fast: true
- platform_test_build: false
+ #platform_test_build: false
# secrets:
# aws_region: ${{ secrets.AWS_REGION }}
# aws_kms_role: ${{ secrets.KMS_SIGNING_IAM_ROLE }}
# aws_oidc_session: ${{ secrets.AWS_OIDC_SESSION }}
# secureboot_db_kms_arn: ${{ secrets.SECUREBOOT_DB_KMS_ARN }}
+ meta:
+ name: Compute image metadata
+ needs: [build]
+ runs-on: ubuntu-latest
+ outputs:
+ image_tag: ${{ steps.meta.outputs.image_tag }}
+ steps:
+ - name: Checkout
+ uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
+ - name: Compute image tag
+ id: meta
+ run: |
+ IMAGE_TAG=$(.github/scripts/compute-image-tag.sh "${{ needs.build.outputs.version }}")
+ echo "image_tag=${IMAGE_TAG}" >> $GITHUB_OUTPUT
upload_oci:
name: Run glcli to publish to OCI
needs: [build]
# use custom upload_oci.yml as we do not sign the images
- # uses: gardenlinux/gardenlinux/.github/workflows/upload_oci.yml@40e7dfa820cb8bd5e0317779f818d31464c18c63
+ # uses: gardenlinux/gardenlinux/.github/workflows/upload_oci.yml@409e9b640087ade203321a8d63bd1651f4677205
uses: ./.github/workflows/upload_oci.yml
with:
version: ${{ needs.build.outputs.version }}
+ test:
+ name: Test nightly image
+ needs: [meta, upload_oci]
+ uses: ./.github/workflows/test.yml
+ with:
+ image_tag: ${{ needs.meta.outputs.image_tag }}
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index ea9abc1f..87ecf16f 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -1,19 +1,11 @@
name: test hypervisor capabilities
on:
- push:
- branches:
- - feat/ci-test-cloud-hypervisor
- workflow_run:
- workflows:
- - nightly
- types:
- - completed
workflow_dispatch:
inputs:
image_tag:
description: "Image tag to test (must be usi-sci)"
type: string
- default: ""
+ required: true
workflow_call:
inputs:
image_tag:
@@ -26,20 +18,31 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
- uses: actions/checkout@v4
+ uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
+ - name: Install oras
+ uses: oras-project/setup-oras@1d808f7d7f6995cc68b7bf507bfe5c5446e1dc9d # v2
+ with:
+ version: 1.2.2
+ - name: Validate image tag
+ run: |
+ if [ -z "${{ inputs.image_tag }}" ]; then
+ echo "Error: image_tag is required"
+ exit 1
+ fi
+
+ echo "Verifying image ${{ inputs.image_tag }} exists in GHCR..."
+ if ! digest=$(oras resolve ghcr.io/gardenlinux/gardenlinux-sci:${{ inputs.image_tag }} 2>&1); then
+ echo "Error: Image tag '${{ inputs.image_tag }}' not found in ghcr.io/gardenlinux/gardenlinux-sci"
+ echo "Resolve output: $digest"
+ exit 1
+ fi
+ echo "Image tag present in GHCR (digest: ${digest:0:12}...)"
- name: Install Dependencies
uses: ./.github/actions/test/integration/dependencies
- - name: Obtain newest Tag from GHCR
- id: fetch_tag
- if: ${{ inputs.image_tag == '' || github.event_name == 'workflow_run' || github.event_name == 'push' }}
- run: |
- latest_tag=$(oras repo tags ghcr.io/gardenlinux/gardenlinux-ccloud | grep -E '^[0-9]+\.[0-9]+\.[0-9]+-metal-sci-usi-amd64-[0-9]+-[0-9]+-[0-9]-[0-9a-f]{8}$' | sort -r | head -n 1)
- echo $latest_tag
- echo "latest_tag=$latest_tag" >> $GITHUB_ENV
- name: Build
uses: ./.github/actions/test/integration/build
with:
- image_tag: ${{ env.latest_tag || inputs.image_tag }}
+ image_tag: ${{ inputs.image_tag }}
- name: Setup
uses: ./.github/actions/test/integration/setup
- name: Test QEMU
diff --git a/.github/workflows/upload_oci.yml b/.github/workflows/upload_oci.yml
index 896e2495..e32154f1 100644
--- a/.github/workflows/upload_oci.yml
+++ b/.github/workflows/upload_oci.yml
@@ -14,7 +14,7 @@ on:
jobs:
generate_matrix_publish:
name: Generate flavors matrix to publish
- uses: gardenlinux/gardenlinux/.github/workflows/build_flavors_matrix.yml@40e7dfa820cb8bd5e0317779f818d31464c18c63
+ uses: gardenlinux/gardenlinux/.github/workflows/build_flavors_matrix.yml@409e9b640087ade203321a8d63bd1651f4677205
with:
flags: '${{ inputs.flavor_filter }} --no-arch --json-by-arch --build --test'
upload_gl_artifacts:
@@ -37,14 +37,14 @@ jobs:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # pin@v4.1.1
with:
submodules: true
- - uses: oras-project/setup-oras@v1
+ - uses: oras-project/setup-oras@1d808f7d7f6995cc68b7bf507bfe5c5446e1dc9d # v2
- run: oras version
- name: Install python-gardenlinux-lib
- uses: gardenlinux/python-gardenlinux-lib/.github/actions/setup@hotfix-disabled-python-cache-in-setup-action
+ uses: gardenlinux/python-gardenlinux-lib/.github/actions/setup@19c1b24c01faab81a7fe24713748dd172d00904a
- name: Install cosign
- uses: sigstore/cosign-installer@v3.9.1
+ uses: sigstore/cosign-installer@6f9f17788090df1f26f669e9d70d6ae9567deba6 # v4.1.2
with:
- cosign-release: 'v2.4.1'
+ cosign-release: 'v3.1.3'
- name: Set flavor version reference
run: |
git rev-parse HEAD | cut -c1-8 | tee COMMIT
@@ -118,7 +118,7 @@ jobs:
with:
submodules: true
- name: Install python-gardenlinux-lib
- uses: gardenlinux/python-gardenlinux-lib/.github/actions/setup@hotfix-disabled-python-cache-in-setup-action
+ uses: gardenlinux/python-gardenlinux-lib/.github/actions/setup@19c1b24c01faab81a7fe24713748dd172d00904a
- name: Set flavor version reference
run: |
git rev-parse HEAD | cut -c1-8 | tee COMMIT
@@ -138,7 +138,7 @@ jobs:
mkdir manifests
mv oci_manifest_entry_${CNAME}.json manifests/
- gl-oci update-index \
- --container "ghcr.io/${{ github.repository }}" \
- --version ${{ inputs.upload_version || inputs.version }} \
+ gl-oci push-index-from-directory \
+ --index "ghcr.io/${{ github.repository }}" \
+ --index-tag ${{ inputs.upload_version || inputs.version }} \
--manifest_folder manifests
diff --git a/Containerfile b/Containerfile
new file mode 100644
index 00000000..edd1ecce
--- /dev/null
+++ b/Containerfile
@@ -0,0 +1,3 @@
+FROM ghcr.io/gardenlinux/builder:d6d24ba1aec66889a2acab83aedcb00e869abfcd@sha256:3dc78daebb56605baf105d2f20a6e8b94137237c1c2587b80d571fbb5c9f49ab
+
+RUN sed 's/version="$2"/version=\$(echo \$2 | cut -d. -f 1-2)/' -i /builder/bootstrap
diff --git a/README.md b/README.md
index 5d4d29bc..77b14dc7 100644
--- a/README.md
+++ b/README.md
@@ -17,3 +17,7 @@ The following make targets are available:
- `prepare`: Initialize and update submodules, required for first-time setup
- `update [COMMIT=]`: Update Garden Linux submodule to latest (or specific) commit and sync workflow references
- `clean`: Remove Garden Linux submodule and reset the environment
+
+
+
+
diff --git a/VERSION b/VERSION
deleted file mode 120000
index e96da460..00000000
--- a/VERSION
+++ /dev/null
@@ -1 +0,0 @@
-gardenlinux/VERSION
\ No newline at end of file
diff --git a/VERSION b/VERSION
new file mode 100644
index 00000000..161eda4d
--- /dev/null
+++ b/VERSION
@@ -0,0 +1 @@
+1877.21.0
diff --git a/bin/flavors_parse.py b/bin/flavors_parse.py
new file mode 120000
index 00000000..8c2e0e41
--- /dev/null
+++ b/bin/flavors_parse.py
@@ -0,0 +1 @@
+../gardenlinux/bin/flavors_parse.py
\ No newline at end of file
diff --git a/bin/garden-version b/bin/garden-version
deleted file mode 120000
index d88969eb..00000000
--- a/bin/garden-version
+++ /dev/null
@@ -1 +0,0 @@
-../gardenlinux/bin/garden-version
\ No newline at end of file
diff --git a/bin/garden-version b/bin/garden-version
new file mode 100755
index 00000000..48c2b777
--- /dev/null
+++ b/bin/garden-version
@@ -0,0 +1,155 @@
+#!/usr/bin/env bash
+
+# Contains sources from https://github.com/debuerreotype/debuerreotype
+
+set -Eeuo pipefail
+# shellcheck disable=2128
+thisDir="$(dirname "$(readlink -f "${BASH_SOURCE}")")"
+versionfile="$(readlink -f "${thisDir}/../VERSION")"
+startdate="Mar 31 00:00:00 UTC 2020"
+build_os="$(uname -s)"
+
+function check_command() {
+ if ! command -v "$1" >/dev/null 2>&1; then
+ echo "Error: The binary '$1' could not be found. Please make sure to install it." >&2
+ exit 1
+ fi
+}
+
+# Use "gdate" & sed (GNU) which must be installed by "Homebrew"
+# on macOS systems to have a normalized date interface
+if [ "Darwin" == "$build_os" ]; then
+ date_gnu="gdate"
+ sed_gnu="gsed"
+else
+ date_gnu="date"
+ sed_gnu="sed"
+fi
+check_command "$date_gnu"
+check_command "$sed_gnu"
+
+# shellcheck disable=1091
+source "${thisDir}/.constants.sh" \
+ --flags 'major,minor,patch,date,datefull,epoch,git' \
+ --usage '[ --major | --minor | --patch | --date | --datefull | --epoch | --git ] [|]' \
+ --sample '20200427' \
+ --sample '--date 27.1' \
+ --help "Generates version dependent values according to the file $versionfile or to the parameter handed over. Versions can be converted adequately
+
+--major prints only the major version
+--minor prints only the minor version
+--patch prints only the patch/patch version
+--date prints the date according to the version e.g. 20200427 if garden-version=27
+--datefull prints a full date deteministically usable by debootstrap
+--epoch prints the seconds sinc 19700101 till garden-version
+--git prints the version plus the last git-hash
+
+If no parameter is specified the full version . e.g. 27.5 is printed. The version is taken from $versionfile. On HEAD this should always evaluate to 'today', on branch versions this always should resolve to the next version that will be build e.g. 27.1. This implies there is no branch with a .0 in the $versionfile file.
+The version calculated expresses the days since $startdate. Calculation is always UTC based."
+
+# shellcheck disable=2154
+eval "${dgetopt}"
+typeout="default"
+while true; do
+ flag="$1"; shift
+ dgetopt-case "${flag}"
+ case "${flag}" in
+ --major|--minor|--patch|--date|--datefull|--epoch|--git)
+ typeout="${flag}" ;;
+ --) break ;;
+ *) eusage "unknown flag '${flag}'" ;;
+ esac
+done
+
+# Checks repo.gardenlinux.io for the highest available suite minor for the given major
+function get_minor_from_repo {
+ minor=0 # running index
+ limit=100 # hard limit the search in case of unexpected curl results
+ major=$1 # major to check the latest minor for
+ repo_url="https://packages.gardenlinux.io/gardenlinux/dists/$major.__MINOR__/InRelease"
+ while [ $minor -le $limit ]
+ do
+ check_url=${repo_url//__MINOR__/$minor}
+ if curl -s "$check_url" | grep -q "Error"; then
+ ((minor--))
+ echo $minor
+ return
+ fi
+ ((minor++))
+ done
+}
+
+function get_patch_from_repo {
+ # TODO: implement if we really expect that we'll ever have a nonzero micro/patch version
+ local major=$1
+ local minor=$2
+ if [ "$minor" -eq -1 ]; then
+ echo -1
+ return
+ fi
+ echo 0
+ return
+}
+
+function trim_when_old_version {
+ if [ "$1" == "today" ] || [ "$1" == "experimental" ]; then
+ echo "$1"
+ return
+ fi
+ # HACK just for 1877 for SCI
+ # shellcheck disable=2046
+ if [ $(echo "$1" | cut -d. -f1) -lt 1876 ]; then
+ echo "$1" | cut -d. -f1-2
+ else
+ echo "$1"
+ fi
+}
+
+input="${1:-$($sed_gnu -e "s/#.*\$//" -e "/^$/d" "${versionfile}")}"; shift || true
+input=$($sed_gnu "s/^[[:space:]]*//;s/[[:space:]]*\$//" <<< "${input}")
+
+# no version / timestamp on versionfile
+[ -z "${input}" ] && input="today"
+
+minor=0
+patch=0
+# shellcheck disable=2046
+if [[ "${input}" =~ ^[0-9\.]*$ && $(cut -d. -f1 <<< "${input}") -lt 10000000 ]];
+then [ $(cut -d. -sf4 <<< "${input}") ] && eusage "invalid version format ${input}. should be [..]"
+
+ major="$(cut -d. -f1 <<< "${input}")"
+ # shellcheck disable=2046
+ if [ $(cut -d. -sf2 <<< "${input}") ]; then
+ minor="$(cut -d. -f2 <<< "${input}")"
+ else
+ minor=$(get_minor_from_repo "$major")
+ fi
+ # shellcheck disable=2046
+ if [ $(cut -d. -sf3 <<< "${input}") ]; then
+ patch="$(cut -d. -f3 <<< "${input}")"
+ else
+ patch=$(get_patch_from_repo "$major" "$minor")
+ fi
+ version="${major}.${minor}.${patch}"
+else
+ if [[ ${input} = today ]] || [[ ${input} = experimental ]];
+ then indate=$($date_gnu --date "today" +%s 2>/dev/null)
+ major="$(( ("${indate}" - $($date_gnu --date "${startdate}" +%s)) / (60*60*24) ))"
+ version=${input}
+ else indate=$($date_gnu --date "${input}" +%s 2>/dev/null) || eusage "invalid date ${input}"
+ major="$(( ("${indate}" - $($date_gnu --date "${startdate}" +%s)) / (60*60*24) ))"
+ version="${major}.${minor}.${patch}"
+ fi
+fi
+
+# shellcheck disable=2154
+case "${typeout}" in
+ --major) echo "${major}" ;;
+ --minor) echo "${minor}" ;;
+ --patch) echo "${patch}" ;;
+ --date) $date_gnu --date "${startdate} + ${major} days" +%Y%m%d ;;
+ --datefull) $date_gnu --date "${startdate} + ${major} days" +%Y%m%dT%H%M%SZ ;;
+ --epoch) $date_gnu --date "${startdate} + ${major} days" +%s ;;
+ --git) echo "$(trim_when_old_version "${version}")-$(git -C "${scriptsDir}" rev-parse --short 'HEAD^{commit}')" ;;
+ *) trim_when_old_version "${version}" ;;
+esac
diff --git a/build b/build
deleted file mode 120000
index 9a5480ab..00000000
--- a/build
+++ /dev/null
@@ -1 +0,0 @@
-gardenlinux/build
\ No newline at end of file
diff --git a/build b/build
new file mode 100755
index 00000000..cc890cd0
--- /dev/null
+++ b/build
@@ -0,0 +1,128 @@
+#!/usr/bin/env bash
+
+set -euo pipefail
+shopt -s nullglob
+
+exec 3>&1
+exec 1>&2
+
+#container_image=ghcr.io/gardenlinux/builder:d6d24ba1aec66889a2acab83aedcb00e869abfcd
+container_image=localhost/builder
+container_engine=podman
+target_dir=.build
+
+container_run_opts=(
+ --memory 4G
+ --security-opt seccomp=unconfined
+ --security-opt apparmor=unconfined
+ --security-opt label=disable
+ --read-only
+)
+
+container_cmd=()
+
+use_kms=0
+resolve_cname=0
+
+while [ $# -gt 0 ]; do
+ case "$1" in
+ --container-image)
+ container_image="$2"
+ shift 2
+ ;;
+ --container-engine)
+ container_engine="$2"
+ shift 2
+ ;;
+ --container-run-opts)
+ declare -a "container_run_opts=($2)"
+ shift 2
+ ;;
+ --privileged)
+ container_run_opts+=(--privileged)
+ container_cmd=(--second-stage)
+ shift
+ ;;
+ --kms)
+ use_kms=1
+ shift
+ ;;
+ --print-container-image)
+ printf '%s\n' "$container_image" >&3
+ exit 0
+ ;;
+ --resolve-cname)
+ resolve_cname=1
+ shift
+ ;;
+ --target)
+ target_dir="$2"
+ shift 2
+ ;;
+ *)
+ break
+ ;;
+ esac
+done
+
+[ -d "$target_dir" ] || mkdir "$target_dir"
+
+container_mount_opts=(
+ -v "$PWD/keyring.gpg:/builder/keyring.gpg:ro"
+ -v "$(realpath "$target_dir"):/builder/.build"
+)
+
+for feature in features/*; do
+ if [ -d "$feature" ]; then
+ container_mount_opts+=(-v "$(realpath -- "$feature"):/builder/$feature:ro")
+ fi
+done
+
+if [ "$container_image" = localhost/builder ]; then
+ dir="$(dirname -- "$(realpath -- "${BASH_SOURCE[0]}")")"
+ "$container_engine" build -t "$container_image" "$dir"
+fi
+
+repo="$(./get_repo)"
+commit="$(./get_commit)"
+timestamp="$(./get_timestamp)"
+default_version="$(./get_version)"
+
+
+if [ "$resolve_cname" = 1 ]; then
+ arch="$("$container_engine" run --rm "${container_run_opts[@]}" "${container_mount_opts[@]}" "$container_image" dpkg --print-architecture)"
+ cname="$("$container_engine" run --rm "${container_run_opts[@]}" "${container_mount_opts[@]}" "$container_image" /builder/parse_features --feature-dir /builder/features --default-arch "$arch" --default-version "$default_version" --cname "$1")"
+ short_commit="$(head -c 8 <<< "$commit")"
+ echo "$cname-$short_commit" >&3
+ exit 0
+fi
+
+make_opts=(
+ REPO="$repo"
+ COMMIT="$commit"
+ TIMESTAMP="$timestamp"
+ DEFAULT_VERSION="$default_version"
+)
+
+if [ "$use_kms" = 1 ]; then
+ for e in AWS_DEFAULT_REGION AWS_REGION AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY AWS_SESSION_TOKEN; do
+ if [ -n "${!e-}" ]; then
+ make_opts+=("$e=${!e}")
+ fi
+ done
+fi
+
+# Default values which can be overriden via 'build.config' file
+tempfs_size=2G
+
+if [[ -f "$PWD"/build.config ]]; then
+ . "$PWD"/build.config
+fi
+
+make_opts+=("TEMPFS_SIZE=$tempfs_size")
+
+if [ -d cert ]; then
+ container_mount_opts+=(-v "$PWD/cert:/builder/cert:ro")
+fi
+
+"$container_engine" run --rm "${container_run_opts[@]}" "${container_mount_opts[@]}" "$container_image" ${container_cmd[@]+"${container_cmd[@]}"} fake_xattr make --no-print-directory -C /builder "${make_opts[@]}" "$@" >&3
diff --git a/features/_iso b/features/_iso
deleted file mode 120000
index d7ebec9b..00000000
--- a/features/_iso
+++ /dev/null
@@ -1 +0,0 @@
-../gardenlinux/features/_iso
\ No newline at end of file
diff --git a/features/_iso/README.md b/features/_iso/README.md
new file mode 100644
index 00000000..41b572d0
--- /dev/null
+++ b/features/_iso/README.md
@@ -0,0 +1,21 @@
+## Feature: _iso
+
+## !! USE THIS FOR DEMO PURPOSES ONLY !!
+
+### Description
+
+
+This feature flag creates an `.iso` artifact of Garden Linux.
+The root user has a hardcoded password _gardenlinux_
+
+
+### Features
+This feature simply creates a bootable `.iso` image as an additional artifact.
+
+### Meta
+|||
+|---|---|
+|type|flag|
+|artifact|None|
+|included_features|None|
+|excluded_features|None|
diff --git a/features/_iso/exec.config b/features/_iso/exec.config
new file mode 100755
index 00000000..c8536047
--- /dev/null
+++ b/features/_iso/exec.config
@@ -0,0 +1 @@
+echo "root:gardenlinux" | chpasswd -c YESCRYPT
diff --git a/features/_iso/file.include/etc/kernel/cmdline.d/99-serial.cfg b/features/_iso/file.include/etc/kernel/cmdline.d/99-serial.cfg
new file mode 100644
index 00000000..e438d02d
--- /dev/null
+++ b/features/_iso/file.include/etc/kernel/cmdline.d/99-serial.cfg
@@ -0,0 +1 @@
+CMDLINE_LINUX="$CMDLINE_LINUX console=ttyS0,115200"
diff --git a/features/_iso/file.include/opt/install/install.sh b/features/_iso/file.include/opt/install/install.sh
new file mode 100755
index 00000000..906f4831
--- /dev/null
+++ b/features/_iso/file.include/opt/install/install.sh
@@ -0,0 +1,59 @@
+#!/usr/bin/env bash
+set -ue
+
+thisDir=$(readlink -f $(dirname "${BASH_SOURCE[0]}"))
+
+targetDisk="$1"
+
+pushd "$thisDir"
+
+# remove all HD related boot entries
+for e in $(efibootmgr | awk '$NF ~ /^HD/ { print $1 }' | sed "s/Boot\([0-9A-F]*\)./\1/"); do
+ echo "Removing entry $e"
+ efibootmgr -B -b "$e" > /dev/null
+done
+
+# prepare disk for repart
+sgdisk -Z "$targetDisk"
+sgdisk -o "$targetDisk"
+
+# actually partition and populate with data
+mkdir -p /run/source
+mount --bind / /run/source
+systemd-repart --definitions repart/ --json=pretty --dry-run=off --copy-source=/run/source/ "$targetDisk"
+
+sleep 5
+
+# prepare mounts for chroot env
+target="/run/chroot"
+mkdir "$target"
+mount /dev/disk/by-label/ROOT "$target"
+mount /dev/disk/by-label/ESP "$target/efi"
+
+# prepare extra mounts
+pushd "$target" > /dev/null
+mount -t proc proc proc
+mount -t sysfs sys sys
+mount --bind /dev dev
+
+# regenerate initrd and generate loader entries
+chroot "$target" dracut -f /boot/initrd.img-"$(uname -r)"
+
+if mount --bind /sys/firmware/efi/efivars "$target/sys/firmware/efi/efivars"; then
+ # efi
+ chroot "$target" bootctl install
+ chroot "$target" kernel-install add "$(uname -r)" "/boot/vmlinuz-$(uname -r)" "/boot/initrd.img-$(uname -r)"
+else
+ # legacy
+ chroot "${target}" sfdisk --part-attrs "${targetDisk}" 1 LegacyBIOSBootable
+ chroot "${target}" dd if="/usr/lib/SYSLINUX/gptmbr.bin" of="${targetDisk}" bs=440 count=1 conv=notrunc
+ chroot "${target}" mkdir -p /efi/syslinux
+ chroot "${target}" cp /usr/lib/syslinux/modules/bios/menu.c32 /efi/syslinux/
+ chroot "${target}" cp /usr/lib/syslinux/modules/bios/libutil.c32 /efi/syslinux/
+ chroot "${target}" syslinux --directory syslinux --install /dev/disk/by-label/ESP
+ mkdir /run/chroot/efi/Default
+ chroot "$target" kernel-install add "$(uname -r)" "/boot/vmlinuz-$(uname -r)" "/boot/initrd.img-$(uname -r)"
+ chroot "${target}" update-syslinux
+fi
+
+echo "Safe to reboot"
diff --git a/features/_iso/file.include/opt/install/repart/00-efi.conf b/features/_iso/file.include/opt/install/repart/00-efi.conf
new file mode 100644
index 00000000..d71d8caa
--- /dev/null
+++ b/features/_iso/file.include/opt/install/repart/00-efi.conf
@@ -0,0 +1,8 @@
+# modify only the size to fit your needs
+[Partition]
+Type=esp
+Format=vfat
+SizeMinBytes=1024M
+SizeMaxBytes=1024M
+Label=ESP
+MountPoint=/efi
diff --git a/features/_iso/file.include/opt/install/repart/10-root.conf b/features/_iso/file.include/opt/install/repart/10-root.conf
new file mode 100644
index 00000000..617337f0
--- /dev/null
+++ b/features/_iso/file.include/opt/install/repart/10-root.conf
@@ -0,0 +1,9 @@
+# modify only the size to fit your needs, do not specify the size to use whatever space is left on disk
+[Partition]
+Type=root
+#SizeMinBytes=2G
+#SizeMaxBytes=2G
+CopyFiles=/
+CopyFiles=/boot
+Label=ROOT
+MountPoint=/
diff --git a/features/_iso/image.iso b/features/_iso/image.iso
new file mode 100755
index 00000000..2c875f5a
--- /dev/null
+++ b/features/_iso/image.iso
@@ -0,0 +1,85 @@
+#!/usr/bin/env bash
+set -euo pipefail
+
+input="$(realpath -- "$1")"
+output="$(realpath -- "$2")"
+
+dir="$(mktemp -d)"
+pushd "$dir" > /dev/null
+
+export PATH="/builder/image.d:$PATH"
+
+chroot_dir="$(mktemp -d)"
+mount -t tmpfs tmpfs "$chroot_dir"
+tar --extract --xattrs --xattrs-include '*' --directory "$chroot_dir" < "$input"
+
+mount --rbind --make-rprivate /proc "$chroot_dir/proc"
+mount --rbind --make-rprivate /sys "$chroot_dir/sys"
+mount --rbind --make-rprivate /dev "$chroot_dir/dev"
+mount --bind /usr/bin/false "${chroot_dir}/usr/bin/systemd-detect-virt"
+
+kernel=$(echo "${chroot_dir}"/boot/vmlinuz-* | tr " " '\n' | cut -d- -f 2- | sort -V | tail -1)
+chroot "$chroot_dir" dracut -f /tmp/initrd "${kernel}" -m "bash systemd systemd-initrd kernel-modules kernel-modules-extra terminfo dracut-systemd shutdown dmsquash-live" --reproducible
+
+# we use ukify because dracut 059 and systemd 254 don't mix, dracut generate a broken uki
+# https://github.com/dracutdevs/dracut/issues/2431
+# TODO: fix when dracut is fixed
+#chroot "${chroot_dir}" dracut -f /tmp/unified ${kernel} --uefi --kernel-cmdline "console=tty0 console=ttyS0,115200 rd.live.squashimg=squashfs.img root=live:CDLABEL=GardenlinuxISO rd.live.overlay.overlayfs rd.live.dir=live rd.live.ram" -m "bash systemd systemd-initrd kernel-modules kernel-modules-extra terminfo dracut-systemd shutdown dmsquash-live" --reproducible
+chroot "${chroot_dir}" /lib/systemd/ukify build --output=/tmp/unified --linux=/boot/vmlinuz-"${kernel}" --initrd=/tmp/initrd --cmdline="console=tty0 console=ttyS0,115200 rd.live.squashimg=squashfs.img root=live:CDLABEL=GardenlinuxISO rd.live.overlay.overlayfs rd.live.dir=live rd.live.ram"
+
+umount -l "$chroot_dir/proc"
+umount -l "$chroot_dir/sys"
+umount -l "$chroot_dir/dev"
+umount "${chroot_dir}/usr/bin/systemd-detect-virt"
+
+mkdir CD_root
+mkdir CD_root/{isolinux,images,kernel,boot,boot/images,boot/syslinux,live}
+
+mksquashfs "$chroot_dir" "CD_root/live/squashfs.img" -comp lzo
+cp "${chroot_dir}/boot/"vmlinuz* "CD_root/boot/images/vmlinuz"
+mv "${chroot_dir}/tmp/"initrd* "CD_root/boot/images/initrd"
+mv "${chroot_dir}/tmp/unified" bootx64.efi
+
+#TODO: determine proper size
+dd if=/dev/zero of=efiboot.img bs=512 count=131072
+mkfs.msdos -F 16 -n 'EFIBOOTISO' efiboot.img
+mmd -i efiboot.img ::EFI
+mmd -i efiboot.img ::EFI/BOOT
+mcopy -i efiboot.img bootx64.efi ::EFI/BOOT/BOOTX64.EFI
+
+mv efiboot.img CD_root/isolinux/
+cp "${chroot_dir}/usr/lib/ISOLINUX/isolinux.bin" CD_root/isolinux/
+cp "${chroot_dir}/usr/lib/ISOLINUX/isohdpfx.bin" CD_root/isolinux/
+cp "${chroot_dir}/usr/lib/syslinux/modules/bios/ldlinux.c32" CD_root/isolinux
+
+cat << EOF > CD_root/isolinux/isolinux.cfg
+PATH /boot/syslinux
+DEFAULT loadconfig
+
+LABEL loadconfig
+ CONFIG /boot/syslinux/syslinux.cfg
+EOF
+
+cat << EOF > CD_root/boot/syslinux/syslinux.cfg
+MENU TITLE gardenlinux
+DEFAULT GardenlinuxRam
+
+LABEL GardenlinuxRam
+MENU LABEL Gardenlinux Live in RAM
+LINUX /boot/images/vmlinuz console=tty0 console=ttyS0,115200 rd.live.squashimg=squashfs.img root=live:CDLABEL=GardenlinuxISO rd.live.overlay.overlayfs rd.live.dir=live rd.live.ram
+INITRD /boot/images/initrd
+EOF
+
+# TODO: make this reproducible
+xorriso -as mkisofs \
+ -volid "GardenlinuxISO" \
+ -o "${output}" \
+ -isohybrid-mbr "${chroot_dir}/usr/lib/ISOLINUX/isohdpfx.bin" \
+ -c isolinux/boot.cat \
+ -b isolinux/isolinux.bin \
+ -no-emul-boot -boot-load-size 4 -boot-info-table \
+ -eltorito-alt-boot \
+ -e isolinux/efiboot.img \
+ -no-emul-boot \
+ -isohybrid-gpt-basdat \
+ CD_root
diff --git a/features/_iso/info.yaml b/features/_iso/info.yaml
new file mode 100644
index 00000000..302d84a9
--- /dev/null
+++ b/features/_iso/info.yaml
@@ -0,0 +1,6 @@
+description: "iso"
+type: flag
+features:
+ exclude:
+ - _selinux
+ - sap
diff --git a/features/_iso/pkg.include b/features/_iso/pkg.include
new file mode 100644
index 00000000..b70528d8
--- /dev/null
+++ b/features/_iso/pkg.include
@@ -0,0 +1,8 @@
+dracut
+dracut-core
+dracut-live
+binutils
+isolinux
+python3-pefile
+systemd-ukify
+gdisk
diff --git a/features/_iso/test/autologin.disable b/features/_iso/test/autologin.disable
new file mode 100644
index 00000000..e69de29b
diff --git a/features/_iso/test/test_capabilities.py b/features/_iso/test/test_capabilities.py
new file mode 100644
index 00000000..c0048aee
--- /dev/null
+++ b/features/_iso/test/test_capabilities.py
@@ -0,0 +1 @@
+from helper.tests.capabilities import capabilities as test_capabilities
diff --git a/features/_iso/test/test_packages_musthave.py b/features/_iso/test/test_packages_musthave.py
new file mode 100644
index 00000000..4b2783d2
--- /dev/null
+++ b/features/_iso/test/test_packages_musthave.py
@@ -0,0 +1 @@
+from helper.tests.packages_musthave import packages_musthave as test_packages_musthave
diff --git a/features/_pxe/file.include/usr/lib/dracut/modules.d/98gardenlinux-live/live-get-squashfs.sh b/features/_pxe/file.include/usr/lib/dracut/modules.d/98gardenlinux-live/live-get-squashfs.sh
index 818d0f38..bc30d2c7 100755
--- a/features/_pxe/file.include/usr/lib/dracut/modules.d/98gardenlinux-live/live-get-squashfs.sh
+++ b/features/_pxe/file.include/usr/lib/dracut/modules.d/98gardenlinux-live/live-get-squashfs.sh
@@ -27,7 +27,7 @@ if [ ! -f "${shaFile}" ]; then
exit 1
fi
-if ! echo "$(grep . ${shaFile}) ${squashFile}" | sha256sum --status --check; then
+if ! echo "$(grep . ${shaFile}) ${squashFile}" | sha256sum --status --check -; then
warn "the hash verification of the squashfs has failed - exiting"
exit 1
fi
diff --git a/features/_rescue/file.include/etc/systemd/system/emergency.service.d/debugprint.conf b/features/_rescue/file.include/etc/systemd/system/emergency.service.d/debugprint.conf
index fd70fadb..2b7feac7 100644
--- a/features/_rescue/file.include/etc/systemd/system/emergency.service.d/debugprint.conf
+++ b/features/_rescue/file.include/etc/systemd/system/emergency.service.d/debugprint.conf
@@ -2,9 +2,8 @@
StandardOutput=journal+console
StandardError=journal+console
ExecStartPre=/bin/sh -c ' \
- systemctl --failed --no-legend --no-pager | awk "{print \$2}" | \
- xargs -r -I{} sh -c " \
- echo \"\\n=== FAILED UNIT: {} ===\\n\"; \
- journalctl -b -u {} --no-pager || true; \
- "'
+ for unit in $(systemctl --failed --no-legend --no-pager | awk "{print \$2}"); do \
+ echo "\n=== FAILED UNIT: $unit ===\n"; \
+ journalctl -b -u "$unit" --no-pager || true; \
+ done'
TimeoutStartSec=20s
diff --git a/features/_scicommon/exec.config b/features/_scicommon/exec.config
index c67667e1..d18e272c 100755
--- a/features/_scicommon/exec.config
+++ b/features/_scicommon/exec.config
@@ -12,19 +12,19 @@ for feature in "${FEATURES[@]}"; do
done
# capi versions: https://github.com/kubernetes-sigs/cri-tools/releases
-CAPI_VERSION=v1.33.0
+CAPI_VERSION=v1.35.0
K8S_VERSION_REPO="${CAPI_VERSION%.*}"
# key can be downloaded liek e.g.
# curl -fsSL https://pkgs.k8s.io/core:/stable:/${K8S_VERSION_REPO}/deb/Release.key > pkgs-k8s-io_${K8S_VERSION_REPO}_release.key
-gpg --dearmor -o "/etc/apt/keyrings/kubernetes-${K8S_VERSION_REPO}-apt-keyring.gpg" <"/builder/features/_scicommon/pkgs-k8s-io_${K8S_VERSION_REPO}_release.key"
+cp "/builder/features/_scicommon/pkgs-k8s-io_${K8S_VERSION_REPO}_release.key" "/etc/apt/keyrings/kubernetes-${K8S_VERSION_REPO}-apt-keyring.asc"
cat < /dev/null
+dpkg -i ignition_*_amd64.deb
+popd > /dev/null
+rm -rf "$TEMP_DIR"
diff --git a/features/_usi/file.exclude b/features/_usi/file.exclude
index 9c50a71c..86e0873c 100644
--- a/features/_usi/file.exclude
+++ b/features/_usi/file.exclude
@@ -6,3 +6,8 @@
#/opt/{,.}*
#/home/{,.}*
/root/{,.}*
+/etc/cron.daily/apt-compat
+/etc/cron.daily/dpkg
+/etc/cron.daily/quota
+/etc/cron.monthly/update-pciids
+/etc/cron.monthly/update-usbids
diff --git a/features/_usi/file.include/etc/systemd/system-preset/00-systemd-usi.preset b/features/_usi/file.include/etc/systemd/system-preset/00-systemd-usi.preset
index 56084989..55578a5e 100644
--- a/features/_usi/file.include/etc/systemd/system-preset/00-systemd-usi.preset
+++ b/features/_usi/file.include/etc/systemd/system-preset/00-systemd-usi.preset
@@ -2,4 +2,6 @@
disable apt-daily.timer
disable dpkg-db-backup.timer
disable systemd-sysupdate-reboot.timer
+disable systemd-sysupdate-reboot.service
disable systemd-sysupdate.timer
+disable systemd-sysupdate.service
diff --git a/features/_usi/file.include/etc/systemd/system/dbgimport.service b/features/_usi/file.include/etc/systemd/system/dbgimport.service
new file mode 100644
index 00000000..2b84b937
--- /dev/null
+++ b/features/_usi/file.include/etc/systemd/system/dbgimport.service
@@ -0,0 +1,13 @@
+[Unit]
+Description=Import debug container image
+ConditionPathExists=|/opt/dbgimage/debug.tar
+ConditionFirstBoot=yes
+After=containerd.service
+Requires=containerd.service
+
+[Service]
+ExecStart=/bin/sh -c 'ctr image import --base-name "$(cat /opt/dbgimage/debug.tar.name)" /opt/dbgimage/debug.tar && rm -f /opt/dbgimage/debug.tar && rm -f /opt/dbgimage/debug.tar.name && rm -f /opt/dbgimage/image'
+Type=oneshot
+
+[Install]
+WantedBy=multi-user.target
diff --git a/features/_usi/file.include/etc/systemd/system/systemd-repart.service b/features/_usi/file.include/etc/systemd/system/systemd-repart.service
new file mode 120000
index 00000000..dc1dc0cd
--- /dev/null
+++ b/features/_usi/file.include/etc/systemd/system/systemd-repart.service
@@ -0,0 +1 @@
+/dev/null
\ No newline at end of file
diff --git a/features/_usi/initrd.include/etc/systemd/system/systemd-repart.service b/features/_usi/initrd.include/etc/systemd/system/systemd-repart.service
new file mode 120000
index 00000000..dc1dc0cd
--- /dev/null
+++ b/features/_usi/initrd.include/etc/systemd/system/systemd-repart.service
@@ -0,0 +1 @@
+/dev/null
\ No newline at end of file
diff --git a/features/_usi/initrd.include/usr/bin/detect_disk b/features/_usi/initrd.include/usr/bin/detect_disk
index 0a8fb937..d061a300 100755
--- a/features/_usi/initrd.include/usr/bin/detect_disk
+++ b/features/_usi/initrd.include/usr/bin/detect_disk
@@ -4,10 +4,6 @@ set -Eeuo pipefail
ROOT_HINTS_FILE="/sysroot/opt/persist/root-hints.yaml"
-if ! [[ -f $ROOT_HINTS_FILE ]]; then
- echo "no root-hints.yaml provided, error"
- exit 1
-fi
if kname=$(/usr/bin/root-hints $ROOT_HINTS_FILE); then
echo "/dev/${kname}"
else
diff --git a/features/_usi/initrd.include/usr/bin/persist b/features/_usi/initrd.include/usr/bin/persist
index ad950446..26fcaca0 100755
--- a/features/_usi/initrd.include/usr/bin/persist
+++ b/features/_usi/initrd.include/usr/bin/persist
@@ -6,6 +6,11 @@ if ! disk_dev=$(/usr/bin/detect_disk); then
exit 1
fi
+if [[ ! -b "$disk_dev" ]]; then
+ echo "Device $disk_dev not found, exiting"
+ exit 1
+fi
+
# clean up the disk
sgdisk -Z "$disk_dev"
sgdisk -o "$disk_dev"
@@ -70,14 +75,14 @@ export HOME=/root
# source optional config file
[ -f /sysroot/opt/persist/gl-oci.conf ] && . /sysroot/opt/persist/gl-oci.conf
-OCI_REPO="${OCI_REPO:-keppel.global.cloud.sap/ccloud-ghcr-io-mirror/gardenlinux/gardenlinux-ccloud}"
+OCI_REPO="${OCI_REPO:-keppel.global.cloud.sap/ccloud-ghcr-io-mirror/gardenlinux/gardenlinux-sci}"
DASHED_GARDENLINUX_VERSION=${GARDENLINUX_VERSION//./-}
# setup OCI_TAG, UKI_SHA and fetch UKI
OCI_TAG=${OCI_TAG:-"$GARDENLINUX_VERSION-$VARIANT_ID-${DASHED_GARDENLINUX_VERSION}-$GARDENLINUX_COMMIT_ID"}
OCI_TAG=${OCI_TAG//_/-} # replace underscores with dashes
UKI_SHA=$(oras manifest fetch "$OCI_REPO:${OCI_TAG}" | jq -r '.layers[] | select(.mediaType=="application/io.gardenlinux.uki") | .digest')
-oras blob fetch "$OCI_REPO@$UKI_SHA" -o "$esp_dir/EFI/Linux/uki.efi"
+oras blob fetch "$OCI_REPO@$UKI_SHA" -o "$esp_dir/EFI/Linux/${GARDENLINUX_CNAME}.efi"
if [ "$ENABLE_HUGEPAGE_SETUP" = "true" ]; then
echo "hugepagesz=2MB hugepages=$hugepages" > /tmp/cmdlinef
@@ -94,6 +99,20 @@ if [ "$ENABLE_HUGEPAGE_SETUP" = "true" ]; then
objcopy --add-section .cmdline=/tmp/cmdlinef --change-section-vma .cmdline=$(printf 0x%x $offs) $addon "$addon_dir/hugepages.addon.efi"
fi
+# debug container
+DBG_CONTAINER_IMPORT="/sysroot/opt/dbgimage"
+DBG_CONTAINER_IMAGE_DUMP="debug.tar"
+DBG_CONTAINER_FILE="/sysroot/opt/dbgimage/image"
+
+mkdir -p "$DBG_CONTAINER_IMPORT"
+if [ -f "$DBG_CONTAINER_FILE" ]; then
+ oras backup --output "$DBG_CONTAINER_IMPORT/$DBG_CONTAINER_IMAGE_DUMP" "$(cat "$DBG_CONTAINER_FILE")"
+ cat "$DBG_CONTAINER_FILE" | awk -F':' '{print $1}' > "$DBG_CONTAINER_IMPORT/$DBG_CONTAINER_IMAGE_DUMP.name"
+else
+ echo "no container image file provided, skipping..."
+fi
+
+
# Network config generation
if [[ -x /sysroot/opt/persist/network_up.sh ]]; then
chroot /sysroot /opt/persist/network_up.sh
diff --git a/features/_usi/initrd.include/usr/bin/root-hints b/features/_usi/initrd.include/usr/bin/root-hints
index 5186752f..360bac06 100755
--- a/features/_usi/initrd.include/usr/bin/root-hints
+++ b/features/_usi/initrd.include/usr/bin/root-hints
@@ -2,12 +2,17 @@
set -Eeuo pipefail
+# setup error trap
+trap 'err "Error occurred at line $LINENO while executing: $BASH_COMMAND"' ERR
+
function yqroot() {
cat "$1" | chroot /sysroot /usr/bin/yq -c '.hints | .[]'
}
function err() {
echo "$@" 1>&2
+
+ lsblk -bOJ | jq
}
function filter() {
@@ -27,25 +32,94 @@ function filter() {
fi
if [[ $val =~ ^[0-9]+[KMGT]+$ ]]; then
val=$(echo "$val" | numfmt --from=iec)
- echo "and ${col^^} $op ${val}"
+ echo "${col^^} $op ${val}"
else
- echo "and ${col^^} $op \"${val}\""
+ echo "${col^^} $op \"${val}\""
fi
+}
+function blockdevicesize() {
+ local kname="$1"
+ lsblk -bOJ | jq --arg kname "$kname" -r '.blockdevices.[] | select(.kname == $kname).size'
}
+udevadm settle
+
yamlFile="$1"
+esp_disk=""
+if [ -e "/dev/disk/by-label/ESP" ]; then
+ esp_partition=$(basename "$(readlink -f /dev/disk/by-label/ESP)")
+ esp_disk=$(basename "$(readlink -f "/sys/class/block/$esp_partition/..")")
+fi
+
+# TODO: likely go rather with device uuid or alike
#if dev=$(yq -e .dev "$yamlFile" 2> /dev/null); then
# echo "$dev"
# exit 0
#fi
-flsblk="TYPE eq \"disk\""
-while IFS= read -r r; do
- f=$(filter "$r")
- flsblk="$flsblk $f"
-done < <(yqroot "$yamlFile" )
+declare -a flsblk=()
+# check if yaml file exists and is valid, if so, use it to build the filter for lsblk
+if [ -f "$yamlFile" ] && yq -e . "$yamlFile" >/dev/null 2>&1; then
+ while IFS= read -r r; do
+ flsblk+=("$(filter "$r")")
+ done < <(yqroot "$yamlFile")
+fi
+
+LSBLK_JSON=""
+
+function join {
+ local SEPARATOR="$1"
+ shift
+ printf "%s${SEPARATOR}" "$@" | sed --unbuffered "s/${SEPARATOR}$//"
+}
+
+# if flsblk contains elements, we join them by 'and' and use the filter with lsblk
+if [ ${#flsblk[@]} -gt 0 ]; then
+ flsfilter=$(join " and " "${flsblk[@]}")
+ echo "Using filter: $flsfilter" 1>&2
+ LSBLK_JSON=$(lsblk --sort size --exclude 1,2,3,4,7,11 --filter "$flsfilter" -OJ)
+else
+ # no hints, hence we choose the smallest disk we find. we exclude ram disk,
+ # floppy, ide, dynamically allocated, loopback and scsi cd-rom devices
+ LSBLK_JSON=$(lsblk --sort size --exclude 1,2,3,4,7,11 -OJ)
+fi
-#echo "$flsblk"
-lsblk --filter "$flsblk" --noheadings -o kname
+# from the resulting list of disks we pick the first disk that are writeable
+kname=$(echo "$LSBLK_JSON" | jq -r '[.blockdevices.[]|select(.type? == "disk" and .ro? == false)][0].kname // ""')
+
+# check which disk to use.
+# 1. if kname is empty:
+# * we check if we have an esp_disk, if so we use it
+# * otherwise we fail
+# 2. if kname is not empty:
+# * we check if we have an esp_disk, if not we use
+# * kname, otherwise we check if they are the same, if not we fail, otherwise we use kname/esp_disk
+if [ -z "$kname" ]; then
+ if [ -z "$esp_disk" ]; then
+ err "No suitable disk found"
+ exit 1
+ fi
+ echo "Warning: No suitable disk found, falling back to ESP disk ${esp_disk}" 1>&2
+ echo "$esp_disk"
+else
+ if [ -z "$esp_disk" ]; then
+ # no esp_disk using kname
+ echo "$kname"
+ exit 0
+ fi
+
+ if [ "$kname" != "$esp_disk" ]; then
+ # check if desvice size are the same
+ err "Error: Found disk ${kname} does not match ESP disk ${esp_disk}." 1>&2
+ kname_size=$(blockdevicesize "$kname")
+ esp_disk_size=$(blockdevicesize "$esp_disk")
+ if [ "$kname_size" != "$esp_disk_size" ]; then
+ err "Error: Found disk ${kname} size ${kname_size} does not match ESP disk ${esp_disk} size ${esp_disk_size}." 1>&2
+ exit 1
+ fi
+ fi
+ # kname == esp_disk or esp_disk has similar size to kname
+ echo "$esp_disk"
+fi
diff --git a/features/_usi/pkg.exclude b/features/_usi/pkg.exclude
new file mode 100644
index 00000000..df284caa
--- /dev/null
+++ b/features/_usi/pkg.exclude
@@ -0,0 +1 @@
+ignition
diff --git a/features/_usi/pkg.include b/features/_usi/pkg.include
index 7ee423c5..8f20b728 100644
--- a/features/_usi/pkg.include
+++ b/features/_usi/pkg.include
@@ -9,6 +9,5 @@ tpm2-tools
yq
gdisk
binutils
-oras
efibootmgr
systemd-ukify
diff --git a/features/_usidev/exec.config b/features/_usidev/exec.config
index 402f6dbf..8eee4e1c 100755
--- a/features/_usidev/exec.config
+++ b/features/_usidev/exec.config
@@ -1,5 +1,19 @@
#!/usr/bin/env bash
-set -eufo pipefail
+set -euo pipefail
mkdir -p /var/usr.overlay /var/usr.overlay.workdir
+
+# install
+mkdir /tmp/custompackages
+package="https://github.com/toanju/package-gardenlinux-update/releases/download/0.9gl4%2Bbp1877/build.tar.xz.0000"
+
+echo "Downloading and extracting package from $package"
+wget -q "$package" -O - | xz -d | tar xf - -C /tmp/custompackages
+
+pushd /tmp/custompackages > /dev/null
+rm -f -- *dbgsym* *arm64* || true
+ls -1
+dpkg -i gardenlinux-update_*_amd64.deb
+popd > /dev/null
+rm -rf /tmp/custompackages
diff --git a/features/_usidev/pkg.exclude b/features/_usidev/pkg.exclude
new file mode 100644
index 00000000..562044e0
--- /dev/null
+++ b/features/_usidev/pkg.exclude
@@ -0,0 +1 @@
+gardenlinux-update
diff --git a/features/khost b/features/khost
deleted file mode 120000
index 0b36d54a..00000000
--- a/features/khost
+++ /dev/null
@@ -1 +0,0 @@
-../gardenlinux/features/khost
\ No newline at end of file
diff --git a/features/khost/README.md b/features/khost/README.md
new file mode 100644
index 00000000..7d71961c
--- /dev/null
+++ b/features/khost/README.md
@@ -0,0 +1,19 @@
+## Feature: khost
+### Description
+
+The khost feature adjusts Garden Linux to support running Kubernetes (vanilla) workloads.
+
+
+### Features
+The `khost` feature adjusts Garden Linux to support running Kubernetes (vanilla) workloads and installs and configures all related packages (regarding the used hardware architecture) and tools. It adjusts the `kublets`, `sysctl` and removes any swap partition.
+
+### Unit testing
+Unit tests will ensure that the needed packages are present as well as the `kublet` is enabled within `systemd`.
+
+### Meta
+|||
+|---|---|
+|type|element|
+|artifact|None|
+|included_features|`chost`|
+|excluded_features|None|
diff --git a/features/khost/exec.late b/features/khost/exec.late
new file mode 100755
index 00000000..f0ea8caf
--- /dev/null
+++ b/features/khost/exec.late
@@ -0,0 +1,11 @@
+#!/usr/bin/env bash
+set -Eeuo pipefail
+
+K8S_VERSION=v1.34.3
+K8S_VERSION_REPO="${K8S_VERSION%.*}"
+
+cp /builder/features/khost/release.key /etc/apt/keyrings/kubernetes-apt-keyring.asc
+echo "deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.asc] https://pkgs.k8s.io/core:/stable:/${K8S_VERSION_REPO}/deb/ /" | tee /etc/apt/sources.list.d/kubernetes.list
+apt update -y
+apt install -y --no-install-recommends "kubelet=${K8S_VERSION#v}*" "kubectl=${K8S_VERSION#v}*" "kubeadm=${K8S_VERSION#v}*" "cri-tools=${K8S_VERSION_REPO#v}*"
+
diff --git a/features/khost/file.exclude b/features/khost/file.exclude
new file mode 100644
index 00000000..82b5c657
--- /dev/null
+++ b/features/khost/file.exclude
@@ -0,0 +1 @@
+/etc/init.d/apparmor
diff --git a/features/khost/file.include/etc/modules-load.d/br-nf.conf b/features/khost/file.include/etc/modules-load.d/br-nf.conf
new file mode 100644
index 00000000..a13fc179
--- /dev/null
+++ b/features/khost/file.include/etc/modules-load.d/br-nf.conf
@@ -0,0 +1 @@
+br_netfilter
diff --git a/features/khost/file.include/etc/sysctl.d/20-br-nf.conf b/features/khost/file.include/etc/sysctl.d/20-br-nf.conf
new file mode 100644
index 00000000..0454e18a
--- /dev/null
+++ b/features/khost/file.include/etc/sysctl.d/20-br-nf.conf
@@ -0,0 +1,2 @@
+net.bridge.bridge-nf-call-iptables=1
+net.bridge.bridge-nf-call-ip6tables=1
diff --git a/features/khost/file.include/etc/sysctl.d/20-inotify.conf b/features/khost/file.include/etc/sysctl.d/20-inotify.conf
new file mode 100644
index 00000000..8f7c9d98
--- /dev/null
+++ b/features/khost/file.include/etc/sysctl.d/20-inotify.conf
@@ -0,0 +1,2 @@
+fs.inotify.max_user_instances = 8192
+fs.inotify.max_user_watches = 65536
diff --git a/features/khost/file.include/etc/sysctl.d/20-ip-forward.conf b/features/khost/file.include/etc/sysctl.d/20-ip-forward.conf
new file mode 100644
index 00000000..5f01c9cd
--- /dev/null
+++ b/features/khost/file.include/etc/sysctl.d/20-ip-forward.conf
@@ -0,0 +1,3 @@
+net.ipv4.ip_forward=1
+net.ipv6.conf.all.forwarding=1
+
diff --git a/features/khost/fstab.mod b/features/khost/fstab.mod
new file mode 100755
index 00000000..de880d56
--- /dev/null
+++ b/features/khost/fstab.mod
@@ -0,0 +1,6 @@
+#!/usr/bin/env bash
+set -Eeuo pipefail
+
+# remove any swap partition
+sed '/^[^[:space:]]\+[[:space:]]\+[^[:space:]]\+[[:space:]]\+swap[[:space:]]\+/d'
+
diff --git a/features/khost/info.yaml b/features/khost/info.yaml
new file mode 100644
index 00000000..1d9d389e
--- /dev/null
+++ b/features/khost/info.yaml
@@ -0,0 +1,5 @@
+description: 'host for kubernetes workloads (vanilla)'
+type: element
+features:
+ include:
+ - chost
diff --git a/features/khost/pkg.include b/features/khost/pkg.include
new file mode 100644
index 00000000..487a9abe
--- /dev/null
+++ b/features/khost/pkg.include
@@ -0,0 +1,6 @@
+apparmor
+conntrack
+ethtool
+ipvsadm
+socat
+gnupg
diff --git a/features/khost/release.key b/features/khost/release.key
new file mode 100644
index 00000000..64f4d8f8
--- /dev/null
+++ b/features/khost/release.key
@@ -0,0 +1,30 @@
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: GnuPG v1.4.5 (GNU/Linux)
+
+mQENBGMHoXcBCADukGOEQyleViOgtkMVa7hKifP6POCTh+98xNW4TfHK/nBJN2sm
+u4XaiUmtB9UuGt9jl8VxQg4hOMRf40coIwHsNwtSrc2R9v5Kgpvcv537QVIigVHH
+WMNvXeoZkkoDIUljvbCEDWaEhS9R5OMYKd4AaJ+f1c8OELhEcV2dAQLLyjtnEaF/
+qmREN+3Y9+5VcRZvQHeyBxCG+hdUGE740ixgnY2gSqZ/J4YeQntQ6pMUEhT6pbaE
+10q2HUierj/im0V+ZUdCh46Lk/Rdfa5ZKlqYOiA2iN1coDPIdyqKavcdfPqSraKF
+Lan2KLcZcgTxP+0+HfzKefvGEnZa11civbe9ABEBAAG0PmlzdjprdWJlcm5ldGVz
+IE9CUyBQcm9qZWN0IDxpc3Y6a3ViZXJuZXRlc0BidWlsZC5vcGVuc3VzZS5vcmc+
+iQE+BBMBCAAoBQJnFF34AhsDBQkIK2yBBgsJCAcDAgYVCAIJCgsEFgIDAQIeAQIX
+gAAKCRAjRlTamilkNtOACACDK9dQ8CH2Ji9C3Q926nVMUiXdyJK1onCBrQSEBqdR
+LJaT6hGx5pzxkQGgUDpS9p7LA0u920HKLwGb7yIAWtyE5TAj2CYprGgpq98sfsGC
++U5T9IrAdya/BaTAkkP6gNhfMjNaK3bOWsvuLRlluKMNch4ify+IwLqc1JLG40bj
+2HnKBGYkC3m0VtQfUuPQMImSLta/NwRHJMPo8jfGyManqMMxp35/ecP2rXMfb/l1
+WjFDY7h+6nqXay20ljMXkN23W8wFTdvC6lq45wwM5IBnKNR/TjNNYAIizZoHFWz1
+c/ecMWWWCB2S7WbY4xI3JSCOD4XIff3ie7pc68/kgPytiQIcBBMBAgAGBQJjB6F3
+AAoJEM8Lkoze1k873TQP/0t2F/jltLRQMG7VCLw7+ps5JCW5FIqu/S2i9gSdNA0E
+42u+LyxjG3YxmVoVRMsxeu4kErxr8bLcA4p71W/nKeqwF9VLuXKirsBC7z2syFiL
+Ndl0ARnC3ENwuMVlSCwJO0MM5NiJuLOqOGYyD1XzSfnCzkXN0JGA/bfPRS5mPfoW
+0OHIRZFhqE7ED6wyWpHIKT8rXkESFwszUwW/D7o1HagX7+duLt8WkrohGbxTJ215
+YanOKSqyKd+6YGzDNUoGuMNPZJ5wTrThOkTzEFZ4HjmQ16w5xmcUISnCZd4nhsbS
+qN/UyV9Vu3lnkautS15E4CcjP1RRzSkT0jka62vPtAzw+PiGryM1F7svuRaEnJD5
+GXzj9RCUaR6vtFVvqqo4fvbA99k4XXj+dFAXW0TRZ/g2QMePW9cdWielcr+vHF4Z
+2EnsAmdvF7r5e2JCOU3N8OUodebU6ws4VgRVG9gptQgfMR0vciBbNDG2Xuk1WDk1
+qtscbfm5FVL36o7dkjA0x+TYCtqZIr4x3mmfAYFUqzxpfyXbSHqUJR2CoWxlyz72
+XnJ7UEo/0UbgzGzscxLPDyJHMM5Dn/Ni9FVTVKlALHnFOYYSTluoYACF1DMt7NJ3
+oyA0MELL0JQzEinixqxpZ1taOmVR/8pQVrqstqwqsp3RABaeZ80JbigUC29zJUVf
+=Eplj
+-----END PGP PUBLIC KEY BLOCK-----
diff --git a/features/khost/test/test_packages_musthave.py b/features/khost/test/test_packages_musthave.py
new file mode 100644
index 00000000..4b2783d2
--- /dev/null
+++ b/features/khost/test/test_packages_musthave.py
@@ -0,0 +1 @@
+from helper.tests.packages_musthave import packages_musthave as test_packages_musthave
diff --git a/features/khost/test/test_systemd_unit.py b/features/khost/test/test_systemd_unit.py
new file mode 100644
index 00000000..0bc474ab
--- /dev/null
+++ b/features/khost/test/test_systemd_unit.py
@@ -0,0 +1,16 @@
+import pytest
+from helper.utils import execute_remote_command
+from helper.utils import validate_systemd_unit
+
+
+@pytest.mark.parametrize(
+ "systemd_unit",
+ [
+ "kubelet"
+ ]
+)
+
+
+def test_systemd_unit(client, systemd_unit, non_provisioner_chroot):
+ execute_remote_command(client, f"systemctl start {systemd_unit}")
+ validate_systemd_unit(client, f"{systemd_unit}")
diff --git a/features/metal3/exec.config b/features/metal3/exec.config
index b15043a1..4fdb8e0f 100755
--- a/features/metal3/exec.config
+++ b/features/metal3/exec.config
@@ -26,7 +26,7 @@ apt-mark hold ${package_name}
K8S_VERSION=v1.30.7
K8S_VERSION_REPO="${K8S_VERSION%.*}"
-gpg --dearmor -o "/etc/apt/keyrings/kubernetes-${K8S_VERSION_REPO}-apt-keyring.gpg" /dev/null
+rm -f -- *dbgsym* *arm64* || true
+ls -1
+dpkg -i cloud-hypervisor-gl*_amd64.deb edk2-cloud-hypervisor-gl*_amd64.deb libvirt-clients_*_amd64.deb libvirt-common_*_amd64.deb libvirt-daemon_*_amd64.deb libvirt-daemon-common_*_amd64.deb libvirt-daemon-config-network_*_all.deb libvirt-daemon-config-nwfilter_*_all.deb libvirt-daemon-driver-ch-gl_*_amd64.deb libvirt-daemon-driver-network_*_amd64.deb libvirt-daemon-driver-nodedev_*_amd64.deb libvirt-daemon-driver-nwfilter_*_amd64.deb libvirt-daemon-driver-qemu_*_amd64.deb libvirt-daemon-driver-secret_*_amd64.deb libvirt-daemon-driver-storage_*_amd64.deb libvirt-daemon-log_*_amd64.deb libvirt-daemon-system_*_amd64.deb libvirt0_*_amd64.deb
+popd > /dev/null
+rm -rf /tmp/custompackages
+
# UID taken from sles 15, looks like it runs as root in debian/gardenlinux
adduser --uid 476 openvswitch \
--system --group --no-create-home --disabled-password --disabled-login
@@ -15,11 +40,11 @@ function create() {
shift
ID=$1
shift
- adduser --uid $ID --home /var/lib/$NAME $NAME \
+ adduser --uid "$ID" --home "/var/lib/$NAME" "$NAME" \
--system --group --disabled-password --disabled-login
echo "$@"
for group in "$@"; do
- adduser $NAME $group
+ adduser "$NAME" "$group"
done
}
diff --git a/features/sci/file.include/etc/modprobe.d/kvm-amd.conf b/features/sci/file.include/etc/modprobe.d/kvm-amd.conf
new file mode 100644
index 00000000..79910fc2
--- /dev/null
+++ b/features/sci/file.include/etc/modprobe.d/kvm-amd.conf
@@ -0,0 +1 @@
+install kvm_amd if grep -q AuthenticAMD /proc/cpuinfo; then modprobe --ignore-install kvm_amd; else echo "WARNING kvm_amd: no AMD cpu found, skipping"; exit 0; fi
diff --git a/features/sci/file.include/etc/modprobe.d/kvm-intel.conf b/features/sci/file.include/etc/modprobe.d/kvm-intel.conf
new file mode 100644
index 00000000..67abf1e0
--- /dev/null
+++ b/features/sci/file.include/etc/modprobe.d/kvm-intel.conf
@@ -0,0 +1 @@
+install kvm_intel if grep -q GenuineIntel /proc/cpuinfo; then modprobe --ignore-install kvm_intel; else echo "WARNING kvm_intel: no Intel cpu found, skipping"; exit 0; fi
diff --git a/features/sci/file.include/etc/modprobe.d/nfsclient.conf b/features/sci/file.include/etc/modprobe.d/nfsclient.conf
new file mode 100644
index 00000000..d1587635
--- /dev/null
+++ b/features/sci/file.include/etc/modprobe.d/nfsclient.conf
@@ -0,0 +1,3 @@
+# According to Netapp KVM Best Practices mount options this value should be nconnect*64 (nconnect=8)
+options nfs max_session_slots=512
+
diff --git a/features/sci/file.include/etc/modules-load.d/kvm.conf b/features/sci/file.include/etc/modules-load.d/kvm.conf
new file mode 100644
index 00000000..01884b87
--- /dev/null
+++ b/features/sci/file.include/etc/modules-load.d/kvm.conf
@@ -0,0 +1,3 @@
+kvm
+kvm_amd
+kvm_intel
diff --git a/features/sci/file.include/etc/systemd/system-preset/00-sci-libvirt.preset b/features/sci/file.include/etc/systemd/system-preset/00-sci-libvirt.preset
new file mode 100644
index 00000000..a45ccf70
--- /dev/null
+++ b/features/sci/file.include/etc/systemd/system-preset/00-sci-libvirt.preset
@@ -0,0 +1,5 @@
+# default presets for sci image
+disable virtchd-admin.socket
+disable virtchd-ro.socket
+disable virtchd.service
+disable virtchd.socket
diff --git a/features/sci/file.include/etc/systemd/system-preset/10-ipmiev.preset b/features/sci/file.include/etc/systemd/system-preset/10-ipmiev.preset
new file mode 100644
index 00000000..17ed7623
--- /dev/null
+++ b/features/sci/file.include/etc/systemd/system-preset/10-ipmiev.preset
@@ -0,0 +1,2 @@
+# default presets for sci image
+disable ipmievd.service
diff --git a/features/sci/pkg.include b/features/sci/pkg.include
index 71c8ba35..e05599e8 100644
--- a/features/sci/pkg.include
+++ b/features/sci/pkg.include
@@ -1,6 +1,5 @@
-cloud-hypervisor-gl
-edk2-cloud-hypervisor-gl
-libvirt-daemon-driver-ch-gl
multipath-tools
open-iscsi
openvswitch-switch
+wget
+xz-utils
diff --git a/features/sslfips b/features/sslfips
new file mode 120000
index 00000000..94a753fc
--- /dev/null
+++ b/features/sslfips
@@ -0,0 +1 @@
+../gardenlinux/features/sslfips
\ No newline at end of file
diff --git a/flavors.yaml b/flavors.yaml
index 5dd93a8a..8ed403a1 100644
--- a/flavors.yaml
+++ b/flavors.yaml
@@ -1,7 +1,15 @@
targets:
- - name: metal
+ - name: metal
category: baremetal
flavors:
+ - features:
+ - chost
+ - _pxe
+ arch: amd64
+ build: true
+ test: true
+ test-platform: false
+ publish: false
- features:
- sci
- _pxe
@@ -41,6 +49,14 @@ targets:
test: true
test-platform: false
publish: false
+ - features:
+ - sci
+ - _iso
+ arch: amd64
+ build: true
+ test: true
+ test-platform: false
+ publish: false
# this is needed as bare_flavors step in build.yml is currently hard wired
- name: bare
category: container
diff --git a/gardenlinux b/gardenlinux
index 40e7dfa8..409e9b64 160000
--- a/gardenlinux
+++ b/gardenlinux
@@ -1 +1 @@
-Subproject commit 40e7dfa820cb8bd5e0317779f818d31464c18c63
+Subproject commit 409e9b640087ade203321a8d63bd1651f4677205
diff --git a/renovate.json b/renovate.json
new file mode 100644
index 00000000..1ba6e4a3
--- /dev/null
+++ b/renovate.json
@@ -0,0 +1,44 @@
+{
+ "$schema": "https://docs.renovatebot.com/renovate-schema.json",
+ "customManagers": [
+ {
+ "customType": "regex",
+ "description": "Update libvirt package version for rel-1877-dev",
+ "managerFilePatterns": ["/features/sci/exec\\.config$/"],
+ "matchStrings": [
+ "LIBVIRT_VERSION=\"(?[^%]+)%2Bbp1877\""
+ ],
+ "depNameTemplate": "gardenlinux/package-libvirt",
+ "datasourceTemplate": "github-releases",
+ "extractVersionTemplate": "^(?.+)\\+bp1877$",
+ "versioningTemplate": "loose",
+ "autoReplaceStringTemplate": "LIBVIRT_VERSION=\"{{{newValue}}}%2Bbp1877\""
+ },
+ {
+ "customType": "regex",
+ "description": "Update cloud-hypervisor-gl package version for rel-1877-dev",
+ "managerFilePatterns": ["/features/sci/exec\\.config$/"],
+ "matchStrings": [
+ "CLOUD_HYPERVISOR_VERSION=\"(?[^%]+)%2Bbp1877\""
+ ],
+ "depNameTemplate": "gardenlinux/package-cloud-hypervisor-gl",
+ "datasourceTemplate": "github-releases",
+ "extractVersionTemplate": "^(?.+)\\+bp1877$",
+ "versioningTemplate": "loose",
+ "autoReplaceStringTemplate": "CLOUD_HYPERVISOR_VERSION=\"{{{newValue}}}%2Bbp1877\""
+ },
+ {
+ "customType": "regex",
+ "description": "Update edk2-cloud-hypervisor-gl package version for rel-1877-dev",
+ "managerFilePatterns": ["/features/sci/exec\\.config$/"],
+ "matchStrings": [
+ "EDK2_VERSION=\"(?[^%]+)%2Bbp1877\""
+ ],
+ "depNameTemplate": "gardenlinux/package-edk2-cloud-hypervisor-gl",
+ "datasourceTemplate": "github-releases",
+ "extractVersionTemplate": "^(?.+)\\+bp1877$",
+ "versioningTemplate": "loose",
+ "autoReplaceStringTemplate": "EDK2_VERSION=\"{{{newValue}}}%2Bbp1877\""
+ }
+ ]
+}