sqtop 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- sqtop-0.1.0/LICENSE +21 -0
- sqtop-0.1.0/PKG-INFO +324 -0
- sqtop-0.1.0/README.md +304 -0
- sqtop-0.1.0/pyproject.toml +40 -0
- sqtop-0.1.0/pyproject.toml.orig +35 -0
- sqtop-0.1.0/src/sqtop/__init__.py +0 -0
- sqtop-0.1.0/src/sqtop/cli.py +74 -0
- sqtop-0.1.0/src/sqtop/hosts.py +272 -0
- sqtop-0.1.0/src/sqtop/mailer.py +230 -0
- sqtop-0.1.0/src/sqtop/probes.py +401 -0
- sqtop-0.1.0/src/sqtop/profiles.py +262 -0
- sqtop-0.1.0/src/sqtop/report.py +281 -0
- sqtop-0.1.0/src/sqtop/slurm.py +786 -0
- sqtop-0.1.0/src/sqtop/snapshot.py +704 -0
- sqtop-0.1.0/src/sqtop/tui.py +1736 -0
- sqtop-0.1.0/src/sqtop/views.py +274 -0
sqtop-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Yanting Yang
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
sqtop-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,324 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: sqtop
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Slurm dashboard: partitions, account/QOS limits and estimated start times
|
|
5
|
+
Keywords: slurm,hpc,tui,dashboard,squeue,sbatch
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
License-File: LICENSE
|
|
8
|
+
Classifier: Development Status :: 4 - Beta
|
|
9
|
+
Classifier: Environment :: Console
|
|
10
|
+
Classifier: Intended Audience :: Science/Research
|
|
11
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
13
|
+
Classifier: Topic :: System :: Clustering
|
|
14
|
+
Classifier: Topic :: System :: Monitoring
|
|
15
|
+
Requires-Dist: textual>=8,<9
|
|
16
|
+
Requires-Python: ==3.13.*
|
|
17
|
+
Project-URL: Homepage, https://github.com/yanting-yang/sqtop
|
|
18
|
+
Project-URL: Issues, https://github.com/yanting-yang/sqtop/issues
|
|
19
|
+
Description-Content-Type: text/markdown
|
|
20
|
+
|
|
21
|
+
# sqtop
|
|
22
|
+
|
|
23
|
+
A terminal dashboard for Slurm, in the spirit of
|
|
24
|
+
[hunoutl/slurmtop](https://github.com/hunoutl/slurmtop) and
|
|
25
|
+
[slmtop](https://github.com/dawnmy/slmtop), that answers "where can I run, under which
|
|
26
|
+
account/QOS, and when would it start?", and can email you that report every hour while
|
|
27
|
+
it runs.
|
|
28
|
+
|
|
29
|
+
```
|
|
30
|
+
killarney fir tamia
|
|
31
|
+
╸━━━━━━━━━╺━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
32
|
+
someone@klogin02 killarney Slurm 25.05.9 updated 13:49:06 (10s ago) · probed 13:49:06
|
|
33
|
+
╭─ Partitions ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
|
|
34
|
+
│ Partition Use CPU/node Mem/node GPU/node Load Free Idle Pend Max │
|
|
35
|
+
│ gpubase_h100_b1 yes 48/96 2011G 8x h100 ██████▒▒ 75% 4/80 h100 0/10 117 0-03:00:00 │
|
|
36
|
+
│ gpubase_h100_b2 yes 48/96 2011G 8x h100 ███████▒ 86% 1/64 h100 0/8 63 0-12:00:00 │
|
|
37
|
+
│ gpubase_interac yes 64 502G 4x l40s ███████░ 90% 6/100 l40s 0/25 1 0-03:00:00 │
|
|
38
|
+
│ gpubase_l40s_b1 yes 64 502G 4x l40s ███████▒ 90% 18/672 l40s 1/168 2571 0-03:00:00 │
|
|
39
|
+
│ gpubase_l40s_b3 yes 64 502G 4x l40s ███████▒ 88% 8/336 l40s 1/84 90 1-00:00:00 │
|
|
40
|
+
╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
|
|
41
|
+
╭─ Start estimates · aip-abc123/normal ──────────────────────────────────────────────────╮╭─ Accounts & QOS ─────────────────────────────────────────╮
|
|
42
|
+
│ Request 0-03:00:00 0-12:00:00 1-00:00:00 3-00:00:00 7-00:00:00 ││ Account QOS Jobs GPUs Wall FS │
|
|
43
|
+
│ 1x h100 0-22:05:00 1-05:38:00 3-02:01:00 7-23:35:00 39-23:02:00 ││ aip-abc123* interac 0/1 ∞ 0-03:00:00 0.14 │
|
|
44
|
+
│ 8x h100 1-04:16:00 1-10:21:00 3-06:44:00 8-11:56:00 40-05:13:00 ││ aip-abc123* normal* 0/∞ ∞ ∞ 0.14 │
|
|
45
|
+
│ 1x l40s 0-02:12:00 0-01:27:00 0-01:48:00 0-19:17:00 7-15:47:00 │╰────────────────── * left out of commands · enter: probe ─╯
|
|
46
|
+
│ 4x l40s 0-02:12:00 0-02:17:00 0-01:48:00 0-21:38:00 7-18:03:00 │╭─ My jobs ────────────────────────────────────────────────╮
|
|
47
|
+
│ CPU only 0-02:12:00 0-01:27:00 0-01:48:00 0-19:17:00 7-15:47:00 ││ Job Name St Start Time Nodes Reason │
|
|
48
|
+
│ ││ No jobs in the queue │
|
|
49
|
+
╰───────────────────────────────────────────────────────────────── sbatch -c4 --mem=32G ─╯╰──────────────────────────────────────────────────────────╯
|
|
50
|
+
╭─ Details ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
|
|
51
|
+
│ gpubase_h100_b1 UP usable · max time 0-03:00:00 · priority tier 1 │
|
|
52
|
+
│ Nodes 10 (5 mixed, 3 allocated, 2 unavailable) · pending jobs 117 │
|
|
53
|
+
│ 9 nodes: 48 CPUs / 2011 GB / 8x h100 · 1 node: 96 CPUs / 2011 GB / 8x h100 │
|
|
54
|
+
│ CPUs 104 free / 328 allocated / 96 unavailable of 528 · Memory 12045 GB free of 20117 GB │
|
|
55
|
+
╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
|
|
56
|
+
Refresh Re-probe Edit request Email: off Config Quit
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Requirements
|
|
60
|
+
|
|
61
|
+
- [uv](https://docs.astral.sh/uv/) (it fetches Python 3.13 if you do not have it)
|
|
62
|
+
- A Slurm login node (`scontrol` and `squeue` on `PATH`; estimates need `sbatch`/`srun`)
|
|
63
|
+
|
|
64
|
+
## Usage
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
uvx sqtop # run it from PyPI: one tab per cluster, this one first
|
|
68
|
+
uvx sqtop > report.txt # text report of this cluster when not a terminal
|
|
69
|
+
uv tool install sqtop # or install it once, then just type `sqtop`
|
|
70
|
+
|
|
71
|
+
# From a checkout
|
|
72
|
+
uv run sqtop
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
There are no options. The first tab is the cluster you are logged in to (from
|
|
76
|
+
`ClusterName` in `scontrol show config`), and it is the only one checked at startup.
|
|
77
|
+
Every other cluster with an `ssh` host in the [config file](#configuration) (Fir,
|
|
78
|
+
Killarney and Tamia) gets a tab too, but is only contacted, over ssh, once you open its
|
|
79
|
+
tab (click it). Every probe starts as 4 CPUs and 32 GB at each partition
|
|
80
|
+
time limit with `sbatch`; change a tab's request with `Edit request` (CPUs, memory,
|
|
81
|
+
walltimes, extra `sbatch` options), and click the command under Start estimates to
|
|
82
|
+
switch between `sbatch` and `srun`. The visible tab refreshes every minute and re-probes
|
|
83
|
+
every five. Click `Email: off` to email the report every hour until you quit
|
|
84
|
+
([Hourly email](#hourly-email)). Everything is a click: see [Mouse](#mouse).
|
|
85
|
+
|
|
86
|
+
Probes use `--test-only`, so nothing is submitted or cancelled until you confirm a
|
|
87
|
+
Submit or Release (see below), and it is safe to run on a shared login node. Run it on
|
|
88
|
+
the login node: on a compute node, such as inside an interactive job, `srun` probes fail
|
|
89
|
+
with "Requested operation is presently disabled".
|
|
90
|
+
|
|
91
|
+
### Remote clusters
|
|
92
|
+
|
|
93
|
+
Remote tabs run Slurm on the cluster's login node through `ssh`, with your
|
|
94
|
+
`~/.ssh/config` (aliases, users, keys). Nothing is sent to a remote cluster until you
|
|
95
|
+
open its tab, and only the visible tab refreshes.
|
|
96
|
+
|
|
97
|
+
sqtop never asks for a password or MFA. For a cluster that needs one, let ssh share
|
|
98
|
+
connections and log in with `ssh` in another terminal first; sqtop reuses that
|
|
99
|
+
connection:
|
|
100
|
+
|
|
101
|
+
```
|
|
102
|
+
# ~/.ssh/config
|
|
103
|
+
Host *.alliancecan.ca
|
|
104
|
+
ControlMaster auto
|
|
105
|
+
ControlPath ~/.ssh/cm-%C
|
|
106
|
+
ControlPersist 4h
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
After `ssh fir.alliancecan.ca`, the connection stays open for 4 hours after your last
|
|
110
|
+
session there closes. With keys that log in without a prompt, nothing is needed:
|
|
111
|
+
sqtop opens its own shared connection, which closes 10 minutes after the last use.
|
|
112
|
+
A tab that cannot connect shows ssh's error and how to connect; then click `Refresh`.
|
|
113
|
+
|
|
114
|
+
The text report printed when output is not a terminal covers the cluster you are on;
|
|
115
|
+
it covers the remote ones only where Slurm is not available.
|
|
116
|
+
|
|
117
|
+
Each refresh of a remote tab is one ssh session, and the cache of limits is fetched
|
|
118
|
+
only for your accounts and QOS, because login nodes can take seconds to start a
|
|
119
|
+
session and the full cache can be tens of MB. Commands for a remote cluster are shown
|
|
120
|
+
with its host as the prompt (`fir.alliancecan.ca$ sbatch ...`): run them there.
|
|
121
|
+
|
|
122
|
+
### Mouse
|
|
123
|
+
|
|
124
|
+
sqtop has no keyboard shortcuts: everything is a click. The bar at the bottom holds
|
|
125
|
+
the dashboard's actions, and each dialog closes with its own buttons.
|
|
126
|
+
|
|
127
|
+
| Click | Action |
|
|
128
|
+
| --- | --- |
|
|
129
|
+
| a cluster tab | Show that cluster |
|
|
130
|
+
| a row or cell | Select it; the Details panel follows the selection |
|
|
131
|
+
| a highlighted Accounts & QOS row | Probe with that account/QOS |
|
|
132
|
+
| the Partitions title | Switch between Partitions and Nodes by hardware |
|
|
133
|
+
| the account/QOS above the estimates | Probe with the next account/QOS |
|
|
134
|
+
| the command under Start estimates | Switch between `sbatch` and `srun` probes |
|
|
135
|
+
| `Submit` in Details | Submit the selected `sbatch` request, after you confirm |
|
|
136
|
+
| `Copy` after a command in Details | Copy that command |
|
|
137
|
+
| `Release` in a job's Details | Release the job with `scancel`, after you confirm |
|
|
138
|
+
| `Refresh` / `Re-probe` | Refresh everything / re-probe now |
|
|
139
|
+
| `Edit request` | Edit the probe request: whole node, CPUs, memory, walltimes, extra options such as `--partition` or `--constraint`, and the email address (blank for none) |
|
|
140
|
+
| `Email: off` / `Email: on` | Email the report now and every hour until you quit / stop; the label says which is on |
|
|
141
|
+
| `Config` | Edit the [config](#configuration) in a form; saving writes the file and applies it |
|
|
142
|
+
| `Quit` | Quit |
|
|
143
|
+
|
|
144
|
+
## Reading the dashboard
|
|
145
|
+
|
|
146
|
+
- **Partitions**: `Use` says whether your accounts, QOS and Unix groups may submit
|
|
147
|
+
there. `CPU/node`, `Mem/node` and `GPU/node` are each node's hardware (CPUs exclude
|
|
148
|
+
reserved cores); a partition with two kinds of node shows both (`48/96`), with more
|
|
149
|
+
a range. `Load` is the share of GPUs (CPUs on CPU-only partitions) in use: `█`
|
|
150
|
+
allocated, `▒` unavailable (down, drained, reserved), `░` free. `Free` is free/total
|
|
151
|
+
per GPU type, `Idle` counts wholly idle nodes, `Pend` counts pending jobs from all
|
|
152
|
+
users, and `Max` is the time limit. Details list each kind of node with its count,
|
|
153
|
+
then memory, `AllowAccounts`/`AllowQos`, the partition QOS and priority tier.
|
|
154
|
+
- **Accounts & QOS**: every account/QOS pair you can submit under; `*` marks what
|
|
155
|
+
commands leave out because Slurm picks it anyway: the account when it is your only
|
|
156
|
+
one (with several, commands always name it, since sites such as Fir require that
|
|
157
|
+
for GPU jobs) and the account's default QOS. `Jobs` is your running jobs over the tightest per-user
|
|
158
|
+
cap, `GPUs` and `Wall` are the tightest GPU and wall-time caps from any scope, and
|
|
159
|
+
`FS` is your fair-share factor. Details list every cap with its usage: QOS per user,
|
|
160
|
+
per account, per job and per node, plus association limits on you and your account.
|
|
161
|
+
`∞` means no cap, `?` unknown.
|
|
162
|
+
- **Start estimates** (titled with the account/QOS probed): rows are request sizes
|
|
163
|
+
(each GPU type up to the tightest GPU cap, then CPU only), columns are walltimes. Each
|
|
164
|
+
cell is how long until the scheduler expects the job to start: `now`, a wait such as
|
|
165
|
+
`0-10:54:00`, `no` when it cannot run (Details gives the reason), or `-` above the
|
|
166
|
+
account/QOS wall-time cap. The earliest start in each row is underlined. Here a 1-day
|
|
167
|
+
L40S job starts sooner than a 3-hour one, because short jobs queue in the busier `b1`
|
|
168
|
+
partition.
|
|
169
|
+
- **Details** for an estimate shows the partition it would land in, the probe that
|
|
170
|
+
produced the estimate with the scheduler's reply, and the command to submit the same
|
|
171
|
+
request; click `Copy` after either to copy it. The probe has only what the estimate
|
|
172
|
+
depends on; the submit command drops `--test-only` and adds your email options and
|
|
173
|
+
`--output=/dev/null`, so no `slurm-<jobid>.out` file is left behind.
|
|
174
|
+
`--account`/`--qos` are left out when Slurm would pick them anyway.
|
|
175
|
+
- **Submit**: click the `Submit` label in Details to run an `sbatch` command, after a
|
|
176
|
+
dialog shows it and asks you to confirm; `Cancel` submits nothing. The job is submitted in the background (on the cluster's login node
|
|
177
|
+
for a remote tab), its id pops up, and My jobs refreshes; it holds the allocation with
|
|
178
|
+
`sleep infinity` until the time limit; its details in My jobs show the `scancel`
|
|
179
|
+
command that releases it. An `srun` command opens an interactive shell, so `Submit`
|
|
180
|
+
is not clickable for it: click `Copy` and run it in a terminal. A request the probe
|
|
181
|
+
was refused for is not submitted.
|
|
182
|
+
- **My jobs** lists your queued and running jobs: `Partition` is where it runs or was
|
|
183
|
+
submitted to (several for some pending jobs), `Start` is when a job started, or when
|
|
184
|
+
the scheduler expects a pending one to (`-` until it has planned it), `Nodes` is where
|
|
185
|
+
it runs, or the nodes planned for a pending job (dimmed, as they can still change),
|
|
186
|
+
and `Reason` is why a pending job waits. A job's details show the command that
|
|
187
|
+
attaches a shell to it (`srun --jobid=<id> --overlap --pty <shell>`, once it runs)
|
|
188
|
+
and the one that releases it (`scancel <id>`), each with `Copy`. Clicking `Release`
|
|
189
|
+
runs `scancel` after a dialog asks you to confirm (Cancel is selected first): a
|
|
190
|
+
running job is killed and its allocation released, a pending one leaves the queue.
|
|
191
|
+
|
|
192
|
+
## Configuration
|
|
193
|
+
|
|
194
|
+
All settings live in one file, `~/.config/sqtop/config.toml`
|
|
195
|
+
(`$XDG_CONFIG_HOME/sqtop/config.toml` if you set that): email (`[mail]`, `[smtp]`)
|
|
196
|
+
and cluster profiles (`[clusters.<name>]`). Click `Config` in the dashboard to edit it
|
|
197
|
+
in a form: the job email address and states, the hourly email's server, port, sender,
|
|
198
|
+
password and recipient, and one row per cluster (name, GPU counts picked from `pow2`,
|
|
199
|
+
`all` and `whole_node`, and ssh host) with `Add cluster` and `Remove`. `Cancel` closes
|
|
200
|
+
it unchanged. `Save` checks the settings (a problem is shown under the form, which stays
|
|
201
|
+
open), writes the file privately (`chmod 600`, since it holds the SMTP password) and
|
|
202
|
+
applies what changed without a restart: clusters added get tabs and removed ones lose
|
|
203
|
+
theirs, changed profiles and `[mail]` settings are probed again, and the hourly email
|
|
204
|
+
switches to a changed `[smtp]`.
|
|
205
|
+
|
|
206
|
+
Without the file, `sqtop` shows only the cluster you are logged in to, with no email
|
|
207
|
+
settings. The file is plain TOML, so you can also edit it by hand; the form rewrites it
|
|
208
|
+
without comments.
|
|
209
|
+
|
|
210
|
+
### Other clusters
|
|
211
|
+
|
|
212
|
+
Nothing is hardcoded per cluster: partitions, GPU types, time tiers, accounts and
|
|
213
|
+
limits are read from Slurm. A profile records only what Slurm cannot report, keyed by
|
|
214
|
+
the cluster name. To add a cluster, or a tab for one you are not logged in to, add a
|
|
215
|
+
row in the config form (`Config`); in the file it is a table:
|
|
216
|
+
|
|
217
|
+
```toml
|
|
218
|
+
[clusters.mycluster] # the ClusterName from `scontrol show config`
|
|
219
|
+
gpu_counts = "all" # "pow2" (1, 2, 4, ... default), "all" or "whole_node"
|
|
220
|
+
# (GPU jobs then take whole nodes: --exclusive --mem=0)
|
|
221
|
+
ssh = "login.mycluster.org" # a tab for it from anywhere; host or ~/.ssh/config alias
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
For example, the Alliance clusters this was written on need no rules, only an `ssh`
|
|
225
|
+
host for a tab, except `tamia`, which allocates GPUs by whole node:
|
|
226
|
+
|
|
227
|
+
```toml
|
|
228
|
+
[clusters.fir]
|
|
229
|
+
ssh = "fir.alliancecan.ca"
|
|
230
|
+
|
|
231
|
+
[clusters.killarney]
|
|
232
|
+
ssh = "killarney.alliancecan.ca"
|
|
233
|
+
|
|
234
|
+
[clusters.tamia]
|
|
235
|
+
ssh = "tamia.alliancecan.ca"
|
|
236
|
+
gpu_counts = "whole_node"
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
The walltimes probed are not a setting: they are the distinct time limits of the
|
|
240
|
+
partitions you can use, which is where routing changes, and `Edit request` overrides
|
|
241
|
+
them for a session.
|
|
242
|
+
|
|
243
|
+
### Whole nodes
|
|
244
|
+
|
|
245
|
+
Tick "Whole node" in the request editor (`Edit request`) to probe whole nodes: every command then
|
|
246
|
+
asks for `--exclusive --mem=0` (every CPU and all the memory) instead of `-c`/`--mem`,
|
|
247
|
+
and the GPU rows are each type's full node, such as `8x h100` or `4x l40s`. Untick it
|
|
248
|
+
to go back to the CPUs and memory in the editor.
|
|
249
|
+
|
|
250
|
+
On clusters that only allocate GPUs by node (`gpu_counts = "whole_node"`, such as
|
|
251
|
+
Tamia) the GPU rows always ask for the whole node this way, so a job that holds all of
|
|
252
|
+
a node's GPUs also gets its CPUs and memory; the CPU-only row keeps the editor's
|
|
253
|
+
values. The estimates panel then notes "GPUs by whole node".
|
|
254
|
+
|
|
255
|
+
### Email notifications
|
|
256
|
+
|
|
257
|
+
The `[mail]` table in your config (`Config`) adds `--mail-type` and `--mail-user` to every
|
|
258
|
+
command, so a job you submit from one emails you when it starts, ends or fails:
|
|
259
|
+
|
|
260
|
+
```toml
|
|
261
|
+
[mail]
|
|
262
|
+
user = "you@example.com"
|
|
263
|
+
type = "BEGIN,END,FAIL" # any of sbatch's --mail-type values
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
Only the commands to submit carry them: probes leave them out, since email does not
|
|
267
|
+
change when a job would start. Remove the table to leave email out, or clear the
|
|
268
|
+
address for a session with `Edit request`.
|
|
269
|
+
|
|
270
|
+
### Hourly email
|
|
271
|
+
|
|
272
|
+
Click `Email: off` in the dashboard to email the report now and every hour until you
|
|
273
|
+
quit `sqtop` (or click `Email: on` to stop). Each email covers the cluster you are on and every
|
|
274
|
+
remote tab you have opened, with each tab's current request. Every email has the subject
|
|
275
|
+
`sqtop` and replies to the first one, so your mail client keeps them in one
|
|
276
|
+
conversation instead of separate emails. Each starts with your job counts and what
|
|
277
|
+
happened since the previous email, followed by the text report:
|
|
278
|
+
|
|
279
|
+
```
|
|
280
|
+
killarney: 1 running, 2 pending. Since 14:00:
|
|
281
|
+
6284538 (wrap) started on kn021
|
|
282
|
+
6233018 (wrap) ended: TIMEOUT
|
|
283
|
+
6290112 (eval) submitted (Priority), expected to start 10-17 09:30
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
The server is read from `[smtp]` in your config (`Config`) when you turn it on:
|
|
287
|
+
|
|
288
|
+
```toml
|
|
289
|
+
[smtp]
|
|
290
|
+
server = "mail.example.org"
|
|
291
|
+
port = 587 # STARTTLS; 465 for SSL
|
|
292
|
+
sender = "you@example.org" # also the login
|
|
293
|
+
password = "..."
|
|
294
|
+
recipient = "you@example.org" # default: user in [mail]
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
The bottom bar says whether the hourly email is on (`Email: on`) or off (`Email: off`).
|
|
298
|
+
While it is on, the top bar shows when the next email goes out (`next email 16:37`),
|
|
299
|
+
and marks it `(last failed)` if one could not be sent. The thread and the jobs last reported are kept
|
|
300
|
+
in `~/.local/state/sqtop/mail.json`, so the next run of the dashboard continues the
|
|
301
|
+
same conversation; delete the file to start a new one. Gmail starts a new conversation
|
|
302
|
+
after 100 emails, about every four days.
|
|
303
|
+
|
|
304
|
+
### When `sacctmgr` fails
|
|
305
|
+
|
|
306
|
+
On some login nodes `sacctmgr` fails with "Connection refused" because `slurmdbd` runs
|
|
307
|
+
on the controller. Accounting is still enforced: `sqtop` reads limits from
|
|
308
|
+
`scontrol show assoc_mgr` instead. Without `sacctmgr` it cannot list your QOS
|
|
309
|
+
assignments, so it test-submits each cached account/QOS pair and hides the ones Slurm
|
|
310
|
+
rejects.
|
|
311
|
+
|
|
312
|
+
## Development
|
|
313
|
+
|
|
314
|
+
```bash
|
|
315
|
+
uv sync
|
|
316
|
+
uv run python -m unittest discover -s tests -t tests
|
|
317
|
+
uvx ruff check src tests
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
See [AGENTS.md](AGENTS.md) for the code layout and site-specific Slurm quirks.
|
|
321
|
+
|
|
322
|
+
## License
|
|
323
|
+
|
|
324
|
+
MIT; see [LICENSE](LICENSE).
|
sqtop-0.1.0/README.md
ADDED
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
# sqtop
|
|
2
|
+
|
|
3
|
+
A terminal dashboard for Slurm, in the spirit of
|
|
4
|
+
[hunoutl/slurmtop](https://github.com/hunoutl/slurmtop) and
|
|
5
|
+
[slmtop](https://github.com/dawnmy/slmtop), that answers "where can I run, under which
|
|
6
|
+
account/QOS, and when would it start?", and can email you that report every hour while
|
|
7
|
+
it runs.
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
killarney fir tamia
|
|
11
|
+
╸━━━━━━━━━╺━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
12
|
+
someone@klogin02 killarney Slurm 25.05.9 updated 13:49:06 (10s ago) · probed 13:49:06
|
|
13
|
+
╭─ Partitions ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
|
|
14
|
+
│ Partition Use CPU/node Mem/node GPU/node Load Free Idle Pend Max │
|
|
15
|
+
│ gpubase_h100_b1 yes 48/96 2011G 8x h100 ██████▒▒ 75% 4/80 h100 0/10 117 0-03:00:00 │
|
|
16
|
+
│ gpubase_h100_b2 yes 48/96 2011G 8x h100 ███████▒ 86% 1/64 h100 0/8 63 0-12:00:00 │
|
|
17
|
+
│ gpubase_interac yes 64 502G 4x l40s ███████░ 90% 6/100 l40s 0/25 1 0-03:00:00 │
|
|
18
|
+
│ gpubase_l40s_b1 yes 64 502G 4x l40s ███████▒ 90% 18/672 l40s 1/168 2571 0-03:00:00 │
|
|
19
|
+
│ gpubase_l40s_b3 yes 64 502G 4x l40s ███████▒ 88% 8/336 l40s 1/84 90 1-00:00:00 │
|
|
20
|
+
╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
|
|
21
|
+
╭─ Start estimates · aip-abc123/normal ──────────────────────────────────────────────────╮╭─ Accounts & QOS ─────────────────────────────────────────╮
|
|
22
|
+
│ Request 0-03:00:00 0-12:00:00 1-00:00:00 3-00:00:00 7-00:00:00 ││ Account QOS Jobs GPUs Wall FS │
|
|
23
|
+
│ 1x h100 0-22:05:00 1-05:38:00 3-02:01:00 7-23:35:00 39-23:02:00 ││ aip-abc123* interac 0/1 ∞ 0-03:00:00 0.14 │
|
|
24
|
+
│ 8x h100 1-04:16:00 1-10:21:00 3-06:44:00 8-11:56:00 40-05:13:00 ││ aip-abc123* normal* 0/∞ ∞ ∞ 0.14 │
|
|
25
|
+
│ 1x l40s 0-02:12:00 0-01:27:00 0-01:48:00 0-19:17:00 7-15:47:00 │╰────────────────── * left out of commands · enter: probe ─╯
|
|
26
|
+
│ 4x l40s 0-02:12:00 0-02:17:00 0-01:48:00 0-21:38:00 7-18:03:00 │╭─ My jobs ────────────────────────────────────────────────╮
|
|
27
|
+
│ CPU only 0-02:12:00 0-01:27:00 0-01:48:00 0-19:17:00 7-15:47:00 ││ Job Name St Start Time Nodes Reason │
|
|
28
|
+
│ ││ No jobs in the queue │
|
|
29
|
+
╰───────────────────────────────────────────────────────────────── sbatch -c4 --mem=32G ─╯╰──────────────────────────────────────────────────────────╯
|
|
30
|
+
╭─ Details ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
|
|
31
|
+
│ gpubase_h100_b1 UP usable · max time 0-03:00:00 · priority tier 1 │
|
|
32
|
+
│ Nodes 10 (5 mixed, 3 allocated, 2 unavailable) · pending jobs 117 │
|
|
33
|
+
│ 9 nodes: 48 CPUs / 2011 GB / 8x h100 · 1 node: 96 CPUs / 2011 GB / 8x h100 │
|
|
34
|
+
│ CPUs 104 free / 328 allocated / 96 unavailable of 528 · Memory 12045 GB free of 20117 GB │
|
|
35
|
+
╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
|
|
36
|
+
Refresh Re-probe Edit request Email: off Config Quit
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Requirements
|
|
40
|
+
|
|
41
|
+
- [uv](https://docs.astral.sh/uv/) (it fetches Python 3.13 if you do not have it)
|
|
42
|
+
- A Slurm login node (`scontrol` and `squeue` on `PATH`; estimates need `sbatch`/`srun`)
|
|
43
|
+
|
|
44
|
+
## Usage
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
uvx sqtop # run it from PyPI: one tab per cluster, this one first
|
|
48
|
+
uvx sqtop > report.txt # text report of this cluster when not a terminal
|
|
49
|
+
uv tool install sqtop # or install it once, then just type `sqtop`
|
|
50
|
+
|
|
51
|
+
# From a checkout
|
|
52
|
+
uv run sqtop
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
There are no options. The first tab is the cluster you are logged in to (from
|
|
56
|
+
`ClusterName` in `scontrol show config`), and it is the only one checked at startup.
|
|
57
|
+
Every other cluster with an `ssh` host in the [config file](#configuration) (Fir,
|
|
58
|
+
Killarney and Tamia) gets a tab too, but is only contacted, over ssh, once you open its
|
|
59
|
+
tab (click it). Every probe starts as 4 CPUs and 32 GB at each partition
|
|
60
|
+
time limit with `sbatch`; change a tab's request with `Edit request` (CPUs, memory,
|
|
61
|
+
walltimes, extra `sbatch` options), and click the command under Start estimates to
|
|
62
|
+
switch between `sbatch` and `srun`. The visible tab refreshes every minute and re-probes
|
|
63
|
+
every five. Click `Email: off` to email the report every hour until you quit
|
|
64
|
+
([Hourly email](#hourly-email)). Everything is a click: see [Mouse](#mouse).
|
|
65
|
+
|
|
66
|
+
Probes use `--test-only`, so nothing is submitted or cancelled until you confirm a
|
|
67
|
+
Submit or Release (see below), and it is safe to run on a shared login node. Run it on
|
|
68
|
+
the login node: on a compute node, such as inside an interactive job, `srun` probes fail
|
|
69
|
+
with "Requested operation is presently disabled".
|
|
70
|
+
|
|
71
|
+
### Remote clusters
|
|
72
|
+
|
|
73
|
+
Remote tabs run Slurm on the cluster's login node through `ssh`, with your
|
|
74
|
+
`~/.ssh/config` (aliases, users, keys). Nothing is sent to a remote cluster until you
|
|
75
|
+
open its tab, and only the visible tab refreshes.
|
|
76
|
+
|
|
77
|
+
sqtop never asks for a password or MFA. For a cluster that needs one, let ssh share
|
|
78
|
+
connections and log in with `ssh` in another terminal first; sqtop reuses that
|
|
79
|
+
connection:
|
|
80
|
+
|
|
81
|
+
```
|
|
82
|
+
# ~/.ssh/config
|
|
83
|
+
Host *.alliancecan.ca
|
|
84
|
+
ControlMaster auto
|
|
85
|
+
ControlPath ~/.ssh/cm-%C
|
|
86
|
+
ControlPersist 4h
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
After `ssh fir.alliancecan.ca`, the connection stays open for 4 hours after your last
|
|
90
|
+
session there closes. With keys that log in without a prompt, nothing is needed:
|
|
91
|
+
sqtop opens its own shared connection, which closes 10 minutes after the last use.
|
|
92
|
+
A tab that cannot connect shows ssh's error and how to connect; then click `Refresh`.
|
|
93
|
+
|
|
94
|
+
The text report printed when output is not a terminal covers the cluster you are on;
|
|
95
|
+
it covers the remote ones only where Slurm is not available.
|
|
96
|
+
|
|
97
|
+
Each refresh of a remote tab is one ssh session, and the cache of limits is fetched
|
|
98
|
+
only for your accounts and QOS, because login nodes can take seconds to start a
|
|
99
|
+
session and the full cache can be tens of MB. Commands for a remote cluster are shown
|
|
100
|
+
with its host as the prompt (`fir.alliancecan.ca$ sbatch ...`): run them there.
|
|
101
|
+
|
|
102
|
+
### Mouse
|
|
103
|
+
|
|
104
|
+
sqtop has no keyboard shortcuts: everything is a click. The bar at the bottom holds
|
|
105
|
+
the dashboard's actions, and each dialog closes with its own buttons.
|
|
106
|
+
|
|
107
|
+
| Click | Action |
|
|
108
|
+
| --- | --- |
|
|
109
|
+
| a cluster tab | Show that cluster |
|
|
110
|
+
| a row or cell | Select it; the Details panel follows the selection |
|
|
111
|
+
| a highlighted Accounts & QOS row | Probe with that account/QOS |
|
|
112
|
+
| the Partitions title | Switch between Partitions and Nodes by hardware |
|
|
113
|
+
| the account/QOS above the estimates | Probe with the next account/QOS |
|
|
114
|
+
| the command under Start estimates | Switch between `sbatch` and `srun` probes |
|
|
115
|
+
| `Submit` in Details | Submit the selected `sbatch` request, after you confirm |
|
|
116
|
+
| `Copy` after a command in Details | Copy that command |
|
|
117
|
+
| `Release` in a job's Details | Release the job with `scancel`, after you confirm |
|
|
118
|
+
| `Refresh` / `Re-probe` | Refresh everything / re-probe now |
|
|
119
|
+
| `Edit request` | Edit the probe request: whole node, CPUs, memory, walltimes, extra options such as `--partition` or `--constraint`, and the email address (blank for none) |
|
|
120
|
+
| `Email: off` / `Email: on` | Email the report now and every hour until you quit / stop; the label says which is on |
|
|
121
|
+
| `Config` | Edit the [config](#configuration) in a form; saving writes the file and applies it |
|
|
122
|
+
| `Quit` | Quit |
|
|
123
|
+
|
|
124
|
+
## Reading the dashboard
|
|
125
|
+
|
|
126
|
+
- **Partitions**: `Use` says whether your accounts, QOS and Unix groups may submit
|
|
127
|
+
there. `CPU/node`, `Mem/node` and `GPU/node` are each node's hardware (CPUs exclude
|
|
128
|
+
reserved cores); a partition with two kinds of node shows both (`48/96`), with more
|
|
129
|
+
a range. `Load` is the share of GPUs (CPUs on CPU-only partitions) in use: `█`
|
|
130
|
+
allocated, `▒` unavailable (down, drained, reserved), `░` free. `Free` is free/total
|
|
131
|
+
per GPU type, `Idle` counts wholly idle nodes, `Pend` counts pending jobs from all
|
|
132
|
+
users, and `Max` is the time limit. Details list each kind of node with its count,
|
|
133
|
+
then memory, `AllowAccounts`/`AllowQos`, the partition QOS and priority tier.
|
|
134
|
+
- **Accounts & QOS**: every account/QOS pair you can submit under; `*` marks what
|
|
135
|
+
commands leave out because Slurm picks it anyway: the account when it is your only
|
|
136
|
+
one (with several, commands always name it, since sites such as Fir require that
|
|
137
|
+
for GPU jobs) and the account's default QOS. `Jobs` is your running jobs over the tightest per-user
|
|
138
|
+
cap, `GPUs` and `Wall` are the tightest GPU and wall-time caps from any scope, and
|
|
139
|
+
`FS` is your fair-share factor. Details list every cap with its usage: QOS per user,
|
|
140
|
+
per account, per job and per node, plus association limits on you and your account.
|
|
141
|
+
`∞` means no cap, `?` unknown.
|
|
142
|
+
- **Start estimates** (titled with the account/QOS probed): rows are request sizes
|
|
143
|
+
(each GPU type up to the tightest GPU cap, then CPU only), columns are walltimes. Each
|
|
144
|
+
cell is how long until the scheduler expects the job to start: `now`, a wait such as
|
|
145
|
+
`0-10:54:00`, `no` when it cannot run (Details gives the reason), or `-` above the
|
|
146
|
+
account/QOS wall-time cap. The earliest start in each row is underlined. Here a 1-day
|
|
147
|
+
L40S job starts sooner than a 3-hour one, because short jobs queue in the busier `b1`
|
|
148
|
+
partition.
|
|
149
|
+
- **Details** for an estimate shows the partition it would land in, the probe that
|
|
150
|
+
produced the estimate with the scheduler's reply, and the command to submit the same
|
|
151
|
+
request; click `Copy` after either to copy it. The probe has only what the estimate
|
|
152
|
+
depends on; the submit command drops `--test-only` and adds your email options and
|
|
153
|
+
`--output=/dev/null`, so no `slurm-<jobid>.out` file is left behind.
|
|
154
|
+
`--account`/`--qos` are left out when Slurm would pick them anyway.
|
|
155
|
+
- **Submit**: click the `Submit` label in Details to run an `sbatch` command, after a
|
|
156
|
+
dialog shows it and asks you to confirm; `Cancel` submits nothing. The job is submitted in the background (on the cluster's login node
|
|
157
|
+
for a remote tab), its id pops up, and My jobs refreshes; it holds the allocation with
|
|
158
|
+
`sleep infinity` until the time limit; its details in My jobs show the `scancel`
|
|
159
|
+
command that releases it. An `srun` command opens an interactive shell, so `Submit`
|
|
160
|
+
is not clickable for it: click `Copy` and run it in a terminal. A request the probe
|
|
161
|
+
was refused for is not submitted.
|
|
162
|
+
- **My jobs** lists your queued and running jobs: `Partition` is where it runs or was
|
|
163
|
+
submitted to (several for some pending jobs), `Start` is when a job started, or when
|
|
164
|
+
the scheduler expects a pending one to (`-` until it has planned it), `Nodes` is where
|
|
165
|
+
it runs, or the nodes planned for a pending job (dimmed, as they can still change),
|
|
166
|
+
and `Reason` is why a pending job waits. A job's details show the command that
|
|
167
|
+
attaches a shell to it (`srun --jobid=<id> --overlap --pty <shell>`, once it runs)
|
|
168
|
+
and the one that releases it (`scancel <id>`), each with `Copy`. Clicking `Release`
|
|
169
|
+
runs `scancel` after a dialog asks you to confirm (Cancel is selected first): a
|
|
170
|
+
running job is killed and its allocation released, a pending one leaves the queue.
|
|
171
|
+
|
|
172
|
+
## Configuration
|
|
173
|
+
|
|
174
|
+
All settings live in one file, `~/.config/sqtop/config.toml`
|
|
175
|
+
(`$XDG_CONFIG_HOME/sqtop/config.toml` if you set that): email (`[mail]`, `[smtp]`)
|
|
176
|
+
and cluster profiles (`[clusters.<name>]`). Click `Config` in the dashboard to edit it
|
|
177
|
+
in a form: the job email address and states, the hourly email's server, port, sender,
|
|
178
|
+
password and recipient, and one row per cluster (name, GPU counts picked from `pow2`,
|
|
179
|
+
`all` and `whole_node`, and ssh host) with `Add cluster` and `Remove`. `Cancel` closes
|
|
180
|
+
it unchanged. `Save` checks the settings (a problem is shown under the form, which stays
|
|
181
|
+
open), writes the file privately (`chmod 600`, since it holds the SMTP password) and
|
|
182
|
+
applies what changed without a restart: clusters added get tabs and removed ones lose
|
|
183
|
+
theirs, changed profiles and `[mail]` settings are probed again, and the hourly email
|
|
184
|
+
switches to a changed `[smtp]`.
|
|
185
|
+
|
|
186
|
+
Without the file, `sqtop` shows only the cluster you are logged in to, with no email
|
|
187
|
+
settings. The file is plain TOML, so you can also edit it by hand; the form rewrites it
|
|
188
|
+
without comments.
|
|
189
|
+
|
|
190
|
+
### Other clusters
|
|
191
|
+
|
|
192
|
+
Nothing is hardcoded per cluster: partitions, GPU types, time tiers, accounts and
|
|
193
|
+
limits are read from Slurm. A profile records only what Slurm cannot report, keyed by
|
|
194
|
+
the cluster name. To add a cluster, or a tab for one you are not logged in to, add a
|
|
195
|
+
row in the config form (`Config`); in the file it is a table:
|
|
196
|
+
|
|
197
|
+
```toml
|
|
198
|
+
[clusters.mycluster] # the ClusterName from `scontrol show config`
|
|
199
|
+
gpu_counts = "all" # "pow2" (1, 2, 4, ... default), "all" or "whole_node"
|
|
200
|
+
# (GPU jobs then take whole nodes: --exclusive --mem=0)
|
|
201
|
+
ssh = "login.mycluster.org" # a tab for it from anywhere; host or ~/.ssh/config alias
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
For example, the Alliance clusters this was written on need no rules, only an `ssh`
|
|
205
|
+
host for a tab, except `tamia`, which allocates GPUs by whole node:
|
|
206
|
+
|
|
207
|
+
```toml
|
|
208
|
+
[clusters.fir]
|
|
209
|
+
ssh = "fir.alliancecan.ca"
|
|
210
|
+
|
|
211
|
+
[clusters.killarney]
|
|
212
|
+
ssh = "killarney.alliancecan.ca"
|
|
213
|
+
|
|
214
|
+
[clusters.tamia]
|
|
215
|
+
ssh = "tamia.alliancecan.ca"
|
|
216
|
+
gpu_counts = "whole_node"
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
The walltimes probed are not a setting: they are the distinct time limits of the
|
|
220
|
+
partitions you can use, which is where routing changes, and `Edit request` overrides
|
|
221
|
+
them for a session.
|
|
222
|
+
|
|
223
|
+
### Whole nodes
|
|
224
|
+
|
|
225
|
+
Tick "Whole node" in the request editor (`Edit request`) to probe whole nodes: every command then
|
|
226
|
+
asks for `--exclusive --mem=0` (every CPU and all the memory) instead of `-c`/`--mem`,
|
|
227
|
+
and the GPU rows are each type's full node, such as `8x h100` or `4x l40s`. Untick it
|
|
228
|
+
to go back to the CPUs and memory in the editor.
|
|
229
|
+
|
|
230
|
+
On clusters that only allocate GPUs by node (`gpu_counts = "whole_node"`, such as
|
|
231
|
+
Tamia) the GPU rows always ask for the whole node this way, so a job that holds all of
|
|
232
|
+
a node's GPUs also gets its CPUs and memory; the CPU-only row keeps the editor's
|
|
233
|
+
values. The estimates panel then notes "GPUs by whole node".
|
|
234
|
+
|
|
235
|
+
### Email notifications
|
|
236
|
+
|
|
237
|
+
The `[mail]` table in your config (`Config`) adds `--mail-type` and `--mail-user` to every
|
|
238
|
+
command, so a job you submit from one emails you when it starts, ends or fails:
|
|
239
|
+
|
|
240
|
+
```toml
|
|
241
|
+
[mail]
|
|
242
|
+
user = "you@example.com"
|
|
243
|
+
type = "BEGIN,END,FAIL" # any of sbatch's --mail-type values
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
Only the commands to submit carry them: probes leave them out, since email does not
|
|
247
|
+
change when a job would start. Remove the table to leave email out, or clear the
|
|
248
|
+
address for a session with `Edit request`.
|
|
249
|
+
|
|
250
|
+
### Hourly email
|
|
251
|
+
|
|
252
|
+
Click `Email: off` in the dashboard to email the report now and every hour until you
|
|
253
|
+
quit `sqtop` (or click `Email: on` to stop). Each email covers the cluster you are on and every
|
|
254
|
+
remote tab you have opened, with each tab's current request. Every email has the subject
|
|
255
|
+
`sqtop` and replies to the first one, so your mail client keeps them in one
|
|
256
|
+
conversation instead of separate emails. Each starts with your job counts and what
|
|
257
|
+
happened since the previous email, followed by the text report:
|
|
258
|
+
|
|
259
|
+
```
|
|
260
|
+
killarney: 1 running, 2 pending. Since 14:00:
|
|
261
|
+
6284538 (wrap) started on kn021
|
|
262
|
+
6233018 (wrap) ended: TIMEOUT
|
|
263
|
+
6290112 (eval) submitted (Priority), expected to start 10-17 09:30
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
The server is read from `[smtp]` in your config (`Config`) when you turn it on:
|
|
267
|
+
|
|
268
|
+
```toml
|
|
269
|
+
[smtp]
|
|
270
|
+
server = "mail.example.org"
|
|
271
|
+
port = 587 # STARTTLS; 465 for SSL
|
|
272
|
+
sender = "you@example.org" # also the login
|
|
273
|
+
password = "..."
|
|
274
|
+
recipient = "you@example.org" # default: user in [mail]
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
The bottom bar says whether the hourly email is on (`Email: on`) or off (`Email: off`).
|
|
278
|
+
While it is on, the top bar shows when the next email goes out (`next email 16:37`),
|
|
279
|
+
and marks it `(last failed)` if one could not be sent. The thread and the jobs last reported are kept
|
|
280
|
+
in `~/.local/state/sqtop/mail.json`, so the next run of the dashboard continues the
|
|
281
|
+
same conversation; delete the file to start a new one. Gmail starts a new conversation
|
|
282
|
+
after 100 emails, about every four days.
|
|
283
|
+
|
|
284
|
+
### When `sacctmgr` fails
|
|
285
|
+
|
|
286
|
+
On some login nodes `sacctmgr` fails with "Connection refused" because `slurmdbd` runs
|
|
287
|
+
on the controller. Accounting is still enforced: `sqtop` reads limits from
|
|
288
|
+
`scontrol show assoc_mgr` instead. Without `sacctmgr` it cannot list your QOS
|
|
289
|
+
assignments, so it test-submits each cached account/QOS pair and hides the ones Slurm
|
|
290
|
+
rejects.
|
|
291
|
+
|
|
292
|
+
## Development
|
|
293
|
+
|
|
294
|
+
```bash
|
|
295
|
+
uv sync
|
|
296
|
+
uv run python -m unittest discover -s tests -t tests
|
|
297
|
+
uvx ruff check src tests
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
See [AGENTS.md](AGENTS.md) for the code layout and site-specific Slurm quirks.
|
|
301
|
+
|
|
302
|
+
## License
|
|
303
|
+
|
|
304
|
+
MIT; see [LICENSE](LICENSE).
|