Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Github actions fix, UEK-next support, and a table fix #85

Merged
merged 5 commits into from
Jun 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 0 additions & 26 deletions .github/workflows/litevm.yml
Original file line number Diff line number Diff line change
Expand Up @@ -63,32 +63,6 @@ jobs:
tox list
tox --notest
tox -e runner --notest

# Use Github Actions to cache RPMs by date. This can save a couple minutes
# in the run, which is nice. The cache contains the Yum sqlite database,
# and the downloaded RPMs.
#
# A cache miss results in getting the most recent cached data (e.g. from
# yesterday). The runner will check the repo metadata and get the updated
# data, and delete any stale data, so after the run completes, the
# testdata can be cached for future runs.
#
# On a cache hit, the test runner will still check the yum repo metadata,
# and if it differs from the cached data, it will clear and download it.
# So a cache hit isn't guaranteed to speed things up, but kernel packages
# aren't usually updated _that_ frequently.
- name: Get Date
id: get-date
run: |
echo "date=$(/bin/date -u "+%Y%m%d")" >> $GITHUB_OUTPUT
shell: bash
- name: Cache RPMs
uses: actions/cache@v3
with:
path: testdata/yumcache
key: ${{ runner.os }}-rpms-${{ steps.get-date.outputs.date }}
restore-keys: |
${{ runner.os }}-rpms-
- name: Fetch RPMs
run: |
tox -e runner -- python -m testing.litevm.rpm
Expand Down
9 changes: 8 additions & 1 deletion drgn_tools/corelens.py
Original file line number Diff line number Diff line change
Expand Up @@ -549,6 +549,8 @@ def _run_module(
if print_header:
print(f"\n====== MODULE {mod.name} ======")
mod.run(prog, args)
except (KeyboardInterrupt, BrokenPipeError):
raise
except Exception:
formatted = traceback.format_exc()
errors.append(
Expand Down Expand Up @@ -791,4 +793,9 @@ def cl(cl_cmd: str) -> None:
# terrible, terrible corner of Python.
import drgn_tools.corelens

drgn_tools.corelens.main()
try:
drgn_tools.corelens.main()
except KeyboardInterrupt:
sys.exit("interrupted")
except BrokenPipeError:
pass
43 changes: 37 additions & 6 deletions drgn_tools/debuginfo.py
Original file line number Diff line number Diff line change
Expand Up @@ -452,6 +452,13 @@ class KernelVersion(NamedTuple):
Note that depending on the package versioning scheme, the patchlevel number
here may be useless, misleading, or otherwise unhelpful.
"""
version_tuple: Tuple[int, ...]
"""
The upstream version, split into integer groups for easy comparison.

This should be a three element tuple, but the code does not enforce it as a
requirement, so you should treat it as a variable length tuple of integers.
"""
release: str
"""The packaging release version (the stuff after the hyphen)."""
release_tuple: Tuple[int, ...]
Expand Down Expand Up @@ -479,14 +486,22 @@ class KernelVersion(NamedTuple):
"""Whether the kernel is a UEK kernel."""
uek_version: Optional[int]
"""The major version of the UEK release, if applicable."""
is_ueknext: bool
"""Whether the kernel is a UEK-next kernel (uek_version will be None)"""

@classmethod
def parse(cls, original: str) -> "KernelVersion":
"""
Parse the given kernel release string and return a ``KernelVersion``:

>>> KernelVersion.parse(prog["UTS_RELEASE"].string_().decode("ascii"))
KernelVersion(version='4.14.35', release='2047.516.2.4', ol_version=7, ol_update=None, arch='x86_64', original='4.14.35-2047.516.2.4.el7uek.x86_64', is_uek=True)
>>> KernelVersion.parse('4.14.35-2047.516.2.4.el7uek.x86_64')
KernelVersion(version='4.14.35', version_tuple=(4, 14, 35),
release='2047.516.2.4',
release_tuple=(2047, 516, 2, 4),
ol_version=7, ol_update=None, arch='x86_64',
original='4.14.35-2047.516.2.4.el7uek.x86_64',
extraversion1='', extraversion2='', is_uek=True,
uek_version=5, is_ueknext=False)

:param original: The kernel's release string
:returns: A ``KernelVersion`` with fields parsed
Expand All @@ -503,17 +518,23 @@ def parse(cls, original: str) -> "KernelVersion":
raise ValueError(
"Could not understand kernel version string: " + original
)
version_tuple = tuple(
int(g) for g in re.split("[.-]", match["version"])
)
release_tuple = tuple(
int(g) for g in re.split("[.-]", match["release"])
)
update = None
if match["update"]:
update = int(match["update"])
is_uek = match["extra"].startswith("uek")
uek_ver = None
if match["extra"].startswith("uek"):
if is_uek:
uek_ver = _UEK_VER.get(match["version"])
is_uek_next = is_uek and uek_ver is None and version_tuple >= (6, 8, 0)
return cls(
match["version"],
version_tuple,
match["release"],
release_tuple,
int(match.group("ol_version")),
Expand All @@ -522,12 +543,15 @@ def parse(cls, original: str) -> "KernelVersion":
original,
match["extraversion1"] or "",
match["extraversion2"] or "",
match["extra"].startswith("uek"),
is_uek,
uek_ver,
is_uek_next,
)

def oraclelinux_debuginfo_rpm(self) -> str:
if self.is_uek:
if self.is_uek and self.is_ueknext:
package_name = "kernel-ueknext"
elif self.is_uek:
package_name = "kernel-uek"
else:
package_name = "kernel"
Expand Down Expand Up @@ -635,7 +659,14 @@ def get(
cls, kver: KernelVersion, host_ol: Optional[int]
) -> "CtfCompatibility":
# At this point, only UEK kernels have CTF debuginfo.
if not kver.is_uek or kver.uek_version is None:
if not kver.is_uek:
return cls.NO
# UEK-next kernels have no compatibility issues
if kver.is_ueknext:
return cls.YES
elif kver.uek_version is None:
# If it's UEK, but we can't identify a version or -next, that's a
# bug!
return cls.NO

# Prior to UEK4, it is untested and will not be tested.
Expand Down
2 changes: 1 addition & 1 deletion drgn_tools/table.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ def print_table(
"".join(
str(val).ljust(col_width + 2)
for (val, col_width) in zip(entry, col_widths)
).strip(),
).rstrip(),
file=out,
)

Expand Down
42 changes: 35 additions & 7 deletions testing/litevm/rpm.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
from pathlib import Path
from typing import List
from typing import Optional
from typing import Union

from drgn_tools.util import download_file
from testing.util import BASE_DIR
Expand All @@ -24,7 +25,7 @@
)
REPODATA = "repodata/repomd.xml"

DEBUGINFO_URL = "https://oss.oracle.com/ol{ol_ver}/debuginfo/kernel-uek-debuginfo-{release}.rpm"
DEBUGINFO_URL = "https://oss.oracle.com/ol{ol_ver}/debuginfo/{pkgbase}-debuginfo-{release}.rpm"

YUM_CACHE_DIR = BASE_DIR / "yumcache"

Expand Down Expand Up @@ -91,7 +92,7 @@ def download_file_cached(

class TestKernel:
ol_ver: int
uek_ver: int
uek_ver: Union[int, str]
arch: str
pkgs: List[str]

Expand All @@ -104,11 +105,15 @@ def __init__(
arch: str,
pkgs: List[str],
cache_dir: Optional[Path] = None,
pkgbase: str = "kernel-uek",
yum_fmt: Optional[str] = None,
) -> None:
self.ol_ver = ol_ver
self.uek_ver = uek_ver
self.arch = arch
self.pkgs = pkgs
self.yum_fmt = yum_fmt
self.pkgbase = pkgbase

self._release: str = ""
self._rpm_urls: List[str] = []
Expand Down Expand Up @@ -136,7 +141,7 @@ def _cache_key(self, kind: str) -> str:
def _getlatest(self) -> None:
# Fetch Yum index (repomd.xml) to get the database filename.
# This is never cached, and it's a small file.
yumbase = UEK_YUM.format(
yumbase = (self.yum_fmt or UEK_YUM).format(
ol_ver=self.ol_ver,
uek_ver=self.uek_ver,
arch=self.arch,
Expand Down Expand Up @@ -170,14 +175,13 @@ def _getlatest(self) -> None:
# Finally, search for the latest version in the DB. We always search for
# kernel-uek since even if the package is split, that's the
# meta-package.
pkg = "kernel-uek"
conn = sqlite3.connect(str(db_path))
rows = conn.execute(
"""
SELECT version, release, location_href FROM packages
WHERE name=? AND arch=?;
""",
(pkg, self.arch),
(self.pkgbase, self.arch),
).fetchall()
conn.close()

Expand All @@ -193,10 +197,12 @@ def key(t):
self._rpm_urls = []
rpm_url = yumbase + href
for final_pkg in self.pkgs:
self._rpm_urls.append(rpm_url.replace(pkg, final_pkg))
self._rpm_urls.append(rpm_url.replace(self.pkgbase, final_pkg))
self._release = f"{ver}-{rel}.{self.arch}"
self._dbinfo_url = DEBUGINFO_URL.format(
ol_ver=self.ol_ver, release=self._release
ol_ver=self.ol_ver,
release=self._release,
pkgbase=self.pkgbase,
)

def _get_rpms(self) -> None:
Expand Down Expand Up @@ -236,6 +242,28 @@ def get_oot_modules(self) -> List[Path]:


TEST_KERNELS = [
# UEK-next is a snapshot of the latest upstream kernel, with UEK
# configurations and any customizations. It's not officially supported, but
# it's an excellent test bed to ensure we are ready to support the latest
# upstream features.
# We also apparently need to add "-modules-core" RPMs, because there weren't
# enough kernel RPMs yet.
# Tests currently fail on UEK-next. Uncomment this to enable the tests:
# TestKernel(
# 9,
# "next",
# "x86_64",
# [
# "kernel-ueknext-core",
# "kernel-ueknext-modules",
# "kernel-ueknext-modules-core",
# ],
# yum_fmt=(
# "https://yum.oracle.com/repo/OracleLinux/OL{ol_ver}/"
# "developer/UEK{uek_ver}/{arch}/"
# ),
# pkgbase="kernel-ueknext",
# ),
# UEK7 switches from a single "kernel-uek" to "-core" and "-modules".
# The "kernel-uek" package still exists as a placeholder.
TestKernel(9, 7, "x86_64", ["kernel-uek-core", "kernel-uek-modules"]),
Expand Down
Loading