Skip to content

Commit ae12fac

Browse files
authored
Merge pull request #5246 from grondo/flux-resource-R
flux-resource: add `R` subcommand
2 parents ade38ce + 3996425 commit ae12fac

File tree

9 files changed

+99
-17
lines changed

9 files changed

+99
-17
lines changed

doc/man1/flux-resource.rst

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,21 @@ COMMANDS
8080
specify ranks or hosts which do not exist, the result will be filtered
8181
to include only those ranks or hosts that are present in *TARGETS*.
8282

83+
**R** [-s STATE,..] [-i TARGETS]
84+
Emit an RFC 20 Resource Set on stdout.
85+
86+
With *-s,--states=STATE,...*, the set of resource states is restricted
87+
to a list of provided states. Valid states include "up", "down",
88+
"allocated", "free", and "all". Note that the scheduler represents
89+
offline, excluded, and drained resources as "down" due to the simplified
90+
interface with the resource service defined by RFC 27.
91+
92+
With *-i, --include=TARGETS*, the results are filtered to only include
93+
resources matching **TARGETS**, which may be specified either as an idset
94+
of broker ranks or list of hosts in hostlist form. It is not an error to
95+
specify ranks or hosts which do not exist, the result will be filtered
96+
to include only those ranks or hosts that are present in *TARGETS*.
97+
8398
**status** [-n] [-o FORMAT] [-s STATE,...] [-i TARGETS] [--skip-empty]
8499
Show system view of resources. This command queries both the resource
85100
service and scheduler to identify resources that are available,

etc/completions/flux.pre

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -288,7 +288,7 @@ _flux_mini()
288288
# flux-resource(1) completions
289289
_flux_resource()
290290
{
291-
local subcmds="drain undrain status list info reload"
291+
local subcmds="drain undrain status list R info reload"
292292
local cmd=$1
293293

294294
local reload_OPTS="\
@@ -311,6 +311,11 @@ _flux_resource()
311311
local status_OPTS="\
312312
${list_OPTS} \
313313
"
314+
local R_OPTS="\
315+
-h --help \
316+
-s --states= \
317+
-i --include= \
318+
"
314319
local undrain_OPTS="\
315320
-h --help \
316321
"

src/cmd/flux-resource.py

Lines changed: 55 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -506,24 +506,15 @@ def resources_uniq_lines(resources, states, formatter, config):
506506
return lines
507507

508508

509-
def list_handler(args):
509+
def get_resource_list(args):
510+
"""
511+
Common function for list_handler() and emit_R()
512+
"""
510513
valid_states = ["up", "down", "allocated", "free", "all"]
511-
headings = {
512-
"state": "STATE",
513-
"queue": "QUEUE",
514-
"properties": "PROPERTIES",
515-
"propertiesx": "PROPERTIES",
516-
"nnodes": "NNODES",
517-
"ncores": "NCORES",
518-
"ngpus": "NGPUS",
519-
"ranks": "RANKS",
520-
"nodelist": "NODELIST",
521-
"rlist": "LIST",
522-
}
523514
config = None
524515

525-
states = args.states.split(",")
526-
for state in states:
516+
args.states = args.states.split(",")
517+
for state in args.states:
527518
if state not in valid_states:
528519
LOGGER.error("Invalid resource state %s specified", state)
529520
sys.exit(1)
@@ -544,11 +535,28 @@ def list_handler(args):
544535
resources.filter(include=args.include)
545536
except (ValueError, TypeError) as exc:
546537
raise ValueError(f"--include: {exc}") from None
538+
return resources, config
539+
540+
541+
def list_handler(args):
542+
headings = {
543+
"state": "STATE",
544+
"queue": "QUEUE",
545+
"properties": "PROPERTIES",
546+
"propertiesx": "PROPERTIES",
547+
"nnodes": "NNODES",
548+
"ncores": "NCORES",
549+
"ngpus": "NGPUS",
550+
"ranks": "RANKS",
551+
"nodelist": "NODELIST",
552+
"rlist": "LIST",
553+
}
554+
resources, config = get_resource_list(args)
547555

548556
fmt = FluxResourceConfig("list").load().get_format_string(args.format)
549557
formatter = flux.util.OutputFormat(fmt, headings=headings)
550558

551-
lines = resources_uniq_lines(resources, states, formatter, config)
559+
lines = resources_uniq_lines(resources, args.states, formatter, config)
552560
formatter.print_items(lines.values(), no_header=args.no_header)
553561

554562

@@ -561,6 +569,19 @@ def info(args):
561569
list_handler(args)
562570

563571

572+
def emit_R(args):
573+
"""Emit R in JSON on stdout for requested set of resources"""
574+
resources, config = get_resource_list(args)
575+
576+
rset = ResourceSet()
577+
for state in args.states:
578+
try:
579+
rset.add(resources[state])
580+
except AttributeError:
581+
raise ValueError(f"unknown state {state}")
582+
print(rset.encode())
583+
584+
564585
LOGGER = logging.getLogger("flux-resource")
565586

566587

@@ -758,6 +779,24 @@ def main():
758779
help="allow resources to contain invalid ranks",
759780
)
760781

782+
R_parser = subparsers.add_parser("R", formatter_class=flux.util.help_formatter())
783+
R_parser.set_defaults(func=emit_R)
784+
R_parser.add_argument(
785+
"-s",
786+
"--states",
787+
metavar="STATE,...",
788+
default="all",
789+
help="Emit R for resources in given states",
790+
)
791+
R_parser.add_argument(
792+
"-i",
793+
"--include",
794+
metavar="TARGETS",
795+
help="Include only specified targets in output set. TARGETS may be "
796+
+ "provided as an idset or hostlist.",
797+
)
798+
R_parser.add_argument("--from-stdin", action="store_true", help=argparse.SUPPRESS)
799+
761800
args = parser.parse_args()
762801
args.func(args)
763802

t/flux-resource/list/fluxion.R

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{"version": 1, "execution": {"R_lite": [{"rank": "0-3", "children": {"core": "0-3"}}], "starttime": 0.0, "expiration": 0.0}}

t/flux-resource/list/missing.R

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{"version": 1, "execution": {"R_lite": [{"rank": "0-3", "children": {"core": "0-3"}}], "starttime": 0.0, "expiration": 0.0}}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{"version": 1, "execution": {"R_lite": [{"rank": "0-3", "children": {"core": "0-3"}}], "starttime": 0.0, "expiration": 0.0}}

t/flux-resource/list/normal-new.R

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{"version": 1, "execution": {"R_lite": [{"rank": "0-4", "children": {"core": "0-3"}}], "starttime": 0.0, "expiration": 0.0, "nodelist": ["pi[3,0-2,4]"], "properties": {"8g": "0-2"}}}

t/flux-resource/list/null.R

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{"version": 1, "execution": {"R_lite": [{"rank": "0-3", "children": {"core": "0-3"}}], "starttime": 0.0, "expiration": 0.0}}

t/t2350-resource-list.t

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,11 @@ for input in ${SHARNESS_TEST_SRCDIR}/flux-resource/list/*.json; do
5353
test_debug "cat ${name}-info.output" &&
5454
test_cmp ${base}-info.expected ${name}-info.output
5555
'
56+
test_expect_success "flux-resource R input check: $testname" '
57+
flux resource R --from-stdin < $input > ${name}-R.output 2>&1 &&
58+
test_debug "cat ${name}-info.output" &&
59+
test_cmp ${base}.R ${name}-R.output
60+
'
5661
done
5762

5863
# Ensure all tested inputs can also work with --include
@@ -73,6 +78,11 @@ for input in ${SHARNESS_TEST_SRCDIR}/flux-resource/list/*.json; do
7378
test_debug "cat ${name}-info-include.output" &&
7479
grep "1 Node" ${name}-info-include.output
7580
'
81+
test_expect_success "flux-resource R input ---include check: $testname" '
82+
flux resource R --from-stdin -i0 < $input \
83+
> ${name}-info-R.output &&
84+
test "$(flux R decode --count=node <${name}-info-R.output)" -eq 1
85+
'
7686
done
7787

7888
test_expect_success 'flux-resource list supports --include' '
@@ -99,6 +109,14 @@ test_expect_success 'flux-resource list: --include works with invalid host' '
99109
test_debug "cat include-invalid-hosts.out" &&
100110
grep "^0" include-invalid-hosts.out
101111
'
112+
test_expect_success 'flux-resource R supports --states' '
113+
flux resource R --from-stdin -s all <$INPUT >all.R &&
114+
test $(flux R decode --count=node <all.R) -eq 5 &&
115+
flux resource R --from-stdin -s up <$INPUT >up.R &&
116+
test $(flux R decode --count=node <up.R) -eq 5 &&
117+
flux resource R --from-stdin -s down <$INPUT >down.R &&
118+
test $(flux R decode --count=node <down.R) -eq 0
119+
'
102120
test_expect_success 'create test input with properties' '
103121
cat <<-EOF >properties-test.in
104122
{

0 commit comments

Comments
 (0)