From 6ccd76a4557fdb9498f697e766fb21e362b5b053 Mon Sep 17 00:00:00 2001 From: "Josh.5" Date: Sat, 14 Sep 2024 17:25:04 +1200 Subject: [PATCH 1/7] Update GitHub actions --- .github/workflows/ghcr.yml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/ghcr.yml b/.github/workflows/ghcr.yml index 0a94980..1baee9a 100644 --- a/.github/workflows/ghcr.yml +++ b/.github/workflows/ghcr.yml @@ -10,7 +10,7 @@ on: - "v*.*.*" pull_request: branches: - - "main" + - "master" jobs: push-store-image: @@ -21,25 +21,25 @@ jobs: steps: - name: "Checkout Repository" - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: "Login to GitHub Container Registry" if: github.event_name != 'pull_request' - uses: docker/login-action@v2 + uses: docker/login-action@v3 with: registry: ghcr.io username: ${{github.actor}} password: ${{secrets.GITHUB_TOKEN}} - name: Set up QEMU - uses: docker/setup-qemu-action@v2 + uses: docker/setup-qemu-action@v3 - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v2 + uses: docker/setup-buildx-action@v3 - name: Docker meta id: meta - uses: docker/metadata-action@v4 + uses: docker/metadata-action@v5 with: images: ghcr.io/${{github.actor}}/${{github.repository}} tags: | @@ -52,7 +52,7 @@ jobs: type=sha - name: Build and push - uses: docker/build-push-action@v4 + uses: docker/build-push-action@v6 with: context: . platforms: linux/amd64,linux/arm64,linux/arm/v7 From 817979e9bd12294e47cf70004ebb911aaeeb9866 Mon Sep 17 00:00:00 2001 From: "Josh.5" Date: Sat, 14 Sep 2024 18:07:37 +1200 Subject: [PATCH 2/7] Improve how docker image is run The stack template should run the dmm process with `--rm`. Then when the swarm service is stopped, it will also terminate the dmm process. --- docker-compose.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docker-compose.yml b/docker-compose.yml index e918022..b274ab2 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -6,7 +6,8 @@ services: image: docker entrypoint: docker command: | - run + run + --rm -i --name device-manager --restart always From d27e407223b02516023135e3067c283030d84c44 Mon Sep 17 00:00:00 2001 From: "Josh.5" Date: Sat, 14 Sep 2024 18:07:55 +1200 Subject: [PATCH 3/7] Fix warnings in Docker build --- Dockerfile | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index ddb09be..2c9890d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,7 +2,7 @@ FROM golang:1.19 -ENV DEBIAN_FRONTEND noninteractive +ENV DEBIAN_FRONTEND=noninteractive WORKDIR /go/src/github.com/allfro/device-volume-driver @@ -17,4 +17,3 @@ WORKDIR / COPY --from=0 /dvd /dvd ENTRYPOINT ["/dvd"] - From 27a3bc1de86fd234c45b0155bd4a7fa1bdff518b Mon Sep 17 00:00:00 2001 From: "Josh.5" Date: Sat, 14 Sep 2024 18:36:38 +1200 Subject: [PATCH 4/7] Update service to scan all running containers on service start When a host restarts, there is no guarantee that this service will start before the ones that you want to have modified. This then leads to those started containers not having the required permissions to access the /dev nodes. This update runs a quick parse over the running containers and for each of them with a /dev mount, it will apply the device rules. --- main.go | 127 +++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 79 insertions(+), 48 deletions(-) diff --git a/main.go b/main.go index 411b48b..1b1ba55 100644 --- a/main.go +++ b/main.go @@ -70,6 +70,31 @@ func listenForMounts() { defer cli.Close() + // Scan all running containers on startup + containers, err := cli.ContainerList(ctx, types.ContainerListOptions{All: false}) + if err != nil { + log.Fatal(err) + } + + for _, container := range containers { + info, err := cli.ContainerInspect(ctx, container.ID) + if err != nil { + log.Println(err) + continue + } + + pid := info.State.Pid + version, err := cgroup.GetDeviceCGroupVersion("/", pid) + if err != nil { + log.Println(err) + continue + } + + log.Printf("Checking mounts for process %d\n", pid) + processMounts(container.ID, info.Mounts, pid, version) + } + + // Monitor container start events msgs, errs := cli.Events( ctx, types.EventsOptions{Filters: filters.NewArgs(filters.Arg("event", "start"))}, @@ -96,56 +121,62 @@ func listenForMounts() { } log.Printf("Checking mounts for process %d\n", pid) + processMounts(msg.Actor.ID, info.Mounts, pid, version) + } + } + } +} - for _, mount := range info.Mounts { - log.Printf( - "%s/%v requested a volume mount for %s at %s\n", - msg.Actor.ID, info.State.Pid, mount.Source, mount.Destination, - ) - - if !strings.HasPrefix(mount.Source, "/dev") { - log.Printf("%s is not a device... skipping\n", mount.Source) - continue - } - - api, err := cgroup.New(version) - cgroupPath, sysfsPath, err := api.GetDeviceCGroupMountPath("/", pid) - - if err != nil { - log.Println(err) - break - } - - cgroupPath = path.Join(rootPath, sysfsPath, cgroupPath) - - log.Printf("The cgroup path for process %d is at %v\n", pid, cgroupPath) - - if fileInfo, err := os.Stat(mount.Source); err != nil { - log.Println(err) - continue - } else { - if fileInfo.IsDir() { - err := filepath.Walk(mount.Source, - func(path string, info os.FileInfo, err error) error { - if err != nil { - return err - } else if info.IsDir() { - return nil - } else if err = applyDeviceRules(api, path, cgroupPath, pid); err != nil { - log.Println(err) - } - return nil - }) - if err != nil { - log.Println(err) - } - } else { - if err = applyDeviceRules(api, mount.Source, cgroupPath, pid); err != nil { - log.Println(err) - } - } - } +func processMounts(containerId string, mounts []types.MountPoint, pid int, version int) { + api, err := cgroup.New(version) + if err != nil { + log.Println(err) + return + } + + for _, mount := range mounts { + log.Printf( + "%s/%v requested a volume mount for %s at %s\n", + containerId, pid, mount.Source, mount.Destination, + ) + + if !strings.HasPrefix(mount.Source, "/dev") { + log.Printf("%s is not a device... skipping\n", mount.Source) + continue + } + + cgroupPath, sysfsPath, err := api.GetDeviceCGroupMountPath("/", pid) + if err != nil { + log.Println(err) + continue + } + cgroupPath = path.Join(rootPath, sysfsPath, cgroupPath) + + log.Printf("The cgroup path for process %d is at %v\n", pid, cgroupPath) + + if fileInfo, err := os.Stat(mount.Source); err != nil { + log.Println(err) + continue + } else { + if fileInfo.IsDir() { + err := filepath.Walk(mount.Source, + func(path string, info os.FileInfo, err error) error { + if err != nil { + return err + } else if info.IsDir() { + return nil + } else if err = applyDeviceRules(api, path, cgroupPath, pid); err != nil { + log.Println(err) + } + return nil + }) + if err != nil { + log.Println(err) + } + } else { + if err = applyDeviceRules(api, mount.Source, cgroupPath, pid); err != nil { + log.Println(err) } } } From 45259dbed64f6282c166a47bd8f336575de3c19e Mon Sep 17 00:00:00 2001 From: "Josh.5" Date: Sat, 14 Sep 2024 18:37:26 +1200 Subject: [PATCH 5/7] Add an `.editorconfig` file to ensure formatting styles for tabs are enforced in IDE --- .editorconfig | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 .editorconfig diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..44f341e --- /dev/null +++ b/.editorconfig @@ -0,0 +1,6 @@ +# Top-most EditorConfig file +root = true + +[*] +indent_style = tab +indent_size = 4 From b431735cf0032e92d8f9dd0128597070574f30c3 Mon Sep 17 00:00:00 2001 From: "Josh.5" Date: Sat, 14 Sep 2024 19:04:31 +1200 Subject: [PATCH 6/7] Improvement to how this service is run Lets just run it with an entrypoint script to simplify the compose template --- Dockerfile | 7 ++++-- docker-compose.yml | 19 +++------------ entrypoint.sh | 58 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 66 insertions(+), 18 deletions(-) create mode 100755 entrypoint.sh diff --git a/Dockerfile b/Dockerfile index 2c9890d..ed1fb34 100644 --- a/Dockerfile +++ b/Dockerfile @@ -10,10 +10,13 @@ COPY . . RUN CGO_ENABLED=1 GOOS=linux go build -ldflags "-linkmode external -extldflags -static" -o /dvd -FROM alpine +FROM docker:latest + +RUN apk add bash WORKDIR / COPY --from=0 /dvd /dvd +COPY /entrypoint.sh /entrypoint.sh -ENTRYPOINT ["/dvd"] +ENTRYPOINT ["/entrypoint.sh"] diff --git a/docker-compose.yml b/docker-compose.yml index b274ab2..3157b08 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,22 +1,9 @@ version: "3.8" - services: dmm: - image: docker - entrypoint: docker - command: | - run - --rm - -i - --name device-manager - --restart always - --privileged - --cgroupns=host - --pid=host - --userns=host - -v /sys:/host/sys - -v /var/run/docker.sock:/var/run/docker.sock - ndouba/device-mapping-manager + image: ghcr.io/allfro/allfro/device-mapping-manager:nightly + environment: + DOCKER_IAMGE: ghcr.io/allfro/allfro/device-mapping-manager:nightly # Set this to the same as 'image' above volumes: - /var/run/docker.sock:/var/run/docker.sock diff --git a/entrypoint.sh b/entrypoint.sh new file mode 100755 index 0000000..6646f62 --- /dev/null +++ b/entrypoint.sh @@ -0,0 +1,58 @@ +#!/usr/bin/env bash + +set -e + + +script_dir=$(cd $(dirname ${BASH_SOURCE[@]}) && pwd) +container_name="swarm-device-manager" + + +# All printed log lines from this script should be formatted with this function +print_log() { + local timestamp="$(date +'%Y-%m-%d %H:%M:%S %z')" + local pid="$$" + local level="$1" + local message="${@:2}" + echo "[${timestamp}] [${pid}] [${level^^}] ${message}" +} + + +# Ensure docker socket is available +if [ ! -S /var/run/docker.sock ]; then + print_log "error" "Missing Docker socket. Ensure you run this container mounting '/var/run/docker.sock'. Exit!" + exit 1 +fi + + +# Re-run this as a docker container with elevated privileges +if [ ! -d /host/sys ]; then + # Ensure image version is available + if [ "X${DOCKER_IAMGE}" = "X" ]; then + print_log "error" "Missing required 'DOCKER_IAMGE' variable. Exit!" + exit 1 + fi + + # Check if container is already running. Stop it + if docker ps --filter "name=^${container_name}$" | grep -q "${container_name}"; then + docker stop "${container_name}" &> /dev/null || true + fi + + # Run docker container + print_log "info" "Running privileged container '${container_name}'..." + exec docker run \ + --rm \ + -i \ + --name "${container_name}" \ + --privileged \ + --cgroupns=host \ + --pid=host \ + --userns=host \ + -v /sys:/host/sys \ + -v /var/run/docker.sock:/var/run/docker.sock \ + "${DOCKER_IAMGE:?}" +fi + + +# Run service +print_log "info" "Running main service..." +exec /dvd From faf427031c11b6d0787a57488e7f42b311cb5164 Mon Sep 17 00:00:00 2001 From: "Josh.5" Date: Thu, 19 Feb 2026 10:17:05 +1300 Subject: [PATCH 7/7] Fix image naming --- .github/workflows/ghcr.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ghcr.yml b/.github/workflows/ghcr.yml index 1baee9a..b1b98f7 100644 --- a/.github/workflows/ghcr.yml +++ b/.github/workflows/ghcr.yml @@ -41,7 +41,7 @@ jobs: id: meta uses: docker/metadata-action@v5 with: - images: ghcr.io/${{github.actor}}/${{github.repository}} + images: ghcr.io/${{github.repository}} tags: | type=schedule type=ref,event=branch