[Merge] ~bamf0/ubuntu-release-upgrader:ibm-prevent-z13-26-04-update into ubuntu-release-upgrader:ubuntu/main
Simon Johnsson
mp+499739 at code.launchpad.net
Wed Feb 4 15:55:35 UTC 2026
Diff comments:
> diff --git a/DistUpgrade/DistUpgradeQuirks.py b/DistUpgrade/DistUpgradeQuirks.py
> index 0782e76..eb9dade 100644
> --- a/DistUpgrade/DistUpgradeQuirks.py
> +++ b/DistUpgrade/DistUpgradeQuirks.py
> @@ -1160,6 +1163,42 @@ class DistUpgradeQuirks(object):
> )
> self.controller.abort()
>
> + def _test_and_fail_on_z13(self):
> + """
> + With release Ubuntu 26.04 we have raised the ISA generation
> + requirement on s390x to z15. Prevent systems that are below z15
> + from upgrading beyond Ubuntu 25.10.
> + """
> +
> + di = distro_info.UbuntuDistroInfo()
> + version = di.version(self.controller.toDist) or 'next release'
> +
> + generation: S390xGeneration | None = get_system_s390x_generation()
> + if generation is None:
> + logging.debug(
> + 's390x generation check: cannot determine generation'
> + )
> + return
> +
> + if generation >= S390xGeneration.Z15:
> + logging.debug(
> + 's390x generation check: generation is z15 or newer'
> + )
> + return
> +
> + self._view.error(
> + _(
> + f'Sorry, cannot upgrade this system to {version}'
> + ),
> + _(
> + 'On Ubuntu 26.04 and later, s390x systems are required '
Right! I was unsure at first since the restriction comes from 26.04 and using `version` was to future-proof for other upgrades. However, I see now that the system would need to be *at least* version 26.04 to run this in future versions. I say let's hard-code it in this case then, as `version` would not always match with the release notes otherwise.
> + 'to be z15 or newer, but your system is not. Please, '
> + 'see https://discourse.ubuntu.com/t/'
> + 'resolute-raccoon-release-notes for more information.'
> + ),
> + )
> + self.controller.abort()
> +
> def _test_and_fail_on_tpm_fde(self):
> """
> LP: #2065229
> diff --git a/DistUpgrade/S390xGeneration.py b/DistUpgrade/S390xGeneration.py
> new file mode 100644
> index 0000000..b7a4ef5
> --- /dev/null
> +++ b/DistUpgrade/S390xGeneration.py
> @@ -0,0 +1,113 @@
> +#!/usr/bin/python3
> +"""
> +S390xGeneration
> +
> +This module provides functionality to determine the generation of the
> +s390x architecture based on the machine type.
> +
> +Author: Simon Johnsson
> +Version: 0.0.1
> +"""
> +
> +import logging
> +import platform
> +
> +from enum import Enum, auto
> +
> +
> +class S390xGeneration(Enum):
> + """
> + S390xGeneration
> +
> + This Enum class provides constants representing different generations
> + of the S390x architecture.
> + """
> +
> + # IMPORTANT: Keep the order of the generations as it is, as the
> + # comparison operators depend on it.
> + ZEC12 = auto()
> + Z13 = auto()
> + Z14 = auto()
> + Z15 = auto()
> + Z16 = auto()
> + Z17 = auto()
> +
> + def __lt__(self, other: "S390xGeneration") -> bool:
> + return self.value < other.value
> +
> + def __gt__(self, other: "S390xGeneration") -> bool:
> + return self.value > other.value
> +
> + def __le__(self, other: "S390xGeneration") -> bool:
> + return self.value <= other.value
> +
> + def __ge__(self, other: "S390xGeneration") -> bool:
> + return self.value >= other.value
> +
> +
> +def _machine_type_to_generation(machine_type: int) -> S390xGeneration | None:
> + """
> + Get the S390x generation corresponding to the given machine type.
> +
> + Returns:
> + S390xGeneration | None: The corresponding S390x generation, or None if
> + the machine code is unrecognized.
> + """
> + mapping: dict[int, S390xGeneration] = {
Ah yes, these were provided by Frank Heimes. I am not entirely sure if there is an easy way of finding them online so I omitted the source.
> + # zEC12 machine types
> + 2827: S390xGeneration.ZEC12,
> + 2828: S390xGeneration.ZEC12,
> + # z13 machine types
> + 2964: S390xGeneration.Z13,
> + 2965: S390xGeneration.Z13,
> + # z14 machine types
> + 3906: S390xGeneration.Z14,
> + 3907: S390xGeneration.Z14,
> + # z15 machine types
> + 8561: S390xGeneration.Z15,
> + 8562: S390xGeneration.Z15,
> + # z16 machine types
> + 3931: S390xGeneration.Z16,
> + 3932: S390xGeneration.Z16,
> + # z17 machine types
> + 9175: S390xGeneration.Z17,
> + 9176: S390xGeneration.Z17,
> + }
> + return mapping.get(machine_type)
> +
> +
> +def _read_machine_type() -> int | None:
> + """
> + Read the machine type from /proc/sysinfo.
> +
> + Returns:
> + int | None: The machine type as an integer, or None if it cannot be
> + determined.
> + """
> + try:
> + with open("/proc/cpuinfo", "r") as f:
> + for line in f:
> + if line.startswith("machine"):
AFAIK there should only be one field containing "machine", but I think your suggestion is more solid. The current code relies on a somewhat fragile assumption.
> + _, value = line.split(":", 1)
Good point, let's go for that!
> + return int(value.strip())
I'm not entirely sure actually. I think we can pretty safely assume that the format is:
"machine"<padding>: <number>,
if the "machine" field exists. However `continue` might be a safer option overall, and I do not see how not returning early would introduce any considerable execution time increases.
> + except (FileNotFoundError, ValueError):
> + return None
> + return None
> +
> +
> +def get_system_s390x_generation() -> S390xGeneration | None:
> + """
> + Return the current running s390x generation, otherwise None if not running
> + on s390x architecture or if the generation cannot be determined.
> + """
> +
> + if platform.machine() != "s390x":
That sounds good. The idea was to provide some module isolation since we do not expose the controller here, but then again we can probably assume that this will only get called in the Quirks.
> + logging.debug("Not running on s390x architecture!")
> + return None
> +
> + machine_type = _read_machine_type()
> + if machine_type is None:
> + logging.warning("Failed to read machine type from /proc/cpuinfo!")
> + return None
> +
> + return _machine_type_to_generation(machine_type)
> diff --git a/debian/changelog b/debian/changelog
> index 9df1d01..1e0cda2 100644
> --- a/debian/changelog
> +++ b/debian/changelog
> @@ -1,3 +1,10 @@
> +ubuntu-release-upgrader (1:26.04.6) resolute; urgency=medium
> +
> + * DistUpgrade: prevent z13 s390x machines from upgrading
> + to 26.04 or later.
Good question! There is no bug tracking this at the moment. This came directly from communicating with IBM I believe, so the choice was made not to create a bug for it.
> +
> + -- Simon Johnsson <simon.johnsson at canonical.com> Tue, 27 Jan 2026 10:46:33 +0100
> +
> ubuntu-release-upgrader (1:26.04.5) resolute; urgency=medium
>
> * DistUpgrade: keep a disabled copy of .list files that could not be migrated
--
https://code.launchpad.net/~bamf0/ubuntu-release-upgrader/+git/ubuntu-release-upgrader/+merge/499739
Your team Ubuntu Core Development Team is subscribed to branch ubuntu-release-upgrader:ubuntu/main.
More information about the Ubuntu-reviews
mailing list