|
5 | 5 | # Apache 2 License |
6 | 6 |
|
7 | 7 | def to_gres_options(stdout): |
| 8 | + """ Convert sinfo output into a list of GRES options for an Ondemand `select` |
| 9 | + widget. |
| 10 | +
|
| 11 | + Parameters: |
| 12 | + stdout: Text from `sinfo --noheader --format "%R %G"` |
| 13 | +
|
| 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. |
| 20 | +
|
| 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'] |
| 26 | +
|
| 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 | + """ |
8 | 30 | gres_data = {} # k=gres_opt, v=[label, max_count] # where gres_opt is what would be passed to --gres |
9 | 31 | gres_data['none'] = ['None', 0] |
10 | 32 |
|
11 | 33 | for line in stdout.splitlines(): |
12 | | - if '(null)' in line: |
13 | | - continue |
14 | | - partition, gres = line.split(' ') |
15 | | - gres_name, gres_type, gres_number_cores = gres.split(':', maxsplit=2) |
16 | | - gres_count, gres_cores = gres_number_cores.split('(') |
17 | | - |
18 | | - for gres_opt in [gres_name, f'{gres_name}:{gres_type}']: |
19 | | - if gres_opt not in gres_data: |
20 | | - label = f'{gres_type} {gres_name}' if ':' in gres_opt else f'Any {gres_opt}' |
21 | | - gres_data[gres_opt] = [label, gres_count] |
22 | | - elif gres_count > gres_data[gres_name][1]: |
23 | | - gres_data[gres_opt][1] = gres_count |
| 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 |
| 48 | + |
24 | 49 | gres_options = [] |
25 | 50 | for gres_opt in gres_data: |
26 | 51 | max_count = gres_data[gres_opt][1] |
|
0 commit comments