Skip to content

Commit

Permalink
Merge pull request #1469 from labgrid-project/grpc
Browse files Browse the repository at this point in the history
Move from crossbar/autobahn to gRPC
  • Loading branch information
Emantor authored Aug 16, 2024
2 parents f472ae7 + ab8f79a commit 1ab0abd
Show file tree
Hide file tree
Showing 67 changed files with 3,900 additions and 1,267 deletions.
3 changes: 0 additions & 3 deletions .crossbar/.gitignore

This file was deleted.

47 changes: 0 additions & 47 deletions .crossbar/config-anonymous.yaml

This file was deleted.

9 changes: 3 additions & 6 deletions .github/workflows/reusable-unit-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ jobs:
${{ runner.os }}-pip-
- name: Install system dependencies
run: |
sudo apt-get install -yq libow-dev openssh-server openssh-client libsnappy-dev graphviz openocd
sudo apt-get install -yq libow-dev openssh-server openssh-client graphviz openocd
sudo mkdir -p /var/cache/labgrid/runner && sudo chown runner /var/cache/labgrid/runner
- name: Prepare local SSH
run: |
Expand All @@ -46,17 +46,14 @@ jobs:
- name: Install labgrid
run: |
pip install -e ".[dev]"
- name: Install crossbar in virtualenv
run: |
virtualenv -p python3 crossbar-venv
crossbar-venv/bin/pip install -r crossbar-requirements.txt
- name: Lint with pylint
if: inputs.python-version != '3.8'
run: |
pylint --list-msgs-enabled
pylint labgrid
- name: Test with pytest
run: |
pytest --cov-config .coveragerc --cov=labgrid --local-sshmanager --ssh-username runner --crossbar-venv crossbar-venv -k "not test_docker_with_daemon"
pytest --cov-config .coveragerc --cov=labgrid --local-sshmanager --ssh-username runner -k "not test_docker_with_daemon"
- name: Build documentation
run: |
make -C doc clean
Expand Down
4 changes: 2 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,6 @@
/.pytest_cache/
/htmlcov/
/labgrid/_version.py
/dockerfiles/staging/crossbar/*
!/dockerfiles/staging/crossbar/places_example.yaml
/dockerfiles/staging/coordinator/*
!/dockerfiles/staging/coordinator/places_example.yaml
/.idea
51 changes: 51 additions & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
@@ -1,3 +1,54 @@
Release 24.1 (Unreleased)
-------------------------
As announced
`before <https://github.com/labgrid-project/labgrid/discussions/1467#discussioncomment-10314852>`_,
this is the first release using gRPC instead of crossbar/autobahn for
communication between client/exporter and coordinator.

Crossbar/autobahn are unfortunately not very well maintained anymore. The
crossbar component was moved to its own virtualenv to cope with the high number
of dependencies leading to conflicts. Support for Python 3.13 is still not
available in a crossbar release on PyPI.

That's why labgrid moves to gRPC with this release. gRPC is a well maintained
RPC framework with a lot of users. As a side effect, the message transfer is
more performant and the import times are shorter.

New Features in 24.1
~~~~~~~~~~~~~~~~~~~~
- All components can be installed into the same virtualenv again.

Bug fixes in 24.1
~~~~~~~~~~~~~~~~~

FIXME

Breaking changes in 24.1
~~~~~~~~~~~~~~~~~~~~~~~~
Maintaining support for both crossbar/autobahn as well as gRPC in labgrid would
be a lot of effort due to the different architectures of those frameworks.
Therefore, a hard migration to gRPC is deemed the lesser issue.

Due to the migration, 24.1 includes the following breaking changes:

- The labgrid environment config option ``crossbar_url`` was renamed to
``coordinator_address``. The environment variable ``LG_CROSSBAR`` was renamed
to ``LG_COORDINATOR``.
- The labgrid environment config option ``crossbar_realm`` is now obsolete as
well as the environment variable ``LG_CROSSBAR_REALM``.
- The coordinator is available as ``labgrid-coordinator`` (instead of
``crossbar start``). No additional configuration file is required.
- The systemd services in ``contrib/systemd/`` were updated.

Other breaking changes include:

FIXME

Known issues in 24.1
~~~~~~~~~~~~~~~~~~~~

FIXME

Release 24.0 (Released Aug 12, 2024)
------------------------------------

Expand Down
6 changes: 3 additions & 3 deletions contrib/README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,14 @@ Quick Start
$ source venv/bin/activate
venv $ pip install -r contrib/requirements-webapp.txt
venv $ ./contrib/labgrid-webapp --help
usage: labgrid-webapp [-h] [--crossbar URL] [--port PORT] [--proxy PROXY]
usage: labgrid-webapp [-h] [--coordinator ADDRESS] [--port PORT] [--proxy PROXY]
Labgrid webapp
options:
-h, --help show this help message and exit
--crossbar URL, -x URL
Crossbar websocket URL (default: ws://127.0.0.1:20408/ws)
--coordinator ADDRESS, -x ADDRESS
Coordinator address as HOST[:PORT] (default: 127.0.0.1:20408)
--port PORT Port to serve on
--proxy PROXY, -P PROXY
Expand Down
6 changes: 3 additions & 3 deletions contrib/completion/labgrid-client.bash
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@

# options top level and subcommands support
_labgrid_shared_options="--help"
_labgrid_main_opts_with_value="@(-x|--crossbar|-c|--config|-p|--place|-s|--state|-i|--initial-state|-P|--proxy)"
_labgrid_main_opts_with_value="@(-x|--coordinator|-c|--config|-p|--place|-s|--state|-i|--initial-state|-P|--proxy)"

# Parses labgrid-client arguments
# Sets arg to subcommand, excluding options and their values.
# Sets last_arg_opt_with_value to true if the last argument is an option requiring a value, else
# false.
# Sets base_cmd to the labgrid-client base command up to subcommand and removes trailing
# option requiring a value - useful to call 'labgrid-client complete' with place/crossbar/proxy set
# option requiring a value - useful to call 'labgrid-client complete' with place/coordinator/proxy set
# Before calling this function, make sure arg, base_cmd and last_arg_opt_with_value are local
_labgrid_parse_args()
{
Expand Down Expand Up @@ -867,7 +867,7 @@ _labgrid_client()
case "$cur" in
--*)
# top level args completion
local options="--crossbar \
local options="--coordinator \
--config \
--place \
--state \
Expand Down
45 changes: 22 additions & 23 deletions contrib/coordinator-statsd.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,14 @@

import sys
import argparse
import statsd
import os
import labgrid.remote.client
import time
import asyncio
import txaio

from labgrid.remote.client import start_session, Error
from labgrid.remote.generated import labgrid_coordinator_pb2
from labgrid.remote.common import Reservation
import statsd


def inc_gauge(gauges, key):
Expand All @@ -56,12 +58,13 @@ def inc_gauge(gauges, key):


async def report_reservations(session, tags, gauges):
reservations = await session.call("org.labgrid.coordinator.get_reservations")
request = labgrid_coordinator_pb2.GetReservationsRequest()

for token, config in reservations.items():
state = config["state"]
response = await session.stub.GetReservations(request)
reservations = [Reservation.from_pb2(x) for x in response.reservations]

groups = config.get("filters", {})
for reservation in reservations:
groups = reservation.filters

if not groups:
groups = {"": {}}
Expand All @@ -72,7 +75,7 @@ async def report_reservations(session, tags, gauges):
".".join(
["reservations", group_name]
+ [group.get(t, "") for t in tags]
+ [state]
+ [reservation.state.name]
),
)

Expand All @@ -94,10 +97,10 @@ def main():
)
parser.add_argument(
"-x",
"--crossbar",
metavar="URL",
help="Crossbar URL for the coordinator",
default=os.environ.get("LG_CROSSBAR", "ws://127.0.0.1:20408/ws"),
"--coordinator",
metavar="ADDRESS",
help="Coordinator address as HOST[:PORT]. Default is %(default)s",
default=os.environ.get("LG_COORDINATOR", "127.0.0.1:20408"),
)
parser.add_argument(
"--period",
Expand Down Expand Up @@ -142,8 +145,8 @@ def main():

args = parser.parse_args()

txaio.use_asyncio()
txaio.config.loop = asyncio.get_event_loop()
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)

statsd_client = None
gauges = {}
Expand Down Expand Up @@ -175,22 +178,18 @@ def main():

next_time = time.monotonic() + args.period
try:
extra = {}
session = labgrid.remote.client.start_session(
args.crossbar,
os.environ.get("LG_CROSSBAR_REALM", "realm1"),
extra,
)
session = start_session(args.coordinator, loop=loop)
try:
session.loop.run_until_complete(
loop.run_until_complete(
asyncio.gather(
report_places(session, args.tags, gauges),
report_reservations(session, args.tags, gauges),
)
)
finally:
session.leave()
except labgrid.remote.client.Error as e:
loop.run_until_complete(session.stop())
loop.run_until_complete(session.close())
except Error as e:
print(f"Error communicating with labgrid: {e}")
continue

Expand Down
23 changes: 16 additions & 7 deletions contrib/labgrid-webapp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#!/usr/bin/env python3
import argparse
import asyncio
import logging
import os
import sys
Expand Down Expand Up @@ -118,11 +119,11 @@ def main():
formatter_class=argparse.RawDescriptionHelpFormatter,
)
parser.add_argument(
'--crossbar',
'--coordinator',
'-x',
metavar='URL',
default=os.environ.get('LG_CROSSBAR', 'ws://127.0.0.1:20408/ws'),
help='Crossbar websocket URL (default: %(default)s)',
default=os.environ.get('LG_COORDINATOR', '127.0.0.1:20408'),
help='Coordinator address as HOST[:PORT] (default: %(default)s)',
)
parser.add_argument('--port', type=int, default=8800, help='Port to serve on')
parser.add_argument('--proxy', '-P', help='Proxy connections via given ssh host')
Expand All @@ -132,16 +133,20 @@ def main():
if args.proxy:
proxymanager.force_proxy(args.proxy)

loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)

try:
session = start_session(
args.crossbar, os.environ.get('LG_CROSSBAR_REALM', 'realm1'), {},
args.coordinator,
loop=loop,
)
except ConnectionRefusedError:
logger.fatal('Unable to connect to labgrid crossbar')
logger.fatal('Unable to connect to labgrid coordinator')
return

server = uvicorn.Server(config=uvicorn.Config(
loop=session.loop,
loop=loop,
host='0.0.0.0',
port=args.port,
app=app,
Expand All @@ -153,7 +158,11 @@ def main():
if route.path not in reserved_routes:
logger.info(f' - {route.path}')

session.loop.run_until_complete(server.serve())
try:
loop.run_until_complete(server.serve())
finally:
loop.run_until_complete(session.stop())
loop.run_until_complete(session.close())


if __name__ == '__main__':
Expand Down
Loading

0 comments on commit 1ab0abd

Please sign in to comment.