This is an automated email from the ASF dual-hosted git repository. tvb pushed a commit to branch tristan/assert-buildbox-casd-version in repository https://gitbox.apache.org/repos/asf/buildstream.git
commit 9ccb9b70e5b01a831e2deaf0bbb815bea284c866 Author: Tristan van Berkom <[email protected]> AuthorDate: Sun Jul 3 19:06:27 2022 +0900 _cas/casdprocessmanager.py: Assert minimal required version of buildbox-casd Here we pass along the Messenger object to the casdprocessmanager so that we can issue a warning on startup in the case that we are unable to properly determine the installed buildbox-casd version. An error is raised if we successfully identify the installed version and it is less than the required version. Fixes #1189 --- src/buildstream/_cas/cascache.py | 5 ++- src/buildstream/_cas/casdprocessmanager.py | 70 +++++++++++++++++++++++++++++- src/buildstream/_context.py | 1 + 3 files changed, 73 insertions(+), 3 deletions(-) diff --git a/src/buildstream/_cas/cascache.py b/src/buildstream/_cas/cascache.py index c6a58098f..eb3cc9161 100644 --- a/src/buildstream/_cas/cascache.py +++ b/src/buildstream/_cas/cascache.py @@ -71,7 +71,8 @@ class CASCache: remote_cache_spec=None, protect_session_blobs=True, log_level=CASLogLevel.WARNING, - log_directory=None + log_directory=None, + messenger=None ): self.casdir = os.path.join(path, "cas") self.tmpdir = os.path.join(path, "tmp") @@ -88,7 +89,7 @@ class CASCache: assert log_directory is not None, "log_directory is required when casd is True" log_dir = os.path.join(log_directory, "_casd") self._casd_process_manager = CASDProcessManager( - path, log_dir, log_level, cache_quota, remote_cache_spec, protect_session_blobs + path, log_dir, log_level, cache_quota, remote_cache_spec, protect_session_blobs, messenger ) self._casd_channel = self._casd_process_manager.create_channel() diff --git a/src/buildstream/_cas/casdprocessmanager.py b/src/buildstream/_cas/casdprocessmanager.py index 34f830483..3c003d0b1 100644 --- a/src/buildstream/_cas/casdprocessmanager.py +++ b/src/buildstream/_cas/casdprocessmanager.py @@ -18,6 +18,7 @@ import contextlib import threading import os +import re import random import shutil import stat @@ -25,6 +26,7 @@ import subprocess import tempfile import time import psutil +from subprocess import CalledProcessError import grpc @@ -40,6 +42,14 @@ _CASD_MAX_LOGFILES = 10 _CASD_TIMEOUT = 300 # in seconds +# +# Minimum required version of buildbox-casd +# +_REQUIRED_CASD_MAJOR = 0 +_REQUIRED_CASD_MINOR = 0 +_REQUIRED_CASD_MICRO = 58 + + # CASDProcessManager # # This manages the subprocess that runs buildbox-casd. @@ -51,14 +61,18 @@ _CASD_TIMEOUT = 300 # in seconds # cache_quota (int): User configured cache quota # remote_cache_spec (RemoteSpec): Optional remote cache server # protect_session_blobs (bool): Disable expiry for blobs used in the current session +# messenger (Messenger): The messenger to report warnings through the UI # class CASDProcessManager: - def __init__(self, path, log_dir, log_level, cache_quota, remote_cache_spec, protect_session_blobs): + def __init__(self, path, log_dir, log_level, cache_quota, remote_cache_spec, protect_session_blobs, messenger): self._log_dir = log_dir self._socket_path = self._make_socket_path(path) self._connection_string = "unix:" + self._socket_path + # Early version check + self._check_casd_version(messenger) + casd_args = [utils.get_host_tool("buildbox-casd")] casd_args.append("--bind=" + self._connection_string) casd_args.append("--log-level=" + log_level.value) @@ -92,6 +106,60 @@ class CASDProcessManager: casd_args, cwd=path, stdout=logfile_fp, stderr=subprocess.STDOUT, preexec_fn=os.setpgrp ) + # _check_casd_version() + # + # Check for minimal acceptable version of buildbox-casd. + # + # If the version is unacceptable, then an error is raised. + # + # If buildbox-casd was built without version information available (or has reported + # version information with a string which we are unprepared to parse), then + # a warning is produced to inform the user. + # + def _check_casd_version(self, messenger): + # + # We specify a trailing "path" argument because some versions of buildbox-casd + # require specifying the storage path even for invoking the --version option. + # + casd_args = [utils.get_host_tool("buildbox-casd")] + casd_args.append("--version") + casd_args.append("/") + + try: + version_output = subprocess.check_output(casd_args) + except CalledProcessError as e: + raise CASCacheError("Error checking buildbox-casd version") from e + + version_output = version_output.decode("utf-8") + version_match = re.match(r".*buildbox-casd (\d+).(\d+).(\d+).*", version_output) + + if version_match: + version_major = int(version_match.group(1)) + version_minor = int(version_match.group(2)) + version_micro = int(version_match.group(3)) + + acceptable_version = True + if version_major < _REQUIRED_CASD_MAJOR: + acceptable_version = False + elif version_major == _REQUIRED_CASD_MAJOR: + if version_minor < _REQUIRED_CASD_MINOR: + acceptable_version = False + elif version_minor == _REQUIRED_CASD_MINOR: + if version_micro < _REQUIRED_CASD_MICRO: + acceptable_version = False + + if not acceptable_version: + raise CASCacheError( + "BuildStream requires buildbox-casd >= {}.{}.{}".format( + _REQUIRED_CASD_MAJOR, _REQUIRED_CASD_MINOR, _REQUIRED_CASD_MICRO + ), + detail="Currently installed: {}".format(version_output), + ) + elif messenger: + messenger.warn( + "Unable to determine buildbox-casd version", detail="buildbox-casd reported: {}".format(version_output) + ) + # _make_socket_path() # # Create a path to the CASD socket, ensuring that we don't exceed diff --git a/src/buildstream/_context.py b/src/buildstream/_context.py index dfe369479..ecca27c10 100644 --- a/src/buildstream/_context.py +++ b/src/buildstream/_context.py @@ -688,6 +688,7 @@ class Context: remote_cache_spec=self.remote_cache_spec, log_level=log_level, log_directory=self.logdir, + messenger=self.messenger, ) return self._cascache
