diff --git a/Makefile b/Makefile index da223a7b..1083999d 100644 --- a/Makefile +++ b/Makefile @@ -57,6 +57,9 @@ ifeq ($(DOWNLOAD_FROM_GIT),1) URL := https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/snapshot/linux-$(VERSION).tar.gz endif +verrel: + @echo $(NAME)-$(VERSION)-$(RELEASE) + get-sources: $(SRC_FILE) $(SIGN_FILE) $(WG_SRC_FILE) $(WG_SIG_FILE) $(SPI_SRC_FILE) $(SRC_FILE): @@ -103,8 +106,9 @@ ifneq ($(SPI_SRC_FILE), None) -rm $(SPI_SRC_FILE) endif -verrel: - @echo $(NAME)-$(VERSION)-$(RELEASE) +.PHONY: update-sources +update-sources: + @$(WORKDIR)/update-sources $(BRANCH) help: @echo "Usage: make " diff --git a/get-fedora-latest-config b/get-fedora-latest-config index edefaabc..09da0598 100755 --- a/get-fedora-latest-config +++ b/get-fedora-latest-config @@ -7,14 +7,6 @@ if [ "${VERBOSE:-0}" -ge 2 ] || [ "${DEBUG:-0}" -eq 1 ]; then set -x fi -localdir="$(dirname "$(readlink -f "$0")")" -releasever="$1" -# Set to 1 to include rc srpm -rc="$2" - -kernelver="$(cat "$localdir/version")" -kernelsrc="linux-$kernelver" - exit_clean() { local exit_code=$? rm -rf "$tmpdir" @@ -25,26 +17,86 @@ errecho() { >&2 echo "$@" } -# example of releasever: '29' or 'rawhide' -if [ "x$releasever" != "x" ]; then - if [[ ! "$releasever" =~ ^[1-9][0-9]$ ]] && [ "$releasever" != "rawhide" ]; then - errecho "Invalid release format" - exit 1 - fi -elif [ "x$releasever" == "x" ]; then - listver="$(curl -s -L https://dl.fedoraproject.org/pub/fedora/linux/releases 2> /dev/null)" - releasever="$(echo "$listver" | sed -e 's/<[^>]*>//g' | awk '{print $1}' | grep -o "[1-9][0-9]" | tail -1)" - if ! [[ "$releasever" =~ ^[1-9][0-9]$ ]]; then - errecho "An error occurred while trying to determine latest Fedora version" - exit 1 +usage() { +errecho "Usage: $0 [OPTIONS]... [] + +This script is used for fetching latest Fedora kernel config for the current +kernel version used by Qubes. + +Options: + --releasever Fedora release version to use. Default is latest. + --include-testing Include testing updates repository + --include-rc Include release candidate kernels + +Remark: + Ensure to have downloaded kernel sources in local directory (make get-sources). +" + exit 1 +} + +get_releasever() { + releasever="$1" + # example of releasever: '29' or 'rawhide' + if [ "x$releasever" != "x" ]; then + if [[ ! "$releasever" =~ ^[1-9][0-9]$ ]] && [ "$releasever" != "rawhide" ]; then + errecho "Invalid release format" + exit 1 + fi + elif [ "x$releasever" == "x" ]; then + listver="$(curl -s -L https://dl.fedoraproject.org/pub/fedora/linux/releases 2> /dev/null)" + releasever="$(echo "$listver" | sed -e 's/<[^>]*>//g' | awk '{print $1}' | grep -o "[1-9][0-9]" | tail -1)" + if ! [[ "$releasever" =~ ^[1-9][0-9]$ ]]; then + errecho "An error occurred while trying to determine latest Fedora version" + exit 1 + fi fi + echo "$releasever" +} + +localdir="$(dirname "$(readlink -f "$0")")" +kernelver="$(cat "$localdir/version")" +kernelsrc="linux-$kernelver" + +if ! OPTS=$(getopt -o hv:t:r: --long help,releasever:,include-testing,include-rc -n "$0" -- "$@"); then + errecho "An error occurred while parsing options." + exit 1 +fi + +eval set -- "$OPTS" + +while [[ $# -gt 0 ]]; do + case "$1" in + -a | --releasever ) releasever="$2"; shift ;; + -m | --include-testing ) ktesting="1"; shift ;; + -i | --include-rc ) krc="1"; shift ;; + -h | --help) usage ;; + esac + shift +done + +if [ ! -e "$localdir/$kernelsrc.tar.xz" ]; then + errecho "Cannot find $kernelsrc.tar.xz in local directory." + exit 1 fi +releasever=$(get_releasever "$releasever") + # get the latest kernel rpm -latestver=$(dnf -q repoquery kernel-core --disablerepo=* --enablerepo=fedora --enablerepo=updates --releasever="$releasever") -if [ "$rc" != "1" ]; then +repo_opts="--disablerepo=* --enablerepo=fedora --enablerepo=updates --releasever=$releasever" + +# include testing +if [ "$ktesting" == "1" ]; then +repo_opts="$repo_opts --enablerepo=updates-testing" +fi + +# shellcheck disable=SC2086 +latestver=$(dnf -q repoquery kernel-core $repo_opts) + +# include rc +if [ "$krc" != "1" ]; then latestver=$(echo "$latestver" | grep -v "rc[0-9]*") fi + latestver=$(echo "$latestver" | sort -V | tail -1 | cut -d ':' -f2) latestrpm="kernel-core-$latestver.rpm" @@ -58,7 +110,8 @@ if [ "x$latestrpm" != "x" ] && [ "x$releasever" != "x" ]; then trap 'exit_clean' 0 1 2 3 6 15 tmpdir="$(mktemp -d -p "$localdir")" # download latest kernel rpm - dnf -q download kernel-core --disablerepo=* --enablerepo=fedora --enablerepo=updates --releasever="$releasever" + # shellcheck disable=SC2086 + dnf -q download kernel-core $repo_opts mv "$latestrpm" "$tmpdir/$latestrpm.untrusted" # check signature diff --git a/kernel-updater.py b/kernel-updater.py new file mode 100755 index 00000000..ea0d0c56 --- /dev/null +++ b/kernel-updater.py @@ -0,0 +1,73 @@ +#!/usr/bin/python3 + +import sys +import argparse +import requests +import json + +from packaging import version +from packaging.version import parse as parse_version + + +class KernelUpdaterClient: + def __init__(self, version, branch): + self.version = version + self.branch = branch + + def get_version_qubes(self): + return self.version + + def get_version_upstream(self): + url_releases = 'https://www.kernel.org/releases.json' + r = requests.get(url_releases) + latest_upstream = None + if 200 <= r.status_code < 300: + content = json.loads(r.content.decode('utf-8')) + releases = [rel['version'] for rel in content['releases'] if + rel['moniker'] in ('stable', 'longterm')] + + releases.sort(key=parse_version, reverse=True) + + if 'stable-' in self.branch: + branch_version = self.branch.split('-')[1] + releases = [rel for rel in releases if + rel.startswith(branch_version)] + + latest_upstream = releases[0] + else: + print('An error occurred while downloading "%s"' % url_releases) + + return latest_upstream + + def is_update_needed(self): + version_qubes = self.get_version_qubes() + version_upstream = self.get_version_upstream() + if version_qubes and version_upstream and (version.parse(version_qubes) < version.parse(version_upstream)): + return version_upstream + +def parse_args(argv): + parser = argparse.ArgumentParser() + + parser.add_argument('--check-update', required=False, action='store_true') + parser.add_argument('--version', required=True) + parser.add_argument('--branch', required=True) + + args = parser.parse_args(argv[1:]) + + return args + + +def main(argv): + args = parse_args(argv) + client = KernelUpdaterClient(version=args.version, branch=args.branch) + + if args.check_update: + is_update_needed = client.is_update_needed() + if is_update_needed is not None: + print(is_update_needed) + + return 0 + + +if __name__ == '__main__': + sys.exit(main(sys.argv)) diff --git a/update-sources b/update-sources new file mode 100755 index 00000000..3c469606 --- /dev/null +++ b/update-sources @@ -0,0 +1,66 @@ +#!/bin/bash +# vim: set ts=4 sw=4 sts=4 et : + +set -e +set -o pipefail + +[ "$DEBUG" = "1" ] && set -x + +distance_version() { + read -ra VER1 <<<"$(echo "$1" | tr '.' ' ')" + read -ra VER2 <<<"$(echo "$2" | tr '.' ' ')" + + [[ ${VER1[0]} -eq ${VER2[0]} ]] && [[ $((VER1[1] - VER2[1])) -le 1 ]] && [[ $((VER1[1] - VER2[1])) -ge 0 ]] +} + +LOCALDIR="$(readlink -f "$(dirname "$0")")" +BUILDERDIR="$LOCALDIR/../../" +VERSION="$(cat version)" +BRANCH="$1" + +if [ -z "$BRANCH" ]; then + # Check if qubes-builder Makefile is here + # else rely on current checkout branch + if [ -e "$BUILDERDIR/Makefile" ]; then + BRANCH="$(make -C ../../ -s get-var GET_VAR=BRANCH_linux_kernel 2>/dev/null)" + else + BRANCH="$(git rev-parse --abbrev-ref HEAD)" + fi +fi + +# Filter allowed branches +if [[ ! "$BRANCH" =~ ^stable-[0-9]+\.[0-9]+$ ]] && [ "$BRANCH" != "master" ]; then + echo "Cannot determine kernel branch to use." + exit 1 +fi + +LATEST_KERNEL_VERSION="$(python3 "$LOCALDIR/kernel-updater.py" --check-update --version "$VERSION" --branch "$BRANCH")" + +if [ "x$LATEST_KERNEL_VERSION" == "x" ]; then + echo "Current kernel version in branch ${BRANCH} is up to date" + exit 0 +fi + +# Download latest kernel +echo "$LATEST_KERNEL_VERSION" > version +make get-sources + +FC_LATEST="$(curl -s -L https://dl.fedoraproject.org/pub/fedora/linux/releases | sed -e 's/<[^>]*>//g' | awk '{print $1}' | grep -o "[1-9][0-9]" | tail -1)" +STABLE_KERNEL="$(dnf -q repoquery kernel --disablerepo=* --enablerepo=fedora --enablerepo=updates --releasever="$FC_LATEST" | sort -V | tail -1 | cut -d ':' -f2 | cut -d '-' -f1)" +if [ "$BRANCH" == "master" ]; then + TESTING_KERNEL="$(dnf -q repoquery kernel --disablerepo=* --enablerepo=fedora --enablerepo=updates --enablerepo=updates-testing --releasever="$FC_LATEST" | sort -V | tail -1 | cut -d ':' -f2 | cut -d '-' -f1)" + RAWHIDE_KERNEL="$(dnf -q repoquery kernel --disablerepo=* --enablerepo=fedora --enablerepo=updates --releasever=rawhide | grep -v "rc[0-9]*" | sort -V | tail -1 | cut -d ':' -f2 | cut -d '-' -f1 || true)" +fi + +if distance_version "$STABLE_KERNEL" "$LATEST_KERNEL_VERSION"; then + "$LOCALDIR/get-fedora-latest-config" --releasever "$FC_LATEST" + mv config-base-"$STABLE_KERNEL" config-base +elif [ "$BRANCH" == "master" ] && { distance_version "$TESTING_KERNEL" "$LATEST_KERNEL_VERSION"; }; then + "$LOCALDIR/get-fedora-latest-config" --releasever "$FC_LATEST" --include-testing + mv config-base-"$STABLE_KERNEL" config-base +elif [ "$BRANCH" == "master" ] && { distance_version "$RAWHIDE_KERNEL" "$LATEST_KERNEL_VERSION"; }; then + "$LOCALDIR/get-fedora-latest-config" --releasever rawhide + mv config-base-"$RAWHIDE_KERNEL" config-base +else + echo "Cannot determine latest config for kernel ${LATEST_KERNEL_VERSION}. Use the current existing config..." +fi \ No newline at end of file