|
1 | | -# ARC CE + SLURM integration test (GitLab CI) |
2 | | - |
3 | | -Spins up a single Docker container running a NorduGrid **ARC Compute |
4 | | -Element (ARC7)** wired to a single-node **SLURM** batch system, then |
5 | | -drives `arcsub` / `arcstat` / `arcget` against it to prove the whole |
6 | | -submit → monitor → retrieve path works end to end. Designed to run as |
7 | | -a GitLab CI pipeline (build stage + test stage), but also runnable |
8 | | -locally with `docker-compose`. |
9 | | - |
10 | | -## Layout |
11 | | - |
12 | | -``` |
13 | | -docker/ |
14 | | - Dockerfile AlmaLinux 9 image: munge + SLURM + ARC7 + systemd |
15 | | - slurm.conf single-node SLURM cluster config |
16 | | - cgroup.conf cgroups disabled (see note below) |
17 | | - arc.conf ARC CE config, LRMS=slurm, REST interface on :443 |
18 | | - bootstrap.sh one-shot startup script (systemd unit runs this) |
19 | | - arc-bootstrap.service systemd unit that runs bootstrap.sh at boot |
20 | | - healthcheck.sh Docker HEALTHCHECK / CI readiness probe |
21 | | -test/ |
22 | | - job.xrsl the test job description (xRSL) |
23 | | - run.sh payload script executed on the SLURM worker |
24 | | - run_integration_test.sh submit -> monitor -> retrieve driver script |
25 | | -.gitlab-ci.yml build_image + integration_test pipeline |
26 | | -docker-compose.yml local equivalent of the CI run |
27 | | -``` |
28 | | - |
29 | | -## How it fits together |
30 | | - |
31 | | -1. **Image build** installs `munge`, `slurm`/`slurm-slurmctld`/`slurm-slurmd`, |
32 | | - and ARC7 (`nordugrid-arc7-arex`, `nordugrid-arc7-client`, |
33 | | - `nordugrid-arc7-arcctl`) from EPEL on AlmaLinux 9, and enables |
34 | | - `systemd` as PID 1 — this matters because ARC's own tooling |
35 | | - (`arcctl`) and the SLURM/munge packages ship real systemd unit |
36 | | - files, and re-using those is far more reliable than hand-rolling a |
37 | | - supervisor script. |
38 | | - |
39 | | -2. **Container start** (`arc-bootstrap.service`, ordered after |
40 | | - `munge`/`slurmctld`/`slurmd`) runs `bootstrap.sh`, which: |
41 | | - - waits until `munge` and `sinfo` actually work, |
42 | | - - (re)generates the ARC **Test-CA** and a **host certificate** bound |
43 | | - to the container's *runtime* hostname (`arcctl test-ca hostcert -n |
44 | | - $(hostname) -f`) — this can't be baked into the image at build |
45 | | - time because the build-time hostname is a random ID, not `arc-ce`, |
46 | | - - starts `arc-arex` / `arc-arex-ws` (`arcctl service start |
47 | | - --as-configured`), |
48 | | - - mints a Test-CA **client certificate** for `griduser01` |
49 | | - (`arcctl test-ca usercert --install-user griduser01 -f`), which |
50 | | - `arcctl` automatically whitelists in |
51 | | - `/etc/grid-security/testCA.allowed-subjects` — this is what makes |
52 | | - the CE's default "closed by default" `[authgroup: zero]` accept |
53 | | - that user, |
54 | | - - waits for the REST endpoint to answer and writes `/run/arc-ready`. |
55 | | - |
56 | | -3. **Docker HEALTHCHECK** (`healthcheck.sh`) only reports `healthy` |
57 | | - once `/run/arc-ready` exists, `sinfo` works, and the REST endpoint |
58 | | - responds — the CI job polls this instead of guessing a fixed sleep. |
59 | | - |
60 | | -4. **The test itself** (`test/run_integration_test.sh`, run as |
61 | | - `griduser01` inside the container via `docker exec`): |
62 | | - - `arcproxy` — generate a short-lived proxy from the Test-CA user cert |
63 | | - - `arcinfo -C https://arc-ce/arex` — sanity-check the CE is reachable |
64 | | - - `arcsub -C https://arc-ce/arex job.xrsl` — **submit** |
65 | | - - poll `arcstat <jobid>` until `Finished` (or fail fast on |
66 | | - `Failed`/`Killed`) — **monitor** |
67 | | - - `arcget <jobid>` — **retrieve** `stdout.log` and `result.txt`, |
68 | | - then assert their contents |
69 | | - - `arcclean <jobid>` to tidy up |
70 | | - |
71 | | -## Why systemd + `--privileged` |
72 | | - |
73 | | -SLURM's daemons and ARC's `arcctl` assume a normal init system |
74 | | -(starting/stopping via `systemctl`, log rotation, etc). Running |
75 | | -`systemd` as PID 1 inside the container needs elevated privileges to |
76 | | -manage cgroups, so both the GitLab job and local `docker-compose` run |
77 | | -the container with `--privileged`. |
78 | | - |
79 | | -**In GitLab, this means your Runner's `config.toml` must allow |
80 | | -privileged containers for the `docker:dind` service:** |
81 | | - |
82 | | -```toml |
83 | | -[[runners]] |
84 | | - executor = "docker" |
85 | | - [runners.docker] |
86 | | - privileged = true |
87 | | -``` |
88 | | - |
89 | | -If you can't get a privileged runner, the alternative is to drop |
90 | | -systemd entirely and hand-roll process supervision (e.g. `supervisord` |
91 | | -calling `munged`, `slurmctld -D`, `slurmd -D`, and the `A-REX` daemon |
92 | | -binary directly) — more portable, but you lose the packaged unit files |
93 | | -and have to reproduce their startup ordering/flags yourself. |
94 | | - |
95 | | -## Why `cgroup.conf` disables cgroups |
96 | | - |
97 | | -`TaskPlugin=task/none` and `ProctrackType=proctrack/linuxproc` in |
98 | | -`slurm.conf` avoid SLURM's cgroup-based process tracking, which |
99 | | -typically isn't usable inside a CI container even with `--privileged` |
100 | | -unless you also bind-mount the host's cgroup hierarchy. Fine for an |
101 | | -integration test that just proves the plumbing works; not |
102 | | -representative of production resource enforcement. |
103 | | - |
104 | | -## Running locally |
105 | | - |
106 | | -```bash |
107 | | -docker compose up --build -d |
108 | | -# watch it come up |
109 | | -docker inspect -f '{{.State.Health.Status}}' arc-ce-slurm-test |
110 | | -# once "healthy": |
111 | | -docker cp test/. arc-ce-slurm-test:/opt/arc-test/ |
112 | | -docker exec arc-ce-slurm-test chown -R griduser01:griduser01 /opt/arc-test |
113 | | -docker exec arc-ce-slurm-test chmod +x /opt/arc-test/run_integration_test.sh /opt/arc-test/run.sh |
114 | | -docker exec -u griduser01 arc-ce-slurm-test /opt/arc-test/run_integration_test.sh |
115 | | -``` |
116 | | - |
117 | | -## Running in GitLab CI |
118 | | - |
119 | | -Just push this repo (or merge these files into yours) with |
120 | | -`.gitlab-ci.yml` at the root. The `build_image` stage builds and saves |
121 | | -the image as a job artifact; `integration_test` loads it, runs it |
122 | | -privileged, waits for the health check, executes the test script |
123 | | -inside the container, and archives ARC/SLURM logs as artifacts |
124 | | -regardless of pass/fail. |
125 | | - |
126 | | -## Things you'll likely want to change for a real environment |
127 | | - |
128 | | -- **Package versions**: this pins nothing beyond "ARC7 from EPEL on |
129 | | - EL9". For reproducible CI, pin `nordugrid-arc7-arex-<version>` etc. |
130 | | - explicitly, or build from the upstream NorduGrid repo instead of |
131 | | - EPEL (see https://www.nordugrid.org/arc/arc7/common/repos/repository.html). |
132 | | -- **Multi-container topology**: this is deliberately an all-in-one |
133 | | - container (CE + SLURM + client in one box) to keep the CI pipeline |
134 | | - simple. For something closer to production, split into an `arc-ce` |
135 | | - service, a `slurmctld`/`slurmd` service (or a real multi-node SLURM |
136 | | - cluster), and a separate `client` container talking to the CE over |
137 | | - the Docker network, sharing a `munge.key` via a named volume. |
138 | | -- **Certificates**: this uses ARC's built-in Test-CA, which is exactly |
139 | | - what it's for (throwaway integration testing). Never use it for |
140 | | - anything reachable from outside your CI network. |
141 | | -- **Job payload**: `test/job.xrsl` / `test/run.sh` are a minimal |
142 | | - smoke test. Extend them to cover whatever your real batch workloads |
143 | | - look like (multi-core requests, input/output staging from object |
144 | | - storage, RunTime Environments, etc). |
| 1 | +<p align="center"> |
| 2 | + <img src="./docs/assets/intercede-logo.svg" alt="interCEde" width="380"> |
| 3 | +</p> |
| 4 | + |
| 5 | +<p align="center"> |
| 6 | + <em>Unified interfaces to Computing Elements and batch systems for DIRAC / DiracX and beyond —<br> |
| 7 | + submit, monitor, retrieve — validated against containerized backends.</em> |
| 8 | +</p> |
| 9 | + |
| 10 | +<p align="center"> |
| 11 | + <a href="https://github.com/DIRACGrid/intercede/actions"><img src="https://img.shields.io/github/actions/workflow/status/DIRACGrid/intercede/ci.yml?branch=main" alt="CI"></a> |
| 12 | + <a href="https://pypi.org/project/intercede/"><img src="https://img.shields.io/pypi/v/intercede" alt="PyPI"></a> |
| 13 | + <a href="https://www.python.org/"><img src="https://img.shields.io/pypi/pyversions/intercede" alt="Python versions"></a> |
| 14 | + <a href="./LICENSE"><img src="https://img.shields.io/github/license/DIRACGrid/intercede" alt="License"></a> |
| 15 | +</p> |
| 16 | + |
| 17 | +--- |
| 18 | + |
| 19 | +## What is interCEde? |
| 20 | + |
| 21 | +**interCEde** sits between Workload Management Systems, such as [DiracX](https://github.com/DIRACGrid/diracx) and the |
| 22 | +many resources where jobs actually run. It provides a single, consistent interface for |
| 23 | +talking to **Computing Elements (CEs)** and **batch systems** — submitting jobs, querying |
| 24 | +their status, and retrieving their outputs — regardless of which backend is on the other |
| 25 | +end. |
| 26 | + |
| 27 | +The name is the job description: the library *intercedes* on WMS' behalf, acting between |
| 28 | +two parties so the rest of the stack never has to know whether it is talking to ARC, |
| 29 | +HTCondor, Slurm over SSH, or a process on the local machine. |
| 30 | + |
| 31 | +Every interface ships with **integration tests that run against containerized instances** |
| 32 | +of the real backends, so a given CE type is verified against multiple versions and |
| 33 | +configurations rather than against a mock that drifts from reality. |
| 34 | + |
| 35 | +## Why it exists |
| 36 | + |
| 37 | +- **One contract, many backends.** Calling code submits a job the same way everywhere; the |
| 38 | + backend-specific quirks live behind the interface. |
| 39 | +- **Composable resources.** Backends combine — `SSH + Slurm`, `SSH + HTCondor`, |
| 40 | + `ARC + HTCondor`, or a plain `local` runner — and each combination is just another |
| 41 | + implementation of the same interface. |
| 42 | +- **Tested against the real thing.** Containerized Slurm, HTCondor, and ARC instances are |
| 43 | + spun up in CI so behavior is checked against actual schedulers, not stubs. |
| 44 | +- **Version coverage.** The same test suite runs across a matrix of backend versions to |
| 45 | + catch incompatibilities before they reach production. |
| 46 | + |
| 47 | +## Relationship to DIRAC / DiracX |
| 48 | + |
| 49 | +interCEde is part of the [DIRACGrid](https://github.com/DIRACGrid) ecosystem and is designed |
| 50 | +to back the Computing Element layer used by [DiracX](https://github.com/DIRACGrid/diracx). |
| 51 | +It can also be used standalone wherever a uniform interface to heterogeneous CEs and batch |
| 52 | +systems is useful. |
0 commit comments