diff --git a/.github/actions/test/integration/build/action.yml b/.github/actions/test/integration/build/action.yml index eca53a3..447de18 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 @@ -135,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 9eb08a1..ac08d4a 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 @@ -49,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 diff --git a/.github/actions/test/integration/collect-logs/action.yml b/.github/actions/test/integration/collect-logs/action.yml index 0974c81..51df119 100644 --- a/.github/actions/test/integration/collect-logs/action.yml +++ b/.github/actions/test/integration/collect-logs/action.yml @@ -34,6 +34,44 @@ runs: scp $SSH_OPTS $USER@$HV2_IP:/var/log/QEMU.log "serial-VM-QEMU-HV2.log" || true scp $SSH_OPTS $USER@$HV2_IP:/var/log/CHV.log "serial-VM-CHV-HV2.log" || true + - name: Obtain network diagnostics from hypervisors + shell: bash + run: | + KEY=/opt/ssh_host_ed25519_key + SSH_OPTS="-i $KEY -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null" + USER="root" + + for HV_NAME in HV1 HV2; do + IP="192.168.122.$([[ $HV_NAME == HV1 ]] && echo 2 || echo 3)" + + ssh $SSH_OPTS $USER@$IP " + echo '=== ip addr ===' + ip addr + echo '=== ip route ===' + ip route + echo '=== bridge link ===' + bridge link 2>/dev/null || true + echo '=== arp -n ===' + arp -n 2>/dev/null || ip neigh || true + echo '=== iptables -L -n ===' + iptables -L -n 2>/dev/null || true + echo '=== iptables -t nat -L -n ===' + iptables -t nat -L -n 2>/dev/null || true + echo '=== virsh net-list ===' + virsh net-list --all 2>/dev/null || true + echo '=== virsh net-dumpxml default ===' + virsh net-dumpxml default 2>/dev/null || true + echo '=== dnsmasq leases ===' + cat /var/lib/libvirt/dnsmasq/*.leases 2>/dev/null || true + echo '=== systemctl status systemd-networkd ===' + systemctl status systemd-networkd --no-pager 2>/dev/null || true + echo '=== networkctl status ===' + networkctl status --no-pager 2>/dev/null || true + echo '=== ssh -V ===' + ssh -V 2>&1 || true + " > "network-diag-${HV_NAME}.log" 2>&1 || true + done + - name: Set permissions shell: bash run: | diff --git a/.github/actions/test/integration/dependencies/action.yml b/.github/actions/test/integration/dependencies/action.yml index e1923df..65fb700 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/hv.xml b/.github/actions/test/integration/setup/hv.xml index 63341fb..c8f6f0d 100644 --- a/.github/actions/test/integration/setup/hv.xml +++ b/.github/actions/test/integration/setup/hv.xml @@ -15,7 +15,7 @@ - + diff --git a/.github/actions/test/integration/test/cloudhypervisor/action.yml b/.github/actions/test/integration/test/cloudhypervisor/action.yml index f3eeabc..078de40 100644 --- a/.github/actions/test/integration/test/cloudhypervisor/action.yml +++ b/.github/actions/test/integration/test/cloudhypervisor/action.yml @@ -52,7 +52,14 @@ runs: IP=\$(virsh -c ch:///session domifaddr VM-CHV | awk '/ipv4/ {print \$4}' | cut -d'/' -f1) if [ -z "\$IP" ]; then echo "No IP address found for VM. Retrying..." - elif ssh \$SSH_OPTS "\$USER@\$IP" 'exit' ; then + elif (( i >= MAX_ITER - 2 )); then + # Show SSH errors on last 3 attempts for debugging + if ssh \$SSH_OPTS "\$USER@\$IP" 'exit'; then + echo "VM is up at IP: \$IP" + ssh \$SSH_OPTS "\$USER@\$IP" 'echo "Hello, World!" > /opt/hello.txt' + break + fi + elif ssh \$SSH_OPTS "\$USER@\$IP" 'exit' 2>/dev/null; then echo "VM is up at IP: \$IP" # create a dummy file for verification later ssh \$SSH_OPTS "\$USER@\$IP" 'echo "Hello, World!" > /opt/hello.txt' @@ -60,6 +67,18 @@ runs: fi if (( i == MAX_ITER )); then echo "Timeout waiting for VM to respond to SSH." + echo "=== DIAGNOSTICS ===" + echo "--- virsh -c ch:///session domifaddr VM-CHV ---" + virsh -c ch:///session domifaddr VM-CHV || true + echo "--- ip addr show virbr0 ---" + ip addr show virbr0 || true + echo "--- ip route ---" + ip route || true + echo "--- arp -n ---" + arp -n 2>/dev/null || ip neigh || true + echo "--- ssh -v attempt ---" + ssh -v \$SSH_OPTS "\$USER@\$IP" 'exit' 2>&1 || true + echo "=== END DIAGNOSTICS ===" exit 1 fi echo "Waiting for VM to respond to SSH... (\$i/\$MAX_ITER)" @@ -111,7 +130,7 @@ runs: MAX_ITER=15 for ((i=1; i<=MAX_ITER; i++)); do - if ssh \$SSH_OPTS "\$USER@\$IP" 'exit' ; then + if ssh \$SSH_OPTS "\$USER@\$IP" 'exit' 2>/dev/null; then echo "VM is up at IP: \$IP" # verify the migration by checking the dummy file if ssh \$SSH_OPTS "\$USER@\$IP" 'test -f /opt/hello.txt'; then @@ -124,6 +143,14 @@ runs: fi if (( i == MAX_ITER )); then echo "Timeout waiting for VM to respond to SSH." + echo "=== DIAGNOSTICS ===" + echo "--- ip addr show virbr0 ---" + ip addr show virbr0 || true + echo "--- ip route ---" + ip route || true + echo "--- ssh -v attempt ---" + ssh -v \$SSH_OPTS "\$USER@\$IP" 'exit' 2>&1 || true + echo "=== END DIAGNOSTICS ===" exit 1 fi echo "Waiting for VM to respond to SSH... (\$i/\$MAX_ITER)" diff --git a/.github/actions/test/integration/test/qemu/action.yml b/.github/actions/test/integration/test/qemu/action.yml index 0dab034..e6887e5 100644 --- a/.github/actions/test/integration/test/qemu/action.yml +++ b/.github/actions/test/integration/test/qemu/action.yml @@ -50,6 +50,13 @@ runs: IP=\$(virsh domifaddr VM-QEMU | awk '/ipv4/ {print \$4}' | cut -d'/' -f1) if [ -z "\$IP" ]; then echo "No IP address found for VM. Retrying..." + elif (( i >= MAX_ITER - 2 )); then + # Show SSH errors on last 3 attempts for debugging + if ssh \$SSH_OPTS "\$USER@\$IP" 'exit'; then + echo "VM is up at IP: \$IP" + ssh \$SSH_OPTS "\$USER@\$IP" 'echo "Hello, World!" > /opt/hello.txt' + break + fi elif ssh \$SSH_OPTS "\$USER@\$IP" 'exit' 2>/dev/null; then echo "VM is up at IP: \$IP" # create a dummy file for verification later @@ -58,6 +65,18 @@ runs: fi if (( i == MAX_ITER )); then echo "Timeout waiting for VM to respond to SSH." + echo "=== DIAGNOSTICS ===" + echo "--- virsh domifaddr VM-QEMU ---" + virsh domifaddr VM-QEMU || true + echo "--- ip addr show virbr0 ---" + ip addr show virbr0 || true + echo "--- ip route ---" + ip route || true + echo "--- arp -n ---" + arp -n 2>/dev/null || ip neigh || true + echo "--- ssh -v attempt ---" + ssh -v \$SSH_OPTS "\$USER@\$IP" 'exit' 2>&1 || true + echo "=== END DIAGNOSTICS ===" exit 1 fi echo "Waiting for VM to respond to SSH... (\$i/\$MAX_ITER)" @@ -122,6 +141,14 @@ runs: fi if (( i == MAX_ITER )); then echo "Timeout waiting for VM to respond to SSH." + echo "=== DIAGNOSTICS ===" + echo "--- ip addr show virbr0 ---" + ip addr show virbr0 || true + echo "--- ip route ---" + ip route || true + echo "--- ssh -v attempt ---" + ssh -v \$SSH_OPTS "\$USER@\$IP" 'exit' 2>&1 || true + echo "=== END DIAGNOSTICS ===" exit 1 fi echo "Waiting for VM to respond to SSH... (\$i/\$MAX_ITER)" diff --git a/.github/actions/test/integration/test/qemu/vm.xml b/.github/actions/test/integration/test/qemu/vm.xml index 3626dc1..1fe453b 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/workflows/dev.yml b/.github/workflows/dev.yml index af0d441..351fed3 100644 --- a/.github/workflows/dev.yml +++ b/.github/workflows/dev.yml @@ -3,6 +3,7 @@ on: push: branches: - main + - rel-2150-dev paths-ignore: - "**/README.md" - "docs/**" @@ -26,23 +27,19 @@ 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@36078a576d0767433423289f2fa217b96cd951c9 + uses: gardenlinux/gardenlinux/.github/workflows/build.yml@a6e35cf0c955dde584c67163a3a8dff6d60e9d56 with: version: ${{ needs.set_version.outputs.VERSION }} # to set target to "release" or "nightly" we need proper KMS secrets @@ -64,7 +61,7 @@ jobs: image_tag: ${{ steps.meta.outputs.image_tag }} steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 - name: Compute image metadata id: meta run: | @@ -112,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 @@ -141,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 3157546..e358b1f 100644 --- a/.github/workflows/nightly.yaml +++ b/.github/workflows/nightly.yaml @@ -14,12 +14,12 @@ 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@36078a576d0767433423289f2fa217b96cd951c9 + uses: gardenlinux/gardenlinux/.github/workflows/build.yml@a6e35cf0c955dde584c67163a3a8dff6d60e9d56 with: version: ${{ inputs.version || 'now' }} # to set target to "release" or "nightly" we need proper KMS secrets @@ -39,7 +39,7 @@ jobs: image_tag: ${{ steps.meta.outputs.image_tag }} steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 - name: Compute image tag id: meta run: | @@ -49,7 +49,7 @@ jobs: 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@36078a576d0767433423289f2fa217b96cd951c9 + # uses: gardenlinux/gardenlinux/.github/workflows/upload_oci.yml@a6e35cf0c955dde584c67163a3a8dff6d60e9d56 uses: ./.github/workflows/upload_oci.yml with: version: ${{ needs.build.outputs.version }} diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 729fffd..87ecf16 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -18,9 +18,9 @@ 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@v1 + uses: oras-project/setup-oras@1d808f7d7f6995cc68b7bf507bfe5c5446e1dc9d # v2 with: version: 1.2.2 - name: Validate image tag @@ -31,8 +31,8 @@ jobs: fi echo "Verifying image ${{ inputs.image_tag }} exists in GHCR..." - if ! digest=$(oras resolve ghcr.io/gardenlinux/gardenlinux-ccloud:${{ inputs.image_tag }} 2>&1); then - echo "Error: Image tag '${{ inputs.image_tag }}' not found in ghcr.io/gardenlinux/gardenlinux-ccloud" + 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 diff --git a/.github/workflows/upload_oci.yml b/.github/workflows/upload_oci.yml index 4574361..c46c226 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@36078a576d0767433423289f2fa217b96cd951c9 + uses: gardenlinux/gardenlinux/.github/workflows/build_flavors_matrix.yml@a6e35cf0c955dde584c67163a3a8dff6d60e9d56 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@19c1b24c01faab81a7fe24713748dd172d00904a + uses: gardenlinux/python-gardenlinux-lib/.github/actions/setup@efdffb9a6b279cd7aada23b02baf4ec2534dc6d2 - 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 diff --git a/Containerfile b/Containerfile new file mode 100644 index 0000000..9893378 --- /dev/null +++ b/Containerfile @@ -0,0 +1,3 @@ +FROM ghcr.io/gardenlinux/builder:98ee0d480844b2d041524841bfdbbb4007d32248@sha256:d7063f72c0db3e7cdd618136efb292379794a0c4d4b5ddfc3759795c17d963ab + +RUN sed 's/version="$2"/version=\$(echo \$2 | cut -d. -f 1-2).0/' -i /builder/bootstrap diff --git a/VERSION b/VERSION deleted file mode 120000 index e96da46..0000000 --- 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 0000000..52dfea6 --- /dev/null +++ b/VERSION @@ -0,0 +1 @@ +2150.9.0 diff --git a/bin/garden-version b/bin/garden-version deleted file mode 120000 index d88969e..0000000 --- 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 0000000..c2212f8 --- /dev/null +++ b/bin/garden-version @@ -0,0 +1,154 @@ +#!/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 + # shellcheck disable=2046 + if [ $(echo "$1" | cut -d. -f1) -lt 2015 ]; 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 9a5480a..0000000 --- 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 0000000..ded1dcd --- /dev/null +++ b/build @@ -0,0 +1,182 @@ +#!/usr/bin/env bash + +set -euo pipefail +shopt -s nullglob + +exec 3>&1 +exec 1>&2 + +#container_image=ghcr.io/gardenlinux/builder:98ee0d480844b2d041524841bfdbbb4007d32248 +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 +allow_frankenstein=0 +apparmor_profile= + +while [ $# -gt 0 ]; do + case "$1" in + --allow-frankenstein) # https://xkcd.com/1589/ + allow_frankenstein=1 + shift + ;; + --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 + ;; + --apparmor-profile) + apparmor_profile="$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" + LOG_WITH_TIMESTAMP="${LOG_WITH_TIMESTAMP:-true}" +) + +if [ "$allow_frankenstein" = 1 ]; then + make_opts+=("ALLOW_FRANKENSTEIN=1") +fi + +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 + +# Check if builder apparmor profile has to be created or selected +if [ "$container_engine" = "docker" ] \ + && [ ! "$apparmor_profile" ] \ + && out=$(sysctl kernel.apparmor_restrict_unprivileged_userns 2> /dev/null) \ + && [[ $out = "kernel.apparmor_restrict_unprivileged_userns = 1" ]]; then + if [ ! -f /etc/apparmor.d/builder ]; then + echo "You are using Docker on a system restricting unprivileged user namespaces with apparmor, which prevents a successful build. For more information please refer to the #Usage section in the README." + read -r -p "Do you want to permanently create a new apparmor profile at /etc/apparmor.d/builder to solve the issue? [Y/n] " response + response=${response,,} + if [[ "$response" =~ ^(yes|y)$ ]]; then + if [ ! -f /etc/apparmor.d/builder ]; then + profile="abi , include profile builder flags=(unconfined) {userns, }" + echo "$profile" | sudo tee /etc/apparmor.d/builder > /dev/null + sudo apparmor_parser -r -W /etc/apparmor.d/builder + fi + echo "Created profile builder at /etc/apparmor.d/builder" + else + echo Abort. + exit 1 + fi + fi + apparmor_profile=builder +fi + +# Apply apparmor profile if seleceted +if [ "$apparmor_profile" ]; then + replaced=false + for i in "${!container_run_opts[@]}"; do + if [ "${container_run_opts[$i]}" = "apparmor=unconfined" ]; then + container_run_opts["$i"]="apparmor=$apparmor_profile" + replaced=true + fi + done + + if ! $replaced; then + container_run_opts+=(--security-opt "apparmor=$apparmor_profile") + fi +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/_archgrouped b/features/_archgrouped new file mode 120000 index 0000000..fdd2adc --- /dev/null +++ b/features/_archgrouped @@ -0,0 +1 @@ +../gardenlinux/features/_archgrouped \ No newline at end of file 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 818d0f3..bc30d2c 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/_scicommon/exec.config b/features/_scicommon/exec.config index 5efda44..d18e272 100755 --- a/features/_scicommon/exec.config +++ b/features/_scicommon/exec.config @@ -12,7 +12,7 @@ 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. diff --git a/features/_scicommon/pkg.include b/features/_scicommon/pkg.include index a8ef404..af58852 100644 --- a/features/_scicommon/pkg.include +++ b/features/_scicommon/pkg.include @@ -1 +1,2 @@ gnupg +openssh-client diff --git a/features/_scicommon/pkgs-k8s-io_v1.33_release.key b/features/_scicommon/pkgs-k8s-io_v1.35_release.key similarity index 100% rename from features/_scicommon/pkgs-k8s-io_v1.33_release.key rename to features/_scicommon/pkgs-k8s-io_v1.35_release.key diff --git a/features/_usi/initrd.include/usr/bin/persist b/features/_usi/initrd.include/usr/bin/persist index 7a6ad93..26fcaca 100755 --- a/features/_usi/initrd.include/usr/bin/persist +++ b/features/_usi/initrd.include/usr/bin/persist @@ -75,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 diff --git a/features/sci/exec.config b/features/sci/exec.config index 3817f6d..5115bba 100755 --- a/features/sci/exec.config +++ b/features/sci/exec.config @@ -1,9 +1,34 @@ #!/usr/bin/env bash + set -Eeuo pipefail +# Apply systemd presets +systemctl preset-all + # Undo the gardener feature disablement systemctl enable ssh +# install custom packages +# TODO : these all should go in the repo + +# all versions URL encoded +EDK2_VERSION="20260221-0gl1+bp2150" +LIBVIRT_VERSION="12.2.0+260825-1gl0+bp2150" +CLOUD_HYPERVISOR_VERSION="52.1+260825-1gl0+bp2150" + +mkdir /tmp/custompackages +for p in https://github.com/gardenlinux/package-edk2-cloud-hypervisor-gl/releases/download/$EDK2_VERSION/build.tar.xz.0000 https://github.com/gardenlinux/package-libvirt/releases/download/$LIBVIRT_VERSION/build.tar.xz.0000 https://github.com/gardenlinux/package-cloud-hypervisor-gl/releases/download/$CLOUD_HYPERVISOR_VERSION/build.tar.xz.0000; do + echo "Downloading and extracting package from $p" + wget -q "$p" -O - | xz -d | tar xf - -C /tmp/custompackages +done + +pushd /tmp/custompackages > /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/pkg.exclude b/features/sci/pkg.exclude index 1794447..5c0fd1a 100644 --- a/features/sci/pkg.exclude +++ b/features/sci/pkg.exclude @@ -1,2 +1,4 @@ frr - +libvirt-daemon-system +libvirt-clients +libvirt0 diff --git a/features/sci/pkg.include b/features/sci/pkg.include index 71c8ba3..c7711e0 100644 --- a/features/sci/pkg.include +++ b/features/sci/pkg.include @@ -1,6 +1,10 @@ -cloud-hypervisor-gl -edk2-cloud-hypervisor-gl -libvirt-daemon-driver-ch-gl +gettext-base +libpciaccess0 +libxml2-utils +mdevctl multipath-tools open-iscsi openvswitch-switch +systemd-container +wget +xz-utils diff --git a/flavors.yaml b/flavors.yaml index 6edc213..10617ee 100644 --- a/flavors.yaml +++ b/flavors.yaml @@ -2,6 +2,14 @@ targets: - name: baremetal category: baremetal flavors: + - features: + - chost + - _pxe + arch: amd64 + build: true + test: true + test-platform: false + publish: false - features: - sci - _pxe diff --git a/gardenlinux b/gardenlinux index 36078a5..a6e35cf 160000 --- a/gardenlinux +++ b/gardenlinux @@ -1 +1 @@ -Subproject commit 36078a576d0767433423289f2fa217b96cd951c9 +Subproject commit a6e35cf0c955dde584c67163a3a8dff6d60e9d56 diff --git a/renovate.json b/renovate.json new file mode 100644 index 0000000..43d8e2a --- /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-2150-dev", + "managerFilePatterns": ["/features/sci/exec\\.config$/"], + "matchStrings": [ + "LIBVIRT_VERSION=\"(?.+)\\+bp2150\"" + ], + "depNameTemplate": "gardenlinux/package-libvirt", + "datasourceTemplate": "github-releases", + "extractVersionTemplate": "^(?.+)\\+bp2150$", + "versioningTemplate": "loose", + "autoReplaceStringTemplate": "LIBVIRT_VERSION=\"{{{newValue}}}+bp2150\"" + }, + { + "customType": "regex", + "description": "Update cloud-hypervisor-gl package version for rel-2150-dev", + "managerFilePatterns": ["/features/sci/exec\\.config$/"], + "matchStrings": [ + "CLOUD_HYPERVISOR_VERSION=\"(?.+)\\+bp2150\"" + ], + "depNameTemplate": "gardenlinux/package-cloud-hypervisor-gl", + "datasourceTemplate": "github-releases", + "extractVersionTemplate": "^(?.+)\\+bp2150$", + "versioningTemplate": "loose", + "autoReplaceStringTemplate": "CLOUD_HYPERVISOR_VERSION=\"{{{newValue}}}+bp2150\"" + }, + { + "customType": "regex", + "description": "Update edk2-cloud-hypervisor-gl package version for rel-2150-dev", + "managerFilePatterns": ["/features/sci/exec\\.config$/"], + "matchStrings": [ + "EDK2_VERSION=\"(?.+)\\+bp2150\"" + ], + "depNameTemplate": "gardenlinux/package-edk2-cloud-hypervisor-gl", + "datasourceTemplate": "github-releases", + "extractVersionTemplate": "^(?.+)\\+bp2150$", + "versioningTemplate": "loose", + "autoReplaceStringTemplate": "EDK2_VERSION=\"{{{newValue}}}+bp2150\"" + } + ] +}