osmith has uploaded this change for review. ( https://gerrit.osmocom.org/c/osmo-ttcn3-hacks/+/41152?usp=email )
Change subject: testenv: coredump: support core_pattern=core ......................................................................
testenv: coredump: support core_pattern=core
Support getting core files from a typical core_pattern=core where the coredump just gets stored in the current working dir, instead of always retrieving it from coredumpctl. This is what we will use with jenkins in the future, as it makes getting core files in other jobs easier. Remove support for the custom testenv-coredump-helper code that isn't needed anymore.
Change-Id: Ia765b01432e4cb4cd36c45de874b966e3ebf55bc --- M _testenv/testenv/coredump.py M _testenv/testenv/daemons.py M _testenv/testenv/requirements.py 3 files changed, 46 insertions(+), 56 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/osmo-ttcn3-hacks refs/changes/52/41152/1
diff --git a/_testenv/testenv/coredump.py b/_testenv/testenv/coredump.py index 0343c67..d3fa35f 100644 --- a/_testenv/testenv/coredump.py +++ b/_testenv/testenv/coredump.py @@ -2,63 +2,20 @@ # SPDX-License-Identifier: GPL-3.0-or-later import datetime import fnmatch +import glob import json import logging -import os +import re import shlex import shutil import subprocess import testenv import testenv.daemons import testenv.testdir -import urllib -import urllib.request
+core_path = None executable_path = None
-lxc_netdev = "eth0" -lxc_ip_pattern = "10.0.*" -lxc_port = 8042 - - -def find_lxc_host_ip(): - cmd = ["ip", "-j", "-o", "-4", "addr", "show", "dev", lxc_netdev] - p = testenv.cmd.run(cmd, check=False, no_podman=True, capture_output=True, text=True) - ret = json.loads(p.stdout)[0]["addr_info"][0]["local"] - if fnmatch.fnmatch(ret, lxc_ip_pattern): - ret = ret.split(".") - ret = f"{ret[0]}.{ret[1]}.{ret[2]}.1" - return ret - return None - - -def get_from_coredumpctl_lxc_host(): - # Server implementation: osmo-ci, ansible/roles/testenv-coredump-helper - global executable_path - - logging.info("Looking for a coredump on lxc host") - - ip = os.environ.get("TESTENV_COREDUMP_FROM_LXC_HOST_IP") or find_lxc_host_ip() - if not ip: - logging.warning("Failed to get lxc host ip, can't look for coredump") - return - - try: - with urllib.request.urlopen(f"http://%7Bip%7D:%7Blxc_port%7D/core") as response: - executable_path = dict(response.getheaders())["X-Executable-Path"] - with open(f"{testenv.testdir.testdir}/core", "wb") as h: - shutil.copyfileobj(response, h) - logging.debug("Coredump found and copied to log dir") - except urllib.error.HTTPError as e: - executable_path = None - if e.code == 404: - logging.debug("No coredump found") - else: - logging.error(f"Unexpected error while attempting to fetch the coredump: {e}") - except urllib.error.URLError as e: - executable_path = None - logging.error(f"Unexpected error while attempting to fetch the coredump: {e}") -
def executable_is_relevant(exe): if testenv.args.binary_repo: @@ -77,10 +34,11 @@ return False
-def get_from_coredumpctl_local(): +def get_from_coredumpctl(): + global core_path global executable_path
- logging.info("Looking for a coredump") + logging.info("Looking for a coredump with coredumpctl")
if not shutil.which("coredumpctl"): logging.debug("coredumpctl is not available, won't try to get coredump") @@ -113,18 +71,49 @@ executable_path = coredump["exe"]
-def get_from_coredumpctl(): - if os.environ.get("TESTENV_COREDUMP_FROM_LXC_HOST"): - get_from_coredumpctl_lxc_host() +def get_from_file(): + global core_path + global executable_path + + logging.info("Looking for a coredump file") + + glob_matches = glob.glob(f"{testenv.testdir.testdir}/*/core*") + if not glob_matches: + return + + core_path = glob_matches[0] + p = testenv.cmd.run( + ["file", core_path], + no_podman=True, + capture_output=True, + text=True, + ) + print(p.stdout, end="") + + execfn_match = re.search(r"execfn: '(.*?)'", p.stdout) + if execfn_match: + executable_path = execfn_match.group(1) + logging.debug("Coredump file and execfn found") else: - get_from_coredumpctl_local() + logging.debug("Failed to get execfn path from coredump file") + + +def get_coredump(): + with open("/proc/sys/kernel/core_pattern") as f: + pattern = f.readline().rstrip() + + if "systemd-coredump" in pattern: + get_from_coredumpctl() + elif pattern.startswith("core"): + get_from_file() + else: + logging.debug(f"Unsupported core_pattern, won't try to get coredump: {pattern}")
def get_backtrace(): global executable_path
- core_path = f"{testenv.testdir.testdir}/core" - if not executable_path or not os.path.exists(core_path): + if not executable_path or not core_path: return
logging.info("Running gdb to get a backtrace") diff --git a/_testenv/testenv/daemons.py b/_testenv/testenv/daemons.py index 3a38850..f57b4b4 100644 --- a/_testenv/testenv/daemons.py +++ b/_testenv/testenv/daemons.py @@ -68,7 +68,7 @@ # Wait 200ms and check if it is still running time.sleep(0.2) if daemons[section].poll() is not None: - testenv.coredump.get_from_coredumpctl() + testenv.coredump.get_coredump() raise testenv.NoTraceException(f"program failed to start: {program}")
# Run setup script @@ -118,7 +118,7 @@ return
current_test = testenv.testsuite.get_current_test() - testenv.coredump.get_from_coredumpctl() + testenv.coredump.get_coredump()
if current_test: logging.error(f"{daemon_name} unexpected exit during {current_test}! rc={returncode}") diff --git a/_testenv/testenv/requirements.py b/_testenv/testenv/requirements.py index 97fae0c..2e53081 100644 --- a/_testenv/testenv/requirements.py +++ b/_testenv/testenv/requirements.py @@ -11,6 +11,7 @@
def check_programs(): programs = [ + "file", "git", ]