Skip to content
8 changes: 7 additions & 1 deletion lisa/features/infiniband.py
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,6 @@ def _install_dependencies(self) -> None:
"rdma-core-devel",
"libibverbs",
"libibverbs-utils",
"build-essential",
"ucx",
"ucx-ib",
"ucx-rdmacm",
Expand Down Expand Up @@ -341,6 +340,13 @@ def _install_dependencies(self) -> None:
ubuntu_required_packages.append(package)
node.os.install_packages(ubuntu_required_packages)
elif isinstance(node.os, CBLMariner):
if node.os.information.version >= "4.0.0":
# build-essential not available on Azure Linux 4.0
cblmariner_required_packages.extend(
["kernel-headers", "binutils", "glibc-devel", "gcc", "make"]
)
else:
cblmariner_required_packages.append("build-essential")
node.os.install_packages(cblmariner_required_packages)
else:
raise UnsupportedDistroException(
Expand Down
9 changes: 7 additions & 2 deletions lisa/microsoft/testsuites/kselftest/kselftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@
_MARINER_OS_PACKAGES = [
"bison",
"flex",
"build-essential",
"openssl-devel",
"bc",
"dwarves",
Expand Down Expand Up @@ -162,7 +161,13 @@ def _install(self) -> bool:
self.node.os.install_packages(_UBUNTU_OS_PACKAGES)
elif isinstance(self.node.os, CBLMariner):
# clone kernel, build kernel, then build kselftests
self.node.os.install_packages(_MARINER_OS_PACKAGES)
packages = list(_MARINER_OS_PACKAGES)
if self.node.os.information.version >= "4.0.0":
# build-essential not available on Azure Linux 4.0
packages.extend(["gcc", "make"])
else:
packages.append("build-essential")
self.node.os.install_packages(packages)

uname = self.node.tools[Uname]
uname_result = uname.get_linux_information(force_run=False)
Expand Down
26 changes: 17 additions & 9 deletions lisa/microsoft/testsuites/ltp/ltp.py
Original file line number Diff line number Diff line change
Expand Up @@ -385,15 +385,23 @@ def _install_dependencies(self) -> None:
]
)
elif isinstance(self.node.os, CBLMariner):
self.node.os.install_packages(
[
"kernel-headers",
"binutils",
"diffutils",
"glibc-devel",
"zlib-devel",
]
)
packages = [
"kernel-headers",
"binutils",
"diffutils",
"glibc-devel",
]
if self.node.os.information.version >= "4.0.0":
packages.extend([
"libaio-devel",
"libattr",
"libcap-devel",
"pkgconf",
"zlib-ng-compat-devel",
])
else:
packages.append("zlib-devel")
self.node.os.install_packages(packages)
else:
raise LisaException(f"{self.node.os} is not supported")

Expand Down
33 changes: 32 additions & 1 deletion lisa/microsoft/testsuites/xfstests/xfstests.py
Original file line number Diff line number Diff line change
Expand Up @@ -699,6 +699,18 @@ class Xfstests(Tool):
"psmisc",
"perl-CPAN",
]
# CBL Mariner 4.0 Dependencies
mariner_4_dep = [
"libattr-devel",
"binutils",
"kernel-headers",
"perl-CPAN",
"diffutils",
"btrfs-progs-devel",
"zlib-ng-compat-devel",
"libblkid-devel",
"libmount-devel",
]
# Regular expression for parsing xfstests output
# Example:
# Passed all 35 tests
Expand Down Expand Up @@ -941,7 +953,11 @@ def _install_dep(self) -> None:
elif isinstance(self.node.os, Suse):
package_list.extend(self.suse_dep)
elif isinstance(self.node.os, CBLMariner):
package_list.extend(self.mariner_dep)
if self.node.os.information.version >= "4.0.0":
package_list.extend(self.fedora_dep)
package_list.extend(self.mariner_4_dep)
else:
package_list.extend(self.mariner_dep)
else:
raise LisaException(
f"Current distro {self.node.os.name} doesn't support xfstests."
Expand Down Expand Up @@ -1067,6 +1083,21 @@ def _install(
file=str(code_path / "src" / "Makefile"),
)

# Temporary Workaround to test xfs in Azurelinux 4.0
# DO NOT MERGE
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems to be a bug (missing symlink in pkg-config package) in 4.0 Alpha image, added a workaround to test xfs. will remove this once upstream gets fixed.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is only issue in Alpha1 image.
Fix is present in azurelinux-stage1-compact package. installing that package creates this symlink. in stage2 image this change would not be required.

if (
isinstance(self.node.os, CBLMariner)
and self.node.os.information.version >= "4.0.0"
):
self.node.execute(
"ln -sf /usr/bin/pkgconf"
" /usr/bin/$(rpm --eval"
" '%{_target_cpu}-%{_vendor}-%{_target_os}%{?_gnu}')"
"-pkg-config",
sudo=True,
shell=True,
)

# Regenerate configure script to fix PKG_CHECK_MODULES macro expansion issue.
# The pre-generated configure script in xfstests-dev git repo may have
# unexpanded PKG_CHECK_MODULES macros if it was generated without pkg-config.
Expand Down
10 changes: 8 additions & 2 deletions lisa/operating_system.py
Original file line number Diff line number Diff line change
Expand Up @@ -2068,7 +2068,7 @@ def name_pattern(cls) -> Pattern[str]:

def __init__(self, node: Any) -> None:
super().__init__(node)
self._dnf_tool_name: str
self._dnf_tool_name: str = "dnf"
Copy link

Copilot AI Mar 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Setting _dnf_tool_name default to "dnf" can cause CBLMariner to run dnf before _initialize_package_installation() has had a chance to detect whether only tdnf is available. Since RPMDistro._install_packages/_uninstall_packages call _dnf_tool() without first calling _initialize_package_installation(), consider ensuring tool selection is initialized before any package operation (e.g., lazy-init inside _dnf_tool() or overriding _install_packages/_uninstall_packages to gate on _first_time_installation).

Copilot uses AI. Check for mistakes.

def _initialize_package_installation(self) -> None:
self.set_kill_user_processes()
Expand Down Expand Up @@ -2136,9 +2136,15 @@ def _create_local_repo(self, source_tarball: Path) -> None:
# the SSH session is reset
def set_kill_user_processes(self) -> None:
sed = self._node.tools[Sed]
# Azure Linux 4.0 moved logind.conf to /usr/lib/systemd/
logind_conf = "/etc/systemd/logind.conf"
if not self._node.shell.exists(
self._node.get_pure_path(logind_conf)
):
logind_conf = "/usr/lib/systemd/logind.conf"
Comment on lines +2141 to +2144
Copy link

Copilot AI Mar 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The fallback to /usr/lib/systemd/logind.conf is not validated for existence. If neither /etc/systemd/logind.conf nor /usr/lib/systemd/logind.conf exists, sed -i will fail and this method will raise unexpectedly. Consider checking the fallback path too and either creating /etc/systemd/logind.conf (preferred) or raising a clear error/skip when systemd config is not present.

Suggested change
if not self._node.shell.exists(
self._node.get_pure_path(logind_conf)
):
logind_conf = "/usr/lib/systemd/logind.conf"
shell = self._node.shell
primary_path = self._node.get_pure_path(logind_conf)
if not shell.exists(primary_path):
fallback_logind_conf = "/usr/lib/systemd/logind.conf"
fallback_path = self._node.get_pure_path(fallback_logind_conf)
if shell.exists(fallback_path):
logind_conf = fallback_logind_conf
else:
# Neither primary nor fallback exist; create the primary config file
self._log.debug(
"Neither /etc/systemd/logind.conf nor /usr/lib/systemd/logind.conf "
"exists. Creating /etc/systemd/logind.conf."
)
self._node.execute(
"mkdir -p /etc/systemd && touch /etc/systemd/logind.conf",
sudo=True,
shell=True,
expected_exit_code=0,
expected_exit_code_failure_message=(
"Failed to create /etc/systemd/logind.conf"
),
)

Copilot uses AI. Check for mistakes.
sed.append(
text="KillUserProcesses=no",
file="/etc/systemd/logind.conf",
file=logind_conf,
Comment on lines +2139 to +2147
Copy link

Copilot AI Mar 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Editing the vendor config at /usr/lib/systemd/logind.conf is brittle (package updates may overwrite it) and may not be the correct override location for systemd. Prefer writing the setting to /etc/systemd/logind.conf (create it if missing) or a drop-in under /etc/systemd/logind.conf.d/, and keep /usr/lib untouched.

Copilot uses AI. Check for mistakes.
sudo=True,
)
self._node.tools[Service].restart_service("systemd-logind")
Comment on lines 2145 to 2150
Copy link

Copilot AI Mar 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

set_kill_user_processes() always uses sed.append(...) and restarts systemd-logind, so repeated calls will keep appending duplicate KillUserProcesses=no lines and repeatedly restart the service (this is also currently invoked from _initialize_package_installation). Making the change idempotent (e.g., replace existing KillUserProcesses= or check if the setting already exists before editing/restarting) would avoid config bloat and unnecessary service churn.

Copilot uses AI. Check for mistakes.
Expand Down
8 changes: 7 additions & 1 deletion lisa/tools/cargo.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,13 @@ def __install_dependencies(self) -> None:
node_os: Posix = cast(Posix, self.node.os)

# install prerequisites
node_os.install_packages(["build-essential", "cmake"])
if isinstance(node_os, CBLMariner) and node_os.information.version >= "4.0.0":
# build-essential not available on Azure Linux 4.0
node_os.install_packages(
["kernel-headers", "binutils", "glibc-devel", "gcc", "make", "cmake"]
)
else:
node_os.install_packages(["build-essential", "cmake"])

gcc = self.node.tools[Gcc]
gcc_version_info = gcc.get_version()
Expand Down
6 changes: 5 additions & 1 deletion lisa/tools/docker.py
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,11 @@ def _install(self) -> bool:
["docker-ce", "docker-ce-cli", "containerd.io"]
)
elif isinstance(self.node.os, CBLMariner):
self.node.os.install_packages(["moby-engine", "moby-cli"])
if self.node.os.information.version >= "4.0.0":
# moby-cli not available on Azure Linux 4.0
self.node.os.install_packages(["moby-engine"])
else:
self.node.os.install_packages(["moby-engine", "moby-cli"])
elif isinstance(self.node.os, Suse) or isinstance(self.node.os, Fedora):
self.node.os.install_packages(["docker"])
elif isinstance(self.node.os, BSD):
Expand Down
9 changes: 6 additions & 3 deletions lisa/tools/fio.py
Original file line number Diff line number Diff line change
Expand Up @@ -420,19 +420,22 @@ def _install_dep_packages(self) -> None:
elif isinstance(self.node.os, CBLMariner):
package_list = [
"wget",
"build-essential",
"sysstat",
"blktrace",
"libaio",
"bc",
"sysstat",
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Image sysstat is available in 4.0 but fails to install due to missing pcp

"libaio-devel",
"gcc",
"kernel-devel",
"kernel-headers",
"binutils",
"glibc-devel",
"zlib-devel",
]
if self.node.os.information.version >= "4.0.0":
# zlib-devel replaced by zlib-ng-compat-devel on Azure Linux 4.0
package_list.append("zlib-ng-compat-devel")
else:
package_list.extend(["build-essential", "zlib-devel"])
else:
raise LisaException(
f"tool {self.command} can't be installed in distro {self.node.os.name}."
Expand Down
4 changes: 2 additions & 2 deletions lisa/tools/fips.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,11 @@ def create(cls, node: "Node", *args: Any, **kwargs: Any) -> Tool:
if isinstance(node.os, CBLMariner):
if node.os.information.release == "2.0":
return AzlV2Fips(node, args, kwargs)
if node.os.information.release == "3.0":
if node.os.information.release in ("3.0", "4.0"):
return AzlV3Fips(node, args, kwargs)

raise UnsupportedDistroException(
os=node.os, message="FIPS tool only supported on CBLMariner 2.0 and 3.0."
os=node.os, message="FIPS tool only supported on CBLMariner 2.0, 3.0 and 4.0."
Copy link

Copilot AI Mar 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The UnsupportedDistroException(...) call is now long enough to violate the repo's flake8 max-line-length = 88 setting, which will fail linting. Please wrap the arguments across multiple lines (similar to grub_config.py) so each line stays within 88 chars.

Suggested change
os=node.os, message="FIPS tool only supported on CBLMariner 2.0, 3.0 and 4.0."
os=node.os,
message="FIPS tool only supported on CBLMariner 2.0, 3.0 and 4.0.",

Copilot uses AI. Check for mistakes.
)

def __init__(self, node: "Node", *args: Any, **kwargs: Any) -> None:
Expand Down
13 changes: 12 additions & 1 deletion lisa/tools/gpu_drivers.py
Original file line number Diff line number Diff line change
Expand Up @@ -379,7 +379,18 @@ def _install_dependencies(self) -> None:
]
# CBL-Mariner dependencies
elif isinstance(self.node.os, CBLMariner):
dependencies = ["build-essential", "binutils", "kernel-devel"]
if self.node.os.information.version >= "4.0.0":
# build-essential not available on Azure Linux 4.0
dependencies = [
"kernel-headers",
"binutils",
"glibc-devel",
"gcc",
"make",
"kernel-devel",
]
else:
dependencies = ["build-essential", "binutils", "kernel-devel"]

if not dependencies:
return
Expand Down
4 changes: 2 additions & 2 deletions lisa/tools/grub_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ def create(cls, node: "Node", *args: Any, **kwargs: Any) -> Tool:
if isinstance(node.os, CBLMariner):
if node.os.information.release == "2.0":
return GrubConfigAzl2(node, args, kwargs)
if node.os.information.release == "3.0":
if node.os.information.release in ("3.0", "4.0"):
return GrubConfigAzl3(node, args, kwargs)
elif isinstance(node.os, Debian):
return GrubConfigDebian(node, args, kwargs)
Expand All @@ -31,7 +31,7 @@ def create(cls, node: "Node", *args: Any, **kwargs: Any) -> Tool:

raise UnsupportedDistroException(
os=node.os,
message="Grub tool only supported on CBLMariner 2.0/3.0, "
message="Grub tool only supported on CBLMariner 2.0, 3.0 and 4.0, "
"Debian-based distributions, and RHEL-based distributions.",
)

Expand Down
19 changes: 11 additions & 8 deletions lisa/tools/ntttcp.py
Original file line number Diff line number Diff line change
Expand Up @@ -762,14 +762,17 @@ def _initialize(self, *args: Any, **kwargs: Any) -> None:

def _install(self) -> bool:
if isinstance(self.node.os, CBLMariner):
self.node.os.install_packages(
[
"kernel-headers",
"binutils",
"glibc-devel",
"zlib-devel",
]
)
packages = [
"kernel-headers",
"binutils",
"glibc-devel",
]
if self.node.os.information.version >= "4.0.0":
# zlib-devel not available on Azure Linux 4.0
packages.append("zlib-ng-compat-devel")
else:
packages.append("zlib-devel")
self.node.os.install_packages(packages)
elif (
isinstance(self.node.os, Ubuntu)
and self.node.os.information.version >= "25.10.0"
Expand Down
6 changes: 5 additions & 1 deletion lisa/tools/perf.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,11 @@ def _install(self) -> bool:
self.node.tools[Uname].get_linux_information().kernel_version_raw
)
if isinstance(self.node.os, CBLMariner):
self.node.os.install_packages("kernel-tools")
if self.node.os.information.version >= "4.0.0":
# Azure Linux 4.0 has perf in a separate package
self.node.os.install_packages("perf")
else:
self.node.os.install_packages("kernel-tools")
elif isinstance(self.node.os, (Redhat, Suse)):
self.node.os.install_packages("perf")
elif isinstance(
Expand Down
6 changes: 5 additions & 1 deletion lisa/tools/sockperf.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,11 @@ def install(self) -> bool:

# mariner needs headers and -dev packages
if isinstance(posix_os, CBLMariner):
packages.append("build-essential")
if posix_os.information.version >= "4.0.0":
# build-essential not available on Azure Linux 4.0
packages.extend(["kernel-headers", "binutils", "glibc-devel"])
else:
packages.append("build-essential")

# install and pick build dir
posix_os.install_packages(packages)
Expand Down
41 changes: 22 additions & 19 deletions lisa/transformers/kernel_source_installer.py
Original file line number Diff line number Diff line change
Expand Up @@ -451,25 +451,28 @@ def _install_build_tools(self, node: Node) -> None:
]
)
elif isinstance(os, CBLMariner):
os.install_packages(
[
"build-essential",
"bison",
"flex",
"bc",
"ccache",
"elfutils-libelf",
"elfutils-libelf-devel",
"ncurses-libs",
"ncurses-compat",
"xz",
"xz-devel",
"xz-libs",
"openssl-libs",
"openssl-devel",
"xxhash-devel",
]
)
packages = [
"bison",
"flex",
"bc",
"elfutils-libelf",
"elfutils-libelf-devel",
"ncurses-libs",
"xz",
"xz-devel",
"xz-libs",
"openssl-libs",
"openssl-devel",
"xxhash-devel",
]
if os.information.version >= "4.0.0":
# build-essential, ccache, ncurses-compat not available on Azure Linux 4.0
packages.extend(
["kernel-headers", "binutils", "glibc-devel", "gcc", "make"]
)
else:
packages.extend(["build-essential", "ccache", "ncurses-compat"])
os.install_packages(packages)
else:
raise LisaException(
f"os '{os.name}' doesn't support in {self.type_name()}. "
Expand Down
Loading