From 6fca21f7e28aa4621702700a235836f5ff681f7f Mon Sep 17 00:00:00 2001 From: Jordan Bonser Date: Fri, 28 Mar 2025 09:44:34 +0000 Subject: [PATCH 1/3] refactor: move base manager to manager folder the base context manager for the executor was confusingly named executor, this commit moves that to the `manager` folder in preparation to add new managers. BREAKING CHANGE: manager moved and renamed from executor to manager --- bazel/labgrid/{executor => manager}/BUILD.bazel | 7 +++++-- bazel/labgrid/manager/__init__.py | 3 +++ bazel/labgrid/{executor => manager}/manager.py | 0 labgrid/executor/BUILD.bazel | 4 ++-- labgrid/executor/executor.py | 2 +- labgrid/executor/host.py | 3 +-- 6 files changed, 12 insertions(+), 7 deletions(-) rename bazel/labgrid/{executor => manager}/BUILD.bazel (55%) create mode 100644 bazel/labgrid/manager/__init__.py rename bazel/labgrid/{executor => manager}/manager.py (100%) diff --git a/bazel/labgrid/executor/BUILD.bazel b/bazel/labgrid/manager/BUILD.bazel similarity index 55% rename from bazel/labgrid/executor/BUILD.bazel rename to bazel/labgrid/manager/BUILD.bazel index 5034f980..1f96682c 100644 --- a/bazel/labgrid/executor/BUILD.bazel +++ b/bazel/labgrid/manager/BUILD.bazel @@ -1,7 +1,10 @@ load("@rules_python//python:defs.bzl", "py_library") py_library( - name = "executor", - srcs = ["manager.py"], + name = "manager", + srcs = [ + "__init__.py", + "manager.py", + ], visibility = ["//visibility:public"], ) diff --git a/bazel/labgrid/manager/__init__.py b/bazel/labgrid/manager/__init__.py new file mode 100644 index 00000000..3ada4411 --- /dev/null +++ b/bazel/labgrid/manager/__init__.py @@ -0,0 +1,3 @@ +from .manager import Manager, Data + +__all__ = ["Manager", "Data"] diff --git a/bazel/labgrid/executor/manager.py b/bazel/labgrid/manager/manager.py similarity index 100% rename from bazel/labgrid/executor/manager.py rename to bazel/labgrid/manager/manager.py diff --git a/labgrid/executor/BUILD.bazel b/labgrid/executor/BUILD.bazel index 1effed64..ba4b4420 100644 --- a/labgrid/executor/BUILD.bazel +++ b/labgrid/executor/BUILD.bazel @@ -17,7 +17,7 @@ py_binary( tags = ["manual"], visibility = ["//:__subpackages__"], deps = [ - "//bazel/labgrid/executor", + "//bazel/labgrid/manager", "//bazel/python/runfiles", "//labgrid/config:managers", ], @@ -28,7 +28,7 @@ py_library( srcs = ["host.py"], data = ["hello-world.txt"], deps = [ - "//bazel/labgrid/executor", + "//bazel/labgrid/manager", "//bazel/python/runfiles", ], ) diff --git a/labgrid/executor/executor.py b/labgrid/executor/executor.py index 467d9027..a614e623 100644 --- a/labgrid/executor/executor.py +++ b/labgrid/executor/executor.py @@ -12,7 +12,7 @@ from shutil import which from subprocess import CalledProcessError, run from sys import argv -from bazel.labgrid.executor.manager import Data, Manager +from bazel.labgrid.manager import Data, Manager from bazel.python.runfiles import runfile, RunfileNotFoundError diff --git a/labgrid/executor/host.py b/labgrid/executor/host.py index 0b3b913b..54e044cc 100644 --- a/labgrid/executor/host.py +++ b/labgrid/executor/host.py @@ -3,8 +3,7 @@ from __future__ import annotations from contextlib import contextmanager from typing import Iterator - -from bazel.labgrid.executor.manager import Data +from bazel.labgrid.manager import Data from bazel.python.runfiles import runfile -- GitLab From b6aca5b22f83425b248ebe7fc14b3daf2d8fa2dc Mon Sep 17 00:00:00 2001 From: Jordan Bonser Date: Fri, 28 Mar 2025 09:57:44 +0000 Subject: [PATCH 2/3] refactor: make labgrid_client more generic allowing its use with the upcoming reserve and acquire managers. it provides some default error handling and options to handle yaml or str output. --- bazel/labgrid/client/common.py | 39 +++++++++++++++++++++------------- 1 file changed, 24 insertions(+), 15 deletions(-) diff --git a/bazel/labgrid/client/common.py b/bazel/labgrid/client/common.py index e5e4b707..f8d9c502 100644 --- a/bazel/labgrid/client/common.py +++ b/bazel/labgrid/client/common.py @@ -1,29 +1,38 @@ import yaml -from subprocess import run, PIPE +from sys import stderr, stdout +from subprocess import run, TimeoutExpired, CalledProcessError from python.runfiles import Runfiles -def labgrid_client(*args, **kwargs): - env = None +def labgrid_client(*args, env=None, timeout=10, output_as_yaml=True, url=""): url_params = () - timeout = None runfiles = Runfiles.Create() labgrid_client_path = runfiles.Rlocation("rules_labgrid/labgrid/client/client") - if "env" in kwargs: - env = kwargs["env"] - if "url" in kwargs: - url_params = ("-x", kwargs["url"]) - if "timeout" in kwargs: - timeout = kwargs["timeout"] + # TODO: look at removing the url parameter and have the user specify it either + # via LG_COORDINATOR env var or by adding `-x ` to the call themselves. + if url: + url_params = ("-x", url) cmd = (labgrid_client_path,) + url_params + args - process = run( - cmd, check=True, stdout=PIPE, env=env, timeout=timeout, encoding="utf-8" - ) + try: + process = run( + cmd, + check=True, + capture_output=True, + env=env, + timeout=timeout, + encoding="utf-8", + ) + except (CalledProcessError, TimeoutExpired) as e: + stderr.write(e.output) + raise if process.stdout: - return yaml.safe_load(process.stdout) + stdout.write(process.stdout) + if output_as_yaml: + return yaml.safe_load(process.stdout) + return process.stdout else: - return [] + return {} -- GitLab From 582e87e03deea8359655cb93a1a02676b5ffa678 Mon Sep 17 00:00:00 2001 From: Jordan Bonser Date: Fri, 28 Mar 2025 10:01:08 +0000 Subject: [PATCH 3/3] feat: add new acquire and reserve managers These two managers can be passed to a `labgrid_config_toolchain` to allow the toolchain to use Labgrid's reserve and acquire functionality to gain allocation of a place before running the test binary, then finally releasing it once the test has completed. --- bazel/labgrid/manager/BUILD.bazel | 34 +++++++++++++++++++++++++++++ bazel/labgrid/manager/acquire.py | 17 +++++++++++++++ bazel/labgrid/manager/reserve.py | 36 +++++++++++++++++++++++++++++++ 3 files changed, 87 insertions(+) create mode 100644 bazel/labgrid/manager/acquire.py create mode 100644 bazel/labgrid/manager/reserve.py diff --git a/bazel/labgrid/manager/BUILD.bazel b/bazel/labgrid/manager/BUILD.bazel index 1f96682c..7b66fd30 100644 --- a/bazel/labgrid/manager/BUILD.bazel +++ b/bazel/labgrid/manager/BUILD.bazel @@ -8,3 +8,37 @@ py_library( ], visibility = ["//visibility:public"], ) + +py_library( + name = "acquire", + srcs = [ + "acquire.py", + ], + data = [ + "//labgrid/client", + ], + visibility = ["//visibility:public"], + deps = [ + ":manager", + "//bazel/labgrid/client", + "//labgrid:pkg", + "@rules_python//python/runfiles", + ], +) + +py_library( + name = "reserve", + srcs = [ + "reserve.py", + ], + data = [ + "//labgrid/client", + ], + visibility = ["//visibility:public"], + deps = [ + ":manager", + "//bazel/labgrid/client", + "//labgrid:pkg", + "@rules_python//python/runfiles", + ], +) diff --git a/bazel/labgrid/manager/acquire.py b/bazel/labgrid/manager/acquire.py new file mode 100644 index 00000000..bb4f79ae --- /dev/null +++ b/bazel/labgrid/manager/acquire.py @@ -0,0 +1,17 @@ +from __future__ import annotations +from contextlib import contextmanager +from typing import Iterator + +from bazel.labgrid.manager.manager import Data +from bazel.labgrid.client import labgrid_client + + +@contextmanager +def manager(input_data: Data) -> Iterator[Data]: + env = input_data.env + labgrid_client("acquire", env=env) + + try: + yield Data(env=env) + finally: + labgrid_client("release", env=env) diff --git a/bazel/labgrid/manager/reserve.py b/bazel/labgrid/manager/reserve.py new file mode 100644 index 00000000..c35d7fbf --- /dev/null +++ b/bazel/labgrid/manager/reserve.py @@ -0,0 +1,36 @@ +from __future__ import annotations +from contextlib import contextmanager +from typing import Iterator + +from bazel.labgrid.manager.manager import Data +from bazel.labgrid.client import labgrid_client + + +@contextmanager +def manager(input_data: Data) -> Iterator[Data]: + env = input_data.env + tags = env.get("BZL_LG_TAGS", "") + token = "" + + if tags: + # Reserve and get token + result = labgrid_client("reserve", tags, env=env) + token = list(result.values())[0].get("token") + + # Wait for allocation + reserve_timeout = env.get("BZL_LG_RESERVE_TIMEOUT", 60) + result = labgrid_client("wait", token, env=env, timeout=reserve_timeout) + place = result.get("allocations", {}).get("main", "+") + + env.update( + { + "LG_TOKEN": token, + "LG_PLACE": place, + } + ) + + try: + yield Data(env=env) + finally: + if token: + labgrid_client("cancel-reservation", token, env=env) -- GitLab