Skip to content

Commit 200592b

Browse files
committed
os: build dep lock and initialized variable cleanup
1 parent 2805214 commit 200592b

File tree

1 file changed

+49
-11
lines changed

1 file changed

+49
-11
lines changed

lisa/operating_system.py

Lines changed: 49 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
from enum import Enum
88
from functools import partial
99
from pathlib import Path
10+
from threading import Lock
1011
from typing import (
1112
TYPE_CHECKING,
1213
Any,
@@ -354,6 +355,16 @@ class Posix(OperatingSystem, BaseClassMixin):
354355
def __init__(self, node: Any) -> None:
355356
super().__init__(node, is_posix=True)
356357
self._first_time_installation: bool = True
358+
# instance variables to check if source repositories are enabled
359+
# some distros make this easier than others,
360+
# but all allow use of source code packages which are compiled
361+
# on the local machine instead of binary packages.
362+
# slower, but allows local optimization and auditing.
363+
# lucky for us! those packages contain build dependency metadata.
364+
# we can use this to avoid keeping long lists
365+
# of constantly changing package names for each distro.
366+
self._source_installation_initialized = False
367+
self._lock = Lock()
357368

358369
@classmethod
359370
def type_name(cls) -> str:
@@ -452,7 +463,6 @@ def enable_package_build_deps(self) -> None:
452463
turning on deb-src or srpm repositories.
453464
"""
454465
self._enable_package_build_deps()
455-
self._src_repo_initialized = True
456466

457467
def install_build_deps(
458468
self,
@@ -462,8 +472,12 @@ def install_build_deps(
462472
Install apt-get/yum build-deps package build dependency installation by
463473
turning on deb-src or srpm repositories.
464474
"""
465-
if not getattr(self, "_src_repo_initialized", False):
466-
self.enable_package_build_deps()
475+
# lock this to prevent double initialization;
476+
# some methods involve directly writing to a file
477+
with self._lock:
478+
if not self._source_installation_initialized:
479+
self.enable_package_build_deps()
480+
self._source_installation_initialized = True
467481

468482
package_names = self._get_package_list(packages)
469483
for package in package_names:
@@ -964,14 +978,19 @@ def _get_package_information(self, package_name: str) -> LisaVersionInfo:
964978
return self._cache_and_return_version_info(package_name, version_info)
965979

966980
def _enable_package_build_deps(self) -> None:
967-
if not getattr(self, "_src_repo_initialized", False):
981+
# debian uses apt sources.list.
982+
# we only need to uncomment the standard source repos
983+
# in that file
984+
sources_list = self._node.get_pure_path("/etc/apt/sources.list")
985+
if self._node.shell.exists(sources_list):
968986
self._node.tools[Sed].substitute(
969-
"# deb-src", "deb-src", "/etc/apt/sources.list", sudo=True
987+
"# deb-src", "deb-src", str(sources_list), sudo=True
970988
)
971989
self.get_repositories()
972-
self._src_repo_initialized = True
973990

974991
def _install_build_deps(self, packages: str) -> None:
992+
# apt-get build-dep installs the listed build dependencies
993+
# from the src .deb for a given package.
975994
self._node.execute(
976995
f"apt-get build-dep -y {packages}",
977996
sudo=True,
@@ -1501,11 +1520,12 @@ def _enable_package_build_deps(self) -> None:
15011520
# file in place of the sources.list file. It uses a fancier format, so
15021521
# requires special handling.
15031522
node = self._node
1504-
if node.shell.exists(node.get_pure_path("/etc/apt/ubuntu.sources")):
1523+
ubuntu_sources = node.get_pure_path("/etc/apt/ubuntu.sources")
1524+
if node.shell.exists(ubuntu_sources):
15051525
node.tools[Sed].substitute(
15061526
regexp=r"Types\: deb",
15071527
replacement=r"Types\: deb deb-src",
1508-
file="/etc/apt/ubuntu.sources",
1528+
file=str(ubuntu_sources),
15091529
sudo=True,
15101530
)
15111531
else:
@@ -1888,6 +1908,7 @@ def _get_information(self) -> OsInformation:
18881908
return information
18891909

18901910
def _enable_package_build_deps(self) -> None:
1911+
# epel enbables source repos by default
18911912
self.install_epel()
18921913

18931914

@@ -2091,13 +2112,16 @@ def _dnf_tool(self) -> str:
20912112
def _enable_package_build_deps(self) -> None:
20922113
# enable epel first
20932114
super()._enable_package_build_deps()
2115+
# almalinux has a few different source repos, they are easy to enable
20942116
self._node.execute("dnf install -y almalinux-release-devel")
20952117
# then enable crb (code ready builder) using alma tool
20962118
# this enables some needed package build dependency srpms
2119+
# this was formerly known as the 'powertools' repo.
20972120
if int(self.information.version.major) == 8:
20982121
pkg = "powertools"
20992122
elif int(self.information.version.major) == 9:
21002123
pkg = "crb"
2124+
# set the repo as enabled
21012125
self._node.execute(
21022126
f"dnf config-manager --set-enabled {pkg}",
21032127
sudo=True,
@@ -2417,28 +2441,42 @@ def add_azure_core_repo(
24172441
)
24182442

24192443
def _enable_package_build_deps(self) -> None:
2444+
# zypper seems more suited to interactive use
2445+
# to enable source repos, list the defaults and select the source repos
24202446
repos = self.get_repositories()
24212447
for repo in repos:
24222448
if isinstance(repo, SuseRepositoryInfo) and "Source-Pool" in repo.name:
2449+
# if it's a source repo, enable it
24232450
self._node.execute(
24242451
f"zypper mr -e {repo.alias}",
24252452
sudo=True,
24262453
expected_exit_code=0,
2427-
expected_exit_code_failure_message=f"Could not enable source pool for repo: {repo.alias}",
2454+
expected_exit_code_failure_message=(
2455+
f"Could not enable source pool for repo: {repo.alias}"
2456+
),
24282457
)
2458+
# then refresh the repo status to fetch the new metadata
24292459
self._node.execute(
24302460
"zypper refresh -y",
24312461
sudo=True,
24322462
expected_exit_code=0,
2433-
expected_exit_code_failure_message="Failure to zypper refresh after enabling source repos.",
2463+
expected_exit_code_failure_message=(
2464+
"Failure to zypper refresh after enabling source repos."
2465+
),
24342466
)
24352467

24362468
def _install_build_deps(self, packages: str) -> None:
2469+
# zypper sourceinstall the packages
2470+
# if there are missing dependencies, you can attempt to
2471+
# force zypper to work out the problem. It seems to assume
2472+
# interactive usage for these even with the -n flag so YMMV.
24372473
self._node.execute(
24382474
f"zypper si --build-deps-only --force-resolution {packages}",
24392475
sudo=True,
24402476
expected_exit_code=0,
2441-
expected_exit_code_failure_message=f"failed to source install package: {packages}",
2477+
expected_exit_code_failure_message=(
2478+
f"failed to source install package: {packages}"
2479+
),
24422480
)
24432481

24442482
def _initialize_package_installation(self) -> None:

0 commit comments

Comments
 (0)