Skip to content

Commit 313c2f7

Browse files
authored
Merge branch 'master' into util/processwrapper
2 parents f527ac8 + 9280f5f commit 313c2f7

13 files changed

Lines changed: 108 additions & 70 deletions

File tree

contrib/systemd/labgrid-exporter.service

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ EnvironmentFile=-/etc/environment
1111
ExecStart=/path/to/labgrid/venv/bin/labgrid-exporter /etc/labgrid/exporter.yaml
1212
Restart=always
1313
RestartSec=30
14+
# Replace 'DynamicUser=yes' with 'User=labgrid' and 'Group=labgrid' when using labgrid helpers with sudo.
1415
DynamicUser=yes
1516
# Adjust to your distribution (most often "dialout" or "tty")
1617
SupplementaryGroups=dialout plugdev

doc/conf.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,7 @@ def setup(app):
223223
# Make version and date stable when generating manpages as they will be tracked in git
224224
if app.outdir.parts[-1] == "man":
225225
app.config.version = ""
226-
app.config.today_fmt = "%Y"
226+
app.config.today = "2025"
227227
app.connect('builder-inited', run_apidoc)
228228
app.connect('doctree-read', write_literal_blocks)
229229

doc/configuration.rst

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3995,12 +3995,32 @@ something like ``{{ env['FOOBAR'] }}`` to insert the content of environment
39953995
variable ``FOOBAR``.
39963996
In addition to ``env`` the template also has access to the following variables:
39973997

3998-
isolated
3999-
``True`` or ``False``, depending on the :code:`--isolated` command line option.
3998+
drop_ins
3999+
An alphabetically sorted list of files in a directory named after the
4000+
currently processed template with ".d" appended. For example if the template
4001+
is named ``/etc/labgrid/configuration.yaml`` the list will contain files
4002+
matching ``/etc/labgrid/configuration.yaml.d/*.yaml`` pattern. The paths are
4003+
relative to the directory containing the template (i.e. ``/etc/labgrid``
4004+
in our example). These files can be included using the ``include`` directive.
4005+
A template loading all its drop-ins at would look like this
4006+
4007+
.. code-block::
4008+
4009+
# for f in drop_ins
4010+
{% include f %}
4011+
# endfor
4012+
4013+
.. warning::
4014+
Use the ``{% include f %}`` form instead of ``# include f``, otherwise
4015+
Jinja2 would strip newline characters before concatenation, and thus break
4016+
the YAML formatting.
40004017

40014018
hostname
40024019
The hostname of the exporter host. Can be used to e.g. construct URLs to the
40034020
current host (``http://{{ hostname }}/``).
40044021

4022+
isolated
4023+
``True`` or ``False``, depending on the :code:`--isolated` command line option.
4024+
40054025
name
40064026
The name of the exporter.

doc/getting_started.rst

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -379,6 +379,15 @@ Follow these instructions to install the systemd files on your machine(s):
379379
installation paths of your distribution.
380380
#. Adapt the ``ExecStart`` paths of the service files to the respective Python
381381
virtual environments of the coordinator and exporter.
382+
#. If you use labgrid helpers (see :file:`helpers/`) with sudo on exporter,
383+
replace ``DynamicUser`` with ``User`` and ``Group`` in the
384+
:file:`labgrid-exporter.service`:
385+
386+
.. code-block::
387+
388+
User=labgrid
389+
Group=labgrid
390+
382391
#. Adjust the ``SupplementaryGroups`` option in the
383392
:file:`labgrid-exporter.service` file to your distribution so that the
384393
exporter gains read and write access on TTY devices (for ``ser2net``); most

dockerfiles/Dockerfile

Lines changed: 14 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,29 @@
1-
FROM debian:bookworm-slim AS labgrid-base
2-
ARG VERSION
1+
FROM debian:trixie-slim AS labgrid-base
2+
ARG VERSION=0.0.0
33

44
LABEL maintainer="eha@deif.com"
55

66
ENV DEBIAN_FRONTEND=noninteractive
77

88
COPY ./ /opt/labgrid/
99

10-
RUN set -e ;\
11-
apt update -q=2 ;\
12-
apt install -q=2 --yes --no-install-recommends python3 python3-dev python3-pip python3-setuptools git build-essential ;\
13-
pip3 install --break-system-packages -U pip;\
14-
apt clean ;\
15-
rm -rf /var/lib/apt/lists/* ;\
16-
cd /opt/labgrid ;\
17-
SETUPTOOLS_SCM_PRETEND_VERSION="$VERSION" pip3 install --break-system-packages --no-cache-dir .
10+
RUN apt update -q=2 && \
11+
apt install -q=2 --yes --no-install-recommends python3 python3-dev python3-pip python3-setuptools git build-essential && \
12+
rm -rf /var/lib/apt/lists/* && \
13+
pip3 config --site set global.break-system-packages true && \
14+
pip3 config --site set global.root-user-action ignore && \
15+
cd /opt/labgrid && \
16+
SETUPTOOLS_SCM_PRETEND_VERSION="$VERSION" pip3 install --no-cache-dir .
1817

1918
#
2019
# Client
2120
#
2221
FROM labgrid-base AS labgrid-client
2322
ARG VERSION
2423

25-
RUN set -e ;\
26-
pip3 install --break-system-packages yq ;\
27-
apt update -q=2 ;\
28-
apt install -q=2 --yes --no-install-recommends microcom openssh-client rsync jq qemu-system qemu-utils ;\
29-
apt clean ;\
24+
RUN pip3 install yq && \
25+
apt update -q=2 && \
26+
apt install -q=2 --yes --no-install-recommends microcom openssh-client rsync jq qemu-system qemu-utils && \
3027
rm -rf /var/lib/apt/lists/*
3128

3229
CMD ["/bin/bash"]
@@ -53,10 +50,8 @@ ARG VERSION
5350

5451
COPY dockerfiles/exporter/entrypoint.sh /entrypoint.sh
5552

56-
RUN set -e ;\
57-
apt update -q=2 ;\
58-
apt install -q=2 --yes --no-install-recommends ser2net ;\
59-
apt clean ;\
53+
RUN apt update -q=2 && \
54+
apt install -q=2 --yes --no-install-recommends ser2net && \
6055
rm -rf /var/lib/apt/lists/*
6156

6257
VOLUME /opt/conf

dockerfiles/staging/dut/Dockerfile

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,14 @@
1-
FROM debian:bookworm-slim
1+
FROM debian:trixie-slim
22

33
LABEL org.opencontainers.image.authors="mail@krevsbech.dk"
44

55
ENV DEBIAN_FRONTEND=noninteractive
66

7-
RUN set -e ;\
8-
apt update -q=2 ;\
9-
apt install -q=2 --yes --no-install-recommends openssh-server;\
10-
apt clean ;\
11-
rm -rf /var/lib/apt/lists/* ;\
12-
mkdir /var/run/sshd ;\
13-
echo 'root:PASSWORD' | chpasswd ;\
14-
echo 'PermitRootLogin yes' >> /etc/ssh/sshd_config ;\
7+
RUN apt update -q=2 && \
8+
apt install -q=2 --yes --no-install-recommends openssh-server && \
9+
rm -rf /var/lib/apt/lists/* && \
10+
echo 'root:PASSWORD' | chpasswd && \
11+
echo 'PermitRootLogin yes' >> /etc/ssh/sshd_config && \
1512
sed 's@session\s*required\s*pam_loginuid.so@session optional pam_loginuid.so@g' -i /etc/pam.d/sshd
1613
# SSH login fix. Otherwise user is kicked off after login
1714

helpers/labgrid-bound-connect

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#!/usr/bin/python3
1+
#!/usr/bin/python3
22

33
# This is intended to be used via sudo. For example, add via visudo:
44
# %developers ALL = NOPASSWD: /usr/local/sbin/labgrid-bound-connect
@@ -15,7 +15,7 @@ def main(ifname, address, port):
1515
raise ValueError("Empty interface name.")
1616
if any((c == "/" or c.isspace()) for c in ifname):
1717
raise ValueError(f"Interface name '{ifname}' contains invalid characters.")
18-
if len(ifname) > 16:
18+
if len(ifname) > 15:
1919
raise ValueError(f"Interface name '{ifname}' is too long.")
2020

2121
address = ipaddress.ip_address(address)
@@ -36,7 +36,7 @@ def main(ifname, address, port):
3636
raise RuntimeError(f"Invalid IP version '{address.version}'")
3737

3838
# Delete the IP lookup cache for the address in case it is stale
39-
subprocess.run(["ip", "neigh", "del", str(address), "dev", ifname],
39+
subprocess.run(["ip", "neigh", "del", str(address), "dev", ifname],
4040
stdout=subprocess.DEVNULL,
4141
stderr=subprocess.DEVNULL
4242
)
@@ -78,4 +78,3 @@ if __name__ == "__main__":
7878
import traceback
7979
traceback.print_exc()
8080
print(f"ERROR: {e}", file=sys.stderr)
81-

helpers/labgrid-raw-interface

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ def main(program, options):
3838
raise ValueError("Empty interface name.")
3939
if any((c == "/" or c.isspace()) for c in options.ifname):
4040
raise ValueError(f"Interface name '{options.ifname}' contains invalid characters.")
41-
if len(options.ifname) > 16:
41+
if len(options.ifname) > 15:
4242
raise ValueError(f"Interface name '{options.ifname}' is too long.")
4343

4444
denylist = get_denylist()

labgrid/remote/client.py

Lines changed: 10 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,9 @@ class ServerError(Error):
7373

7474

7575
class InteractiveCommandError(Error):
76-
pass
76+
def __init__(self: Error, msg: str, exitcode: int):
77+
super(InteractiveCommandError, self).__init__(msg)
78+
self.exitcode = exitcode
7779

7880

7981
class ErrorGroup(ExceptionGroup):
@@ -1099,9 +1101,7 @@ async def console(self, place, target):
10991101
break
11001102
if not self.args.loop:
11011103
if res:
1102-
exc = InteractiveCommandError("microcom error")
1103-
exc.exitcode = res
1104-
raise exc
1104+
raise InteractiveCommandError("microcom error", res)
11051105
break
11061106
await asyncio.sleep(1.0)
11071107

@@ -1301,27 +1301,21 @@ def ssh(self):
13011301

13021302
res = drv.interact(self.args.leftover)
13031303
if res:
1304-
exc = InteractiveCommandError("ssh error")
1305-
exc.exitcode = res
1306-
raise exc
1304+
raise InteractiveCommandError("ssh error", res)
13071305

13081306
def scp(self):
13091307
drv = self._get_ssh()
13101308

13111309
res = drv.scp(src=self.args.src, dst=self.args.dst)
13121310
if res:
1313-
exc = InteractiveCommandError("scp error")
1314-
exc.exitcode = res
1315-
raise exc
1311+
raise InteractiveCommandError("scp error", res)
13161312

13171313
def rsync(self):
13181314
drv = self._get_ssh()
13191315

13201316
res = drv.rsync(src=self.args.src, dst=self.args.dst, extra=self.args.leftover)
13211317
if res:
1322-
exc = InteractiveCommandError("rsync error")
1323-
exc.exitcode = res
1324-
raise exc
1318+
raise InteractiveCommandError("rsync error", res)
13251319

13261320
def sshfs(self):
13271321
drv = self._get_ssh()
@@ -1359,9 +1353,7 @@ def telnet(self):
13591353
args = ["telnet", str(ip)]
13601354
res = subprocess.call(args)
13611355
if res:
1362-
exc = InteractiveCommandError("telnet error")
1363-
exc.exitcode = res
1364-
raise exc
1356+
raise InteractiveCommandError("telnet error", res)
13651357

13661358
def video(self):
13671359
place = self.get_acquired_place()
@@ -1397,9 +1389,7 @@ def video(self):
13971389
else:
13981390
res = drv.stream(quality, controls=controls)
13991391
if res:
1400-
exc = InteractiveCommandError("gst-launch-1.0 error")
1401-
exc.exitcode = res
1402-
raise exc
1392+
raise InteractiveCommandError("gst-launch-1.0 error", res)
14031393

14041394
def audio(self):
14051395
place = self.get_acquired_place()
@@ -1408,9 +1398,7 @@ def audio(self):
14081398
drv = self._get_driver_or_new(target, "USBAudioInputDriver", name=name)
14091399
res = drv.play()
14101400
if res:
1411-
exc = InteractiveCommandError("gst-launch-1.0 error")
1412-
exc.exitcode = res
1413-
raise exc
1401+
raise InteractiveCommandError("gst-launch-1.0 error", res)
14141402

14151403
def _get_tmc(self):
14161404
place = self.get_acquired_place()

labgrid/remote/config.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from pprint import pprint
22

3+
import glob
34
import os
45

56
import attr
@@ -15,15 +16,21 @@ class ResourceConfig:
1516
template_env = attr.ib(default=attr.Factory(dict), validator=attr.validators.instance_of(dict))
1617

1718
def __attrs_post_init__(self):
19+
_dirname = os.path.dirname(self.filename)
1820
env = jinja2.Environment(
19-
loader=jinja2.FileSystemLoader(os.path.dirname(self.filename)),
21+
loader=jinja2.FileSystemLoader(_dirname),
2022
line_statement_prefix="#",
2123
line_comment_prefix="##",
2224
)
2325
try:
2426
template = env.get_template(os.path.basename(self.filename))
2527
except jinja2.TemplateNotFound:
2628
raise NoConfigFoundError(f"{self.filename} could not be found")
29+
drop_ins = [
30+
os.path.relpath(p, _dirname) for p in sorted(glob.glob(os.path.join(self.filename + ".d", "*.yaml")))
31+
]
32+
33+
self.template_env["drop_ins"] = drop_ins
2734
rendered = template.render(self.template_env)
2835
pprint(("rendered", rendered))
2936
self.data = load(rendered)

0 commit comments

Comments
 (0)