Skip to content

Commit 9d545ec

Browse files
committed
add publishing of agent to github releases
1 parent f3904d7 commit 9d545ec

File tree

8 files changed

+245
-37
lines changed

8 files changed

+245
-37
lines changed

.github/workflows/_release.yml

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
on:
2+
workflow_call:
3+
4+
jobs:
5+
agent:
6+
runs-on: ubuntu-latest
7+
strategy:
8+
matrix:
9+
goarch: [amd64, arm64]
10+
11+
steps:
12+
- name: Checkout
13+
uses: actions/checkout@v4
14+
15+
- name: Set up Go
16+
uses: actions/setup-go@v5
17+
with:
18+
go-version-file: go.mod
19+
20+
- name: Build agent
21+
run: CGO_ENABLED=0 GOARCH=${{ matrix.goarch }} go build -o agent-linux-${{ matrix.goarch }} ./cmd/agent/
22+
23+
- name: Upload artifact
24+
uses: actions/upload-artifact@v4
25+
with:
26+
name: agent-linux-${{ matrix.goarch }}
27+
path: agent-linux-${{ matrix.goarch }}
28+
29+
release:
30+
needs: agent
31+
runs-on: ubuntu-latest
32+
33+
steps:
34+
- name: Checkout
35+
uses: actions/checkout@v4
36+
37+
- name: Download artifacts
38+
uses: actions/download-artifact@v4
39+
with:
40+
merge-multiple: true
41+
42+
- name: Create GitHub Release
43+
uses: softprops/action-gh-release@6da8fa9354ddfdc4aeace5fc48d7f679b5214090 # v2.4.1
44+
with:
45+
prerelease: ${{ contains(github.ref_name, 'a') || contains(github.ref_name, 'b') || contains(github.ref_name, 'rc') }}
46+
files: |
47+
agent-linux-amd64
48+
agent-linux-arm64
49+
scripts/install-agent.sh
50+
generate_release_notes: true
51+
env:
52+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

.github/workflows/ci.yml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,13 @@ jobs:
3131
contents: read
3232
packages: write
3333

34+
release:
35+
needs: test
36+
if: github.ref_type == 'tag'
37+
uses: ./.github/workflows/_release.yml
38+
permissions:
39+
contents: write
40+
3441
docs:
3542
uses: ./.github/workflows/_docs.yml
3643
permissions:

docs/how-to.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
```{toctree}
44
:maxdepth: 1
55
6+
how-to/setup-agent
67
how-to/deploy
78
how-to/run-ci-locally
89
how-to/run-sphinx

docs/how-to/deploy.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Deploy to Kubernetes
1+
# Install the manager and plugin on Kubernetes
22

33
This guide covers deploying the manager and plugin to a Kubernetes cluster
44
using Helm.

docs/how-to/run-sphinx.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Run Sphinx
1+
# Build the docs locally
22

33
This guide explains how to build and preview the project documentation locally
44
using Sphinx. Makefile targets are provided so you don't need to remember the

docs/how-to/setup-agent.md

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
# Install the agent on a USB/IP host
2+
3+
The agent runs on a machine with USB devices (typically a Raspberry Pi) and
4+
exposes them over the network via USB/IP. The Kubernetes manager polls agents
5+
to discover available devices.
6+
7+
## Prerequisites
8+
9+
- A Linux machine (Raspberry Pi OS, Debian, Ubuntu, etc.) with USB devices
10+
attached
11+
- The `usbip` kernel module and userspace tools installed
12+
- `curl` available for the install script
13+
- Root access (the installer creates a systemd service)
14+
15+
### Install USB/IP tools
16+
17+
On Debian/Ubuntu/Raspberry Pi OS:
18+
19+
```bash
20+
$ sudo apt-get update && sudo apt-get install -y linux-tools-generic
21+
```
22+
23+
On Raspberry Pi OS the package may be `usbip` instead:
24+
25+
```bash
26+
$ sudo apt-get update && sudo apt-get install -y usbip
27+
```
28+
29+
### Load the kernel module
30+
31+
```bash
32+
$ sudo modprobe usbip_host
33+
```
34+
35+
To load the module automatically on boot:
36+
37+
```bash
38+
$ echo usbip_host | sudo tee /etc/modules-load.d/usbip_host.conf
39+
```
40+
41+
## Install the agent
42+
43+
The install script downloads the correct binary for your architecture,
44+
installs it to `/usr/local/bin/agent`, and creates a systemd service:
45+
46+
```bash
47+
$ curl -fsSLO https://raw.githubusercontent.com/DiamondLightSource/dra-usbip-driver/main/scripts/install-agent.sh
48+
$ sudo sh install-agent.sh
49+
```
50+
51+
To install a specific version:
52+
53+
```bash
54+
$ sudo sh install-agent.sh 0.1.0
55+
```
56+
57+
## Verify
58+
59+
Check that the service is running:
60+
61+
```bash
62+
$ sudo systemctl status dra-usbip-agent
63+
```
64+
65+
The agent serves a device list on port 13240. Test it with:
66+
67+
```bash
68+
$ curl http://localhost:13240/devices
69+
```
70+
71+
## Uninstall
72+
73+
```bash
74+
$ sudo systemctl stop dra-usbip-agent
75+
$ sudo systemctl disable dra-usbip-agent
76+
$ sudo rm /etc/systemd/system/dra-usbip-agent.service
77+
$ sudo systemctl daemon-reload
78+
$ sudo rm /usr/local/bin/agent
79+
```

docs/tutorials/quick-start.md

Lines changed: 41 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -6,42 +6,45 @@ USB device available to a pod in your Kubernetes cluster.
66
## Prerequisites
77

88
- A Kubernetes cluster (v1.34+) with DRA enabled
9-
- `kubectl` configured to access the cluster
10-
- A machine with USB devices to share (the Agent host)
11-
- The `usbip` tools installed on both the Agent host and cluster nodes
9+
- `kubectl` and [Helm](https://helm.sh/docs/intro/install/) 3.x configured
10+
to access the cluster
11+
- A machine with USB devices to share (the agent host, typically a
12+
Raspberry Pi or similar)
13+
- The `usbip` tools installed on both the agent host and cluster nodes
1214
- The `vhci-hcd` and `usbip-host` kernel modules loaded
1315

14-
## 1. Run the Agent
16+
## 1. Install the agent
1517

16-
On the machine with USB devices attached, build and run the Agent binary:
18+
On the machine with USB devices attached, run the install script:
1719

1820
```bash
19-
make agent
20-
./agent --bind-all-devices
21+
curl -fsSLO https://raw.githubusercontent.com/DiamondLightSource/dra-usbip-driver/main/scripts/install-agent.sh
22+
sudo sh install-agent.sh 0.1.0
2123
```
2224

23-
The Agent serves device metadata on port 13240. Verify it is working:
25+
This downloads the correct binary for your architecture, installs it as a
26+
systemd service, and starts it. The agent serves device metadata on port
27+
13240.
28+
29+
Verify it is working:
2430

2531
```bash
2632
curl http://<agent-host>:13240/devices
2733
```
2834

2935
You should see a JSON array describing the connected USB devices.
3036

31-
## 2. Deploy the Manager
32-
33-
The Manager runs inside the cluster and polls Agents for device information.
37+
For more detail see {doc}`/how-to/setup-agent`.
3438

35-
```bash
36-
kubectl apply -f examples/manager.yaml
37-
```
39+
## 2. Deploy the manager and plugin
3840

39-
Or run the container image directly:
41+
Install the Helm chart, passing the address of your agent host:
4042

4143
```bash
42-
kubectl run usbip-manager \
43-
--image=ghcr.io/diamondlightsource/dra-usbip-driver-manager:latest \
44-
-- --agent=<agent-host>
44+
helm -n kube-system upgrade --install dra-usbip-driver \
45+
oci://ghcr.io/diamondlightsource/charts/dra-usbip-driver \
46+
--version 0.1.0 \
47+
--set 'manager.agents={<agent-host>}'
4548
```
4649

4750
Check that ResourceSlices have been created:
@@ -50,29 +53,32 @@ Check that ResourceSlices have been created:
5053
kubectl get resourceslices
5154
```
5255

53-
## 3. Deploy the Plugin DaemonSet
54-
55-
The Plugin runs on each node and handles attaching USB/IP devices when pods
56-
request them:
57-
58-
```bash
59-
kubectl apply -f examples/plugin-daemonset.yaml
60-
```
56+
For more detail see {doc}`/how-to/deploy`.
6157

62-
## 4. Create a ResourceClaim and Pod
58+
## 3. Request a USB device in a pod
6359

64-
Create a ResourceClaim to request a USB device, then a Pod that references it:
60+
Create a `ResourceClaimTemplate` to match a specific USB device, then
61+
reference it from a pod:
6562

6663
```yaml
6764
apiVersion: resource.k8s.io/v1
68-
kind: ResourceClaim
65+
kind: ResourceClaimTemplate
6966
metadata:
70-
name: my-usb-device
67+
name: serial-adapter
7168
spec:
72-
devices:
73-
requests:
74-
- name: usb
75-
deviceClassName: usbip
69+
spec:
70+
devices:
71+
requests:
72+
- name: req-0
73+
firstAvailable:
74+
- name: adapter
75+
deviceClassName: usbip
76+
selectors:
77+
- cel:
78+
expression: |-
79+
device.attributes["usbip.diamond.ac.uk"].vendor == "0403" &&
80+
device.attributes["usbip.diamond.ac.uk"].product == "6015" &&
81+
device.attributes["usbip.diamond.ac.uk"].serial == "FTA954OZ"
7682
---
7783
apiVersion: v1
7884
kind: Pod
@@ -85,7 +91,7 @@ spec:
8591
command: ["sleep", "infinity"]
8692
resourceClaims:
8793
- name: usb-claim
88-
resourceClaimName: my-usb-device
94+
resourceClaimTemplateName: serial-adapter
8995
```
9096
9197
```bash

scripts/install-agent.sh

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
#!/bin/sh
2+
set -eu
3+
4+
REPO="DiamondLightSource/dra-usbip-driver"
5+
INSTALL_DIR="/usr/local/bin"
6+
SERVICE_NAME="dra-usbip-agent"
7+
BINARY_NAME="agent"
8+
9+
# Detect architecture
10+
ARCH=$(uname -m)
11+
case "$ARCH" in
12+
x86_64) GOARCH="amd64" ;;
13+
aarch64) GOARCH="arm64" ;;
14+
*)
15+
echo "Error: unsupported architecture: $ARCH" >&2
16+
exit 1
17+
;;
18+
esac
19+
20+
# Determine version — use first argument, VERSION env var, or fetch latest release
21+
if [ -n "${1:-}" ]; then
22+
TAG="$1"
23+
elif [ -n "${VERSION:-}" ]; then
24+
TAG="$VERSION"
25+
else
26+
TAG=$(curl -fsSL "https://api.github.com/repos/${REPO}/releases/latest" | grep '"tag_name"' | cut -d'"' -f4)
27+
if [ -z "$TAG" ]; then
28+
echo "Error: could not determine latest release" >&2
29+
exit 1
30+
fi
31+
fi
32+
33+
DOWNLOAD_URL="https://github.com/${REPO}/releases/download/${TAG}/agent-linux-${GOARCH}"
34+
35+
echo "Installing ${SERVICE_NAME} ${TAG} (linux/${GOARCH})..."
36+
37+
# Download binary
38+
curl -fsSL -o /tmp/${BINARY_NAME} "$DOWNLOAD_URL"
39+
chmod +x /tmp/${BINARY_NAME}
40+
mv /tmp/${BINARY_NAME} "${INSTALL_DIR}/${BINARY_NAME}"
41+
42+
echo "Installed ${INSTALL_DIR}/${BINARY_NAME}"
43+
44+
# Create systemd service
45+
cat > /etc/systemd/system/${SERVICE_NAME}.service <<EOF
46+
[Unit]
47+
Description=DRA USB/IP Agent
48+
After=network.target
49+
50+
[Service]
51+
ExecStart=${INSTALL_DIR}/${BINARY_NAME}
52+
Restart=on-failure
53+
RestartSec=5
54+
55+
[Install]
56+
WantedBy=multi-user.target
57+
EOF
58+
59+
systemctl daemon-reload
60+
systemctl enable "${SERVICE_NAME}"
61+
systemctl start "${SERVICE_NAME}"
62+
63+
echo "Service ${SERVICE_NAME} enabled and started."

0 commit comments

Comments
 (0)