|
4 | 4 | # Copyright: (c) 2025, StackHPC |
5 | 5 | # Apache 2 License |
6 | 6 |
|
| 7 | + |
7 | 8 | def to_gres_options(stdout): |
8 | | - """ Convert sinfo output into a list of GRES options for an Ondemand `select` |
9 | | - widget. |
| 9 | + """Convert sinfo output into a list of GRES options for an Ondemand `select` |
| 10 | + widget. |
| 11 | +
|
| 12 | + Parameters: |
| 13 | + stdout: Text from `sinfo --noheader --format "%R %G"` |
10 | 14 |
|
11 | | - Parameters: |
12 | | - stdout: Text from `sinfo --noheader --format "%R %G"` |
| 15 | + Returns a list of [label, value] items. This is the format required for |
| 16 | + the `options` attribute of a `select` widget [1] where: |
| 17 | + - value (str) is a valid entry for the srun/sbatch --gres option [2]. |
| 18 | + - label (str) is a user-friendly label with gres name, gres type and |
| 19 | + maximum gres count where relevant. |
| 20 | + The returned list will always include an entry for no GRES request. |
13 | 21 |
|
14 | | - Returns a list of [label, value] items. This is the format required for |
15 | | - the `options` attribute of a `select` widget [1] where: |
16 | | - - value (str) is a valid entry for the srun/sbatch --gres option [2]. |
17 | | - - label (str) is a user-friendly label with gres name, gres type and |
18 | | - maximum gres count where relevant. |
19 | | - The returned list will always include an entry for no GRES request. |
| 22 | + For example with a single GRES defined of `gpu:H200:8' the following |
| 23 | + entries are returned: |
| 24 | + - ['None', 'none'] |
| 25 | + - ['Any gpu (max count: 8)', 'gpu'] |
| 26 | + - ['H200 gpu' (max count: 8)', 'gpu:H200'] |
20 | 27 |
|
21 | | - For example with a single GRES defined of `gpu:H200:8' the following |
22 | | - entries are returned: |
23 | | - - ['None', 'none'] |
24 | | - - ['Any gpu (max count: 8)', 'gpu'] |
25 | | - - ['H200 gpu' (max count: 8)', 'gpu:H200'] |
| 28 | + [1] https://osc.github.io/ood-documentation/latest/how-tos/app-development/interactive/form-widgets.html#form-widgets |
| 29 | + [2] https://slurm.schedmd.com/srun.html#OPT_gres |
| 30 | + """ |
| 31 | + gres_data = ( |
| 32 | + {} |
| 33 | + ) # k=gres_opt, v=[label, max_count] # where gres_opt is what would be passed to --gres |
| 34 | + gres_data["none"] = ["None", 0] |
26 | 35 |
|
27 | | - [1] https://osc.github.io/ood-documentation/latest/how-tos/app-development/interactive/form-widgets.html#form-widgets |
28 | | - [2] https://slurm.schedmd.com/srun.html#OPT_gres |
29 | | - """ |
30 | | - gres_data = {} # k=gres_opt, v=[label, max_count] # where gres_opt is what would be passed to --gres |
31 | | - gres_data['none'] = ['None', 0] |
32 | | - |
33 | | - for line in stdout.splitlines(): |
34 | | - partition, gres_definitions = line.split() # e.g. 'part1 gpu:H200:8(S:0-1),test:foo:1', or 'part2 (null)' |
35 | | - for gres in gres_definitions.split(','): |
36 | | - if '(null)' in gres: |
37 | | - continue |
38 | | - gres_name, gres_type, gres_count_cores = gres.split(':', maxsplit=2) |
39 | | - gres_count = gres_count_cores.split('(')[0] # may or may not have the e.g. '(S:0-1)' core definition |
40 | | - for gres_opt in [gres_name, f'{gres_name}:{gres_type}']: |
41 | | - if gres_opt not in gres_data: |
42 | | - label = f'{gres_type} {gres_name}' if ':' in gres_opt else f'Any {gres_opt}' |
43 | | - gres_data[gres_opt] = [label, gres_count] |
44 | | - elif len(gres_data[gres_name]) == 1: |
45 | | - raise ValueError(gres_data[gres_name]) |
46 | | - elif gres_count > gres_data[gres_name][1]: |
47 | | - gres_data[gres_opt][1] = gres_count |
| 36 | + for line in stdout.splitlines(): |
| 37 | + partition, gres_definitions = ( |
| 38 | + line.split() |
| 39 | + ) # e.g. 'part1 gpu:H200:8(S:0-1),test:foo:1', or 'part2 (null)' |
| 40 | + for gres in gres_definitions.split(","): |
| 41 | + if "(null)" in gres: |
| 42 | + continue |
| 43 | + gres_name, gres_type, gres_count_cores = gres.split(":", maxsplit=2) |
| 44 | + gres_count = gres_count_cores.split("(")[ |
| 45 | + 0 |
| 46 | + ] # may or may not have the e.g. '(S:0-1)' core definition |
| 47 | + for gres_opt in [gres_name, f"{gres_name}:{gres_type}"]: |
| 48 | + if gres_opt not in gres_data: |
| 49 | + label = ( |
| 50 | + f"{gres_type} {gres_name}" |
| 51 | + if ":" in gres_opt |
| 52 | + else f"Any {gres_opt}" |
| 53 | + ) |
| 54 | + gres_data[gres_opt] = [label, gres_count] |
| 55 | + elif len(gres_data[gres_name]) == 1: |
| 56 | + raise ValueError(gres_data[gres_name]) |
| 57 | + elif gres_count > gres_data[gres_name][1]: |
| 58 | + gres_data[gres_opt][1] = gres_count |
48 | 59 |
|
49 | | - gres_options = [] |
50 | | - for gres_opt in gres_data: |
51 | | - max_count = gres_data[gres_opt][1] |
52 | | - label = gres_data[gres_opt][0] |
53 | | - if gres_opt != 'none': |
54 | | - label += f' (max count: {max_count})' |
55 | | - gres_options.append((label, gres_opt)) |
56 | | - return gres_options |
| 60 | + gres_options = [] |
| 61 | + for gres_opt in gres_data: |
| 62 | + max_count = gres_data[gres_opt][1] |
| 63 | + label = gres_data[gres_opt][0] |
| 64 | + if gres_opt != "none": |
| 65 | + label += f" (max count: {max_count})" |
| 66 | + gres_options.append((label, gres_opt)) |
| 67 | + return gres_options |
57 | 68 |
|
58 | 69 |
|
59 | 70 | # pylint: disable=useless-object-inheritance |
|
0 commit comments