From 67be18f1217deaef9b047a326abe0d0f44aceb40 Mon Sep 17 00:00:00 2001 From: "Mark A. Grondona" Date: Wed, 18 Oct 2023 14:09:10 -0700 Subject: [PATCH 1/6] testsuite: remove job shell standalone tests Problem: There exist a set of job shell standalone tests that use the --standalone option of flux-shell(1), but this option will soon be removed. Remove the job shell standalone tests. They appear to mostly be duplicates of other, non-standalone tests in the testsuite anyway. Move one test (a test for invalid arg handling) to the main job shell sharness test. --- t/Makefile.am | 2 - t/t2601-job-shell-standalone.t | 181 ---------- t/t2602-job-shell.t | 5 + ...-job-shell-output-redirection-standalone.t | 313 ------------------ 4 files changed, 5 insertions(+), 496 deletions(-) delete mode 100755 t/t2601-job-shell-standalone.t delete mode 100755 t/t2605-job-shell-output-redirection-standalone.t diff --git a/t/Makefile.am b/t/Makefile.am index 1125f0de749c..b7016eea90d6 100644 --- a/t/Makefile.am +++ b/t/Makefile.am @@ -192,11 +192,9 @@ TESTSCRIPTS = \ t2500-job-attach.t \ t2501-job-status.t \ t2600-job-shell-rcalc.t \ - t2601-job-shell-standalone.t \ t2602-job-shell.t \ t2603-job-shell-initrc.t \ t2604-job-shell-affinity.t \ - t2605-job-shell-output-redirection-standalone.t \ t2606-job-shell-output-redirection.t \ t2607-job-shell-input.t \ t2608-job-shell-log.t \ diff --git a/t/t2601-job-shell-standalone.t b/t/t2601-job-shell-standalone.t deleted file mode 100755 index 67c5b14aa0f2..000000000000 --- a/t/t2601-job-shell-standalone.t +++ /dev/null @@ -1,181 +0,0 @@ -#!/bin/sh -# -test_description='Test flux-shell in --standalone mode' - -. `dirname $0`/sharness.sh - -# Run flux-shell under flux command to get correct paths -FLUX_SHELL="run_timeout 300 flux ${FLUX_BUILD_DIR}/src/shell/flux-shell" - -PMI_INFO=${FLUX_BUILD_DIR}/src/common/libpmi/test_pmi_info -KVSTEST=${FLUX_BUILD_DIR}/src/common/libpmi/test_kvstest - -unset FLUX_URI - -test_expect_success 'flux-shell: generate 1-task jobspec and matching R' ' - flux run --dry-run -N1 -n1 echo Hi >j1 && - cat >R1 <<-EOT - {"version": 1, "execution":{ "R_lite":[ - { "children": { "core": "0" }, "rank": "0" } - ]}} - EOT -' -test_expect_success 'flux-shell: run 1-task echo job' ' - ${FLUX_SHELL} -v -s -r 0 -j j1 -R R1 0 >echo.out 2>echo.err && - grep Hi echo.out -' -test_expect_success 'flux-shell: -v output includes expected task count' ' - grep task_count=1 echo.err -' -test_expect_success 'flux-shell: missing JOBID fails with Usage message' ' - test_must_fail ${FLUX_SHELL} -s -r 0 -j j1 -R R1 2>nojobid.err && - grep Usage nojobid.err -' -test_expect_success 'flux-shell: missing -r fails with standalone message' ' - test_must_fail ${FLUX_SHELL} -s -j j1 -R R1 0 2>no_r.err && - grep standalone no_r.err -' -test_expect_success 'flux-shell: missing -R fails with standalone message' ' - test_must_fail ${FLUX_SHELL} -s -r 0 -j j1 0 2>no_R.err && - grep standalone no_R.err -' -test_expect_success 'flux-shell: missing -j fails with standalone message' ' - test_must_fail ${FLUX_SHELL} -s -r 0 -R R1 0 2>no_j.err && - grep standalone no_j.err -' -test_expect_success 'flux-shell: nonexistent jobspec file fails' ' - ! ${FLUX_SHELL} -v -s -r 0 -j /noexist -R R1 0 \ - >noexist.out 2>noexist.err && - grep "error opening" noexist.err -' -test_expect_success 'flux-shell: malformed jobid fails' ' - ! ${FLUX_SHELL} -v -s -r 0 -j j1 -R R1 BADID \ - >badid.out 2>badid.err && - grep "jobid" badid.err -' -test_expect_success 'flux-shell: out of range jobid fails' ' - ! ${FLUX_SHELL} -v -s -r 0 -j j1 -R R1 18446744073709551616 \ - >badid2.out 2>badid2.err && - grep "jobid" badid2.err -' -test_expect_success 'flux-shell: out of range broker rank fails' ' - test_must_fail ${FLUX_SHELL} -s -r 4294967296 -j j1 -R R1 0 2>er.err && - grep -i option er.err -' -test_expect_success 'flux-shell: wrong range broker rank fails' ' - test_must_fail ${FLUX_SHELL} -s -r 8 -j j1 -R R1 0 2>wr.err && - grep -i fetching wr.err -' -test_expect_success 'flux-shell: unknown argument fails' ' - test_must_fail ${FLUX_SHELL} --FOO -s -r 0 -j j1 -R R1 0 2>alien.err && - grep -i unrecognized alien.err -' -test_expect_success 'flux-shell: generate 2-task jobspec and matching R' ' - flux run -o cpu-affinity=off --dry-run -N1 -n2 printenv >j2 && - cat >R2 <<-EOT - {"version": 1, "execution":{ "R_lite":[ - { "children": { "core": "0-1" }, "rank": "0" } - ]}} - EOT -' -test_expect_success 'flux-shell: run 2-task printenv job' ' - ${FLUX_SHELL} -v -s -r 0 -j j2 -R R2 42 \ - >printenv.out 2>printenv.err -' -test_expect_success 'flux-shell: 0: completed with no error' ' - grep "task 0 complete status=0" printenv.err -' -test_expect_success 'flux-shell: 1: completed with no error' ' - grep "task 1 complete status=0" printenv.err -' -test_expect_success 'flux-shell: 0: FLUX_TASK_LOCAL_ID, TASK_RANK set' ' - grep FLUX_TASK_LOCAL_ID=0 printenv.out && - grep FLUX_TASK_RANK=0 printenv.out -' -test_expect_success 'flux-shell: 1: FLUX_TASK_LOCAL_ID, TASK_RANK set' ' - grep FLUX_TASK_LOCAL_ID=1 printenv.out && - grep FLUX_TASK_RANK=1 printenv.out -' -test_expect_success 'flux-shell: FLUX_JOB_SIZE, JOB_NNODES, JOB_ID set' ' - grep FLUX_JOB_SIZE=2 printenv.out && - grep FLUX_JOB_NNODES=1 printenv.out && - (grep FLUX_JOB_ID=$(flux job id --to=f58 42) printenv.out || - grep FLUX_JOB_ID=42 printenv.out) -' -test_expect_success 'flux-shell: FLUX_URI is not set by shell' ' - test_must_fail grep FLUX_URI printenv.out -' -test_expect_success 'flux-shell: 0: PMI_RANK set' ' - grep PMI_RANK=0 printenv.out -' -test_expect_success 'flux-shell: 1: PMI_RANK set' ' - grep PMI_RANK=1 printenv.out -' -test_expect_success 'flux-shell: PMI_SIZE, PMI_FD set' ' - grep PMI_SIZE=2 printenv.out && - grep PMI_FD= printenv.out -' -test_expect_success 'flux-shell: generate 8-task bash exit rank job' ' - flux run --dry-run -o cpu-affinity=off \ - -N1 -n8 bash -c "exit \$FLUX_TASK_RANK" >j8 && - cat >R8 <<-EOT - {"version": 1, "execution":{ "R_lite":[ - { "children": { "core": "0-7" }, "rank": "0" } - ]}} - EOT -' -test_expect_success 'flux-shell: environ in jobspec is set for task' ' - flux run --dry-run --env=ENVTEST=foo printenv >je && - ${FLUX_SHELL} -v -s -r 0 -j je -R R1 42 \ - >printenv2.out 2>printenv2.err && - grep ENVTEST=foo printenv2.out -' -test_expect_success 'flux-shell: shell PMI works' ' - flux run --dry-run -o cpu-affinity=off \ - -N1 -n8 ${PMI_INFO} >j8pmi && - ${FLUX_SHELL} -v -s -r 0 -j j8pmi -R R8 51 \ - >pmi_info.out 2>pmi_info.err -' -test_expect_success 'flux-shell: shell PMI exports clique info' ' - flux run --dry-run -N1 -n8 \ - ${PMI_INFO} -c >j8pmi_clique && - ${FLUX_SHELL} -v -s -r 0 -j j8pmi_clique -R R8 51 \ - >pmi_clique.out 2>pmi_clique.err && - COUNT=$(grep "clique=0,1,2,3,4,5,6,7" pmi_clique.out | wc -l) && - test ${COUNT} -eq 8 -' -test_expect_success 'flux-shell: shell PMI KVS works' ' - flux run --dry-run -o cpu-affinity=off \ - -N1 -n8 ${KVSTEST} > j8kvs && - ${FLUX_SHELL} -v -s -r 0 -j j8kvs -R R8 52 \ - >kvstest.out 2>kvstest.err -' -test_expect_success NO_ASAN 'flux-shell: shell can launch flux' ' - flux run --dry-run -o cpu-affinity=off \ - -N1 -n8 flux start flux getattr size >j8flux && - ${FLUX_SHELL} -vv -s -r 0 -j j8flux -R R8 39 \ - >flux.out 2>flux.err && - grep -x "0: 8" flux.out -' - -test_expect_success 'flux-shell: shell exits with highest task exit value' ' - test_expect_code 7 ${FLUX_SHELL} -v -s -r 0 -j j8 -R R8 69 \ - >exit.out 2>exit.err -' - -test_expect_success 'flux-shell: shell forwards signals to tasks' ' - flux run --dry-run -n1 bash -c "kill \$PPID; sleep 10" > j9 && - test_expect_code $((128+15)) \ - ${FLUX_SHELL} -v -s -r 0 -j j9 -R R8 69 \ - >sigterm.out 2>sigterm.err && - grep "forwarding signal 15" sigterm.err -' - -test_expect_success 'flux-shell: mustachioed command line args are rendered' ' - flux run --dry-run -n1 -o cpu-affinity=off \ - bash -c "echo test-{{id.dec}}-{{id.dec}} >j10.out" > j10 && - ${FLUX_SHELL} -s -r 0 -j j10 -R R8 42 && - grep test-42-42 j10.out -' - -test_done diff --git a/t/t2602-job-shell.t b/t/t2602-job-shell.t index 51d91b82aa41..ffd4b8dc4a03 100755 --- a/t/t2602-job-shell.t +++ b/t/t2602-job-shell.t @@ -13,6 +13,11 @@ KVSTEST=${FLUX_BUILD_DIR}/src/common/libpmi/test_kvstest LPTEST=${SHARNESS_TEST_DIRECTORY}/shell/lptest waitfile=${SHARNESS_TEST_SRCDIR}/scripts/waitfile.lua +test_expect_success 'job-shell: errors on unknown argument' ' + id=$(flux submit hostname) && + test_expect_code 1 ${FLUX_BUILD_DIR}/src/shell/flux-shell --foo ${id} +' + test_expect_success 'job-shell: reads J not jobspec' ' id=$(flux submit --wait-event=priority \ -n1 --urgency=hold /bin/true) && diff --git a/t/t2605-job-shell-output-redirection-standalone.t b/t/t2605-job-shell-output-redirection-standalone.t deleted file mode 100755 index ad02cbf2a13e..000000000000 --- a/t/t2605-job-shell-output-redirection-standalone.t +++ /dev/null @@ -1,313 +0,0 @@ -#!/bin/sh -# -test_description='Test flux-shell in --standalone mode' - -# Append --logfile option if FLUX_TESTS_LOGFILE is set in environment: -test -n "$FLUX_TESTS_LOGFILE" && set -- "$@" --logfile -. `dirname $0`/sharness.sh - -# Run flux-shell under flux command to get correct paths -FLUX_SHELL="flux ${FLUX_BUILD_DIR}/src/shell/flux-shell" - -unset FLUX_URI - -TEST_SUBPROCESS_DIR=${FLUX_BUILD_DIR}/src/common/libsubprocess - -test_expect_success 'flux-shell: generate 1-task echo jobspecs and matching R' ' - flux run --dry-run -N1 -n1 ${TEST_SUBPROCESS_DIR}/test_echo -P -O foo > j1echostdout && - flux run --dry-run -N1 -n1 ${TEST_SUBPROCESS_DIR}/test_echo -P -E bar > j1echostderr && - flux run --dry-run -N1 -n1 ${TEST_SUBPROCESS_DIR}/test_echo -P -O -E baz > j1echoboth && - cat >R1 <<-EOT - {"version": 1, "execution":{ "R_lite":[ - { "children": { "core": "0" }, "rank": "0" } - ]}} - EOT -' - -test_expect_success 'flux-shell: generate 2-task echo jobspecs and matching R' ' - flux run --dry-run -N1 -n2 ${TEST_SUBPROCESS_DIR}/test_echo -P -O foo > j2echostdout && - flux run --dry-run -N1 -n2 ${TEST_SUBPROCESS_DIR}/test_echo -P -E bar > j2echostderr && - flux run --dry-run -N1 -n2 ${TEST_SUBPROCESS_DIR}/test_echo -P -O -E baz > j2echoboth && - cat >R2 <<-EOT - {"version": 1, "execution":{ "R_lite":[ - { "children": { "core": "0-1" }, "rank": "0" } - ]}} - EOT -' - -# -# 1 task output file tests -# - -test_expect_success 'flux-shell: run 1-task echo job (stdout file)' ' - cat j1echostdout \ - | $jq ".attributes.system.shell.options.output.stdout.type = \"file\"" \ - | $jq ".attributes.system.shell.options.output.stdout.path = \"out0\"" \ - > j1echostdout-0 && - ${FLUX_SHELL} -v -s -r 0 -j j1echostdout-0 -R R1 0 && - grep stdout:foo out0 -' - -test_expect_success 'flux-shell: run 1-task echo job (stderr file)' ' - cat j1echostderr \ - | $jq ".attributes.system.shell.options.output.stderr.type = \"file\"" \ - | $jq ".attributes.system.shell.options.output.stderr.path = \"err1\"" \ - > j1echostderr-1 && - ${FLUX_SHELL} -v -s -r 0 -j j1echostderr-1 -R R1 1 && - grep stderr:bar err1 -' - -test_expect_success 'flux-shell: run 1-task echo job (stderr to stdout file)' ' - cat j1echostderr \ - | $jq ".attributes.system.shell.options.output.stdout.type = \"file\"" \ - | $jq ".attributes.system.shell.options.output.stdout.path = \"out2\"" \ - > j1echostderr-2 && - ${FLUX_SHELL} -v -s -r 0 -j j1echostderr-2 -R R1 2 && - grep stderr:bar out2 -' - -test_expect_success 'flux-shell: run 1-task echo job (stdout file/stderr file)' ' - cat j1echoboth \ - | $jq ".attributes.system.shell.options.output.stdout.type = \"file\"" \ - | $jq ".attributes.system.shell.options.output.stdout.path = \"out3\"" \ - | $jq ".attributes.system.shell.options.output.stderr.type = \"file\"" \ - | $jq ".attributes.system.shell.options.output.stderr.path = \"err3\"" \ - > j1echoboth-3 && - ${FLUX_SHELL} -v -s -r 0 -j j1echoboth-3 -R R1 3 && - grep stdout:baz out3 && - grep stderr:baz err3 -' - -test_expect_success 'flux-shell: run 1-task echo job (stdout & stderr to stdout file)' ' - cat j1echoboth \ - | $jq ".attributes.system.shell.options.output.stdout.type = \"file\"" \ - | $jq ".attributes.system.shell.options.output.stdout.path = \"out4\"" \ - > j1echoboth-4 && - ${FLUX_SHELL} -v -s -r 0 -j j1echoboth-4 -R R1 4 && - grep stdout:baz out4 && - grep stderr:baz out4 -' - -test_expect_success 'flux-shell: run 1-task echo job (stdout file/stderr term)' ' - cat j1echoboth \ - | $jq ".attributes.system.shell.options.output.stdout.type = \"file\"" \ - | $jq ".attributes.system.shell.options.output.stdout.path = \"out5\"" \ - | $jq ".attributes.system.shell.options.output.stderr.type = \"term\"" \ - > j1echoboth-5 && - ${FLUX_SHELL} -v -s -r 0 -j j1echoboth-5 -R R1 2> err5 5 && - grep stdout:baz out5 && - grep stderr:baz err5 -' - -test_expect_success 'flux-shell: run 1-task echo job (stdout term/stderr file)' ' - cat j1echoboth \ - | $jq ".attributes.system.shell.options.output.stderr.type = \"file\"" \ - | $jq ".attributes.system.shell.options.output.stderr.path = \"err6\"" \ - > j1echoboth-6 && - ${FLUX_SHELL} -v -s -r 0 -j j1echoboth-6 -R R1 > out6 6 && - grep stdout:baz out6 && - grep stderr:baz err6 -' - -# -# 2 task output file tests -# - -test_expect_success 'flux-shell: run 2-task echo job (stdout file)' ' - cat j2echostdout \ - | $jq ".attributes.system.shell.options.output.stdout.type = \"file\"" \ - | $jq ".attributes.system.shell.options.output.stdout.path = \"out7\"" \ - | $jq ".attributes.system.shell.options.output.stdout.label = true" \ - > j2echostdout-7 && - ${FLUX_SHELL} -v -s -r 0 -j j2echostdout-7 -R R2 7 && - grep "0: stdout:foo" out7 && - grep "1: stdout:foo" out7 -' - -test_expect_success 'flux-shell: run 2-task echo job (stderr file)' ' - cat j2echostderr \ - | $jq ".attributes.system.shell.options.output.stderr.type = \"file\"" \ - | $jq ".attributes.system.shell.options.output.stderr.path = \"err8\"" \ - | $jq ".attributes.system.shell.options.output.stderr.label = true" \ - > j2echostderr-8 && - ${FLUX_SHELL} -v -s -r 0 -j j2echostderr-8 -R R2 8 && - grep "0: stderr:bar" err8 && - grep "1: stderr:bar" err8 -' - -test_expect_success 'flux-shell: run 2-task echo job (stderr to stdout file)' ' - cat j2echostderr \ - | $jq ".attributes.system.shell.options.output.stdout.type = \"file\"" \ - | $jq ".attributes.system.shell.options.output.stdout.path = \"out9\"" \ - | $jq ".attributes.system.shell.options.output.stdout.label = true" \ - > j2echostderr-9 && - ${FLUX_SHELL} -v -s -r 0 -j j2echostderr-9 -R R2 9 && - grep "0: stderr:bar" out9 && - grep "1: stderr:bar" out9 -' - -test_expect_success 'flux-shell: run 2-task echo job (stdout file/stderr file)' ' - cat j2echoboth \ - | $jq ".attributes.system.shell.options.output.stdout.type = \"file\"" \ - | $jq ".attributes.system.shell.options.output.stdout.path = \"out10\"" \ - | $jq ".attributes.system.shell.options.output.stdout.label = true" \ - | $jq ".attributes.system.shell.options.output.stderr.type = \"file\"" \ - | $jq ".attributes.system.shell.options.output.stderr.path = \"err10\"" \ - | $jq ".attributes.system.shell.options.output.stderr.label = true" \ - > j2echoboth-10 && - ${FLUX_SHELL} -v -s -r 0 -j j2echoboth-10 -R R2 10 && - grep "0: stdout:baz" out10 && - grep "1: stdout:baz" out10 && - grep "0: stderr:baz" err10 && - grep "1: stderr:baz" err10 -' - -test_expect_success 'flux-shell: run 2-task echo job (stdout & stderr to stdout file)' ' - cat j2echoboth \ - | $jq ".attributes.system.shell.options.output.stdout.type = \"file\"" \ - | $jq ".attributes.system.shell.options.output.stdout.path = \"out11\"" \ - | $jq ".attributes.system.shell.options.output.stdout.label = true" \ - > j2echoboth-11 && - ${FLUX_SHELL} -v -s -r 0 -j j2echoboth-11 -R R2 11 && - grep "0: stdout:baz" out11 && - grep "1: stdout:baz" out11 && - grep "0: stderr:baz" out11 && - grep "1: stderr:baz" out11 -' - -test_expect_success 'flux-shell: run 2-task echo job (stdout file/stderr term)' ' - cat j2echoboth \ - | $jq ".attributes.system.shell.options.output.stdout.type = \"file\"" \ - | $jq ".attributes.system.shell.options.output.stdout.path = \"out12\"" \ - | $jq ".attributes.system.shell.options.output.stdout.label = true" \ - | $jq ".attributes.system.shell.options.output.stderr.type = \"term\"" \ - > j2echoboth-12 && - ${FLUX_SHELL} -v -s -r 0 -j j2echoboth-12 -R R2 2> err12 12 && - grep "0: stdout:baz" out12 && - grep "1: stdout:baz" out12 && - grep "0: stderr:baz" err12 && - grep "1: stderr:baz" err12 -' - -test_expect_success 'flux-shell: run 2-task echo job (stdout term/stderr file)' ' - cat j2echoboth \ - | $jq ".attributes.system.shell.options.output.stderr.type = \"file\"" \ - | $jq ".attributes.system.shell.options.output.stderr.path = \"err13\"" \ - | $jq ".attributes.system.shell.options.output.stderr.label = true" \ - > j2echoboth-13 && - ${FLUX_SHELL} -v -s -r 0 -j j2echoboth-13 -R R2 > out13 13 && - grep "0: stdout:baz" out13 && - grep "1: stdout:baz" out13 && - grep "0: stderr:baz" err13 && - grep "1: stderr:baz" err13 -' - -# -# output file mustache tests -# - -test_expect_success 'flux-shell: run 1-task echo job (mustache id stdout file/stderr file)' ' - id=$(flux job id --to=f58 14) && - cat j1echoboth \ - | $jq ".attributes.system.shell.options.output.stdout.type = \"file\"" \ - | $jq ".attributes.system.shell.options.output.stdout.path = \"out{{jobid}}\"" \ - | $jq ".attributes.system.shell.options.output.stderr.type = \"file\"" \ - | $jq ".attributes.system.shell.options.output.stderr.path = \"err{{jobid}}\"" \ - > j1echoboth-14 && - ${FLUX_SHELL} -v -s -r 0 -j j1echoboth-14 -R R1 14 && - grep stdout:baz out${id} && - grep stderr:baz err${id} -' - -test_expect_success 'flux-shell: run 1-task echo job (mustache id stdout & stderr to stdout file)' ' - id=$(flux job id --to=f58 15) && - cat j1echoboth \ - | $jq ".attributes.system.shell.options.output.stdout.type = \"file\"" \ - | $jq ".attributes.system.shell.options.output.stdout.path = \"out{{id}}\"" \ - > j1echoboth-15 && - ${FLUX_SHELL} -v -s -r 0 -j j1echoboth-15 -R R1 15 && - grep stdout:baz out${id} && - grep stderr:baz out${id} -' - -for type in f58 dec hex dothex words; do - test_expect_success "flux-shell: output template {{id.$type}}" ' - jobid=123456789 && - id=$(flux job id --to=${type} ${jobid}) && - cat j1echoboth \ - | $jq ".attributes.system.shell.options.output.stdout.type = \"file\"" \ - | $jq ".attributes.system.shell.options.output.stdout.path = \"out{{id.${type}}}\"" \ - > j1-mustache-${type} && - ${FLUX_SHELL} -v -s -r 0 -j j1-mustache-${type} -R R1 ${jobid} && - grep stdout:baz out${id} && - grep stderr:baz out${id} - ' -done - -test_expect_success "flux-shell: bad output mustache template is not rendered" ' - cat j1echoboth \ - | $jq ".attributes.system.shell.options.output.stdout.type = \"file\"" \ - | $jq ".attributes.system.shell.options.output.stdout.path = \"{{idx}}.out\"" \ - > j1-mustache-error1 && - ${FLUX_SHELL} -v -s -r 0 -j j1-mustache-error1 -R R1 1234 && - grep stdout:baz {{idx}}.out && - grep stderr:baz {{idx}}.out -' -test_expect_success "flux-shell: bad output mustache template is not rendered" ' - cat j1echoboth \ - | $jq ".attributes.system.shell.options.output.stdout.type = \"file\"" \ - | $jq ".attributes.system.shell.options.output.stdout.path = \"{{id.x}}.out\"" \ - > j1-mustache-error2 && - ${FLUX_SHELL} -v -s -r 0 -j j1-mustache-error2 -R R1 1234 && - grep stdout:baz {{id.x}}.out && - grep stderr:baz {{id.x}}.out -' - -test_expect_success "flux-shell: unknown mustache template is not rendered" ' - cat j1echoboth \ - | $jq ".attributes.system.shell.options.output.stdout.type = \"file\"" \ - | $jq ".attributes.system.shell.options.output.stdout.path = \"{{foo}}.out\"" \ - > j1-mustache-error3 && - ${FLUX_SHELL} -v -s -r 0 -j j1-mustache-error3 -R R1 1234 && - grep stdout:baz {{foo}}.out && - grep stderr:baz {{foo}}.out -' - -test_expect_success "flux-shell: too large mustache template is not rendered" ' - tmpl=$(printf "%0.sf" $(seq 0 120)) && - cat j1echoboth \ - | $jq ".attributes.system.shell.options.output.stdout.type = \"file\"" \ - | $jq ".attributes.system.shell.options.output.stdout.path = \"{{$tmpl}}.out\"" \ - > j1-mustache-error4 && - ${FLUX_SHELL} -v -s -r 0 -j j1-mustache-error4 -R R1 1234 && - grep stdout:baz {{$tmpl}}.out && - grep stderr:baz {{$tmpl}}.out -' - -# -# output corner case tests -# - -test_expect_success 'flux-shell: error on bad output type' ' - cat j1echostdout \ - | $jq ".attributes.system.shell.options.output.stdout.type = \"foobar\"" \ - > j1echostdout-16 && - ! ${FLUX_SHELL} -v -s -r 0 -j j1echostdout-16 -R R1 16 -' - -test_expect_success 'flux-shell: error on no path with file output' ' - cat j1echostdout \ - | $jq ".attributes.system.shell.options.output.stdout.type = \"file\"" \ - > j1echostdout-17 && - ! ${FLUX_SHELL} -v -s -r 0 -j j1echostdout-17 -R R1 17 -' - -test_expect_success 'flux-shell: error invalid path to file output' ' - cat j1echostdout \ - | $jq ".attributes.system.shell.options.output.stdout.type = \"file\"" \ - | $jq ".attributes.system.shell.options.output.stdout.path = \"/foo/bar/baz\"" \ - > j1echostdout-18 && - ! ${FLUX_SHELL} -v -s -r 0 -j j1echostdout-18 -R R1 18 -' - -test_done From 1762b23d09d4814b7f8556a889a580aab1136aa3 Mon Sep 17 00:00:00 2001 From: "Mark A. Grondona" Date: Thu, 19 Oct 2023 06:56:20 -0700 Subject: [PATCH 2/6] testsuite: avoid shell standalone mode in initrc tests Problem: The tests in t2603-job-shell-initrc.t use the job shell --standalone option, but that option is going away. Convert tests to use `flux run` to launch the job shell. Remove the `setopt` test which ensured that flux_shell_setopt(3) works when the jobspec options object is not set. It is not possible to submit a jobspec and load an alternate initrc without using the shell options object, so this test can no longer be maintained (and it is unlikely that the condition will come up in the real world, so the test was of limited value). --- t/Makefile.am | 9 --- t/shell/plugins/setopt.c | 74 ------------------ t/t2603-job-shell-initrc.t | 154 +++++++++++++------------------------ 3 files changed, 55 insertions(+), 182 deletions(-) delete mode 100644 t/shell/plugins/setopt.c diff --git a/t/Makefile.am b/t/Makefile.am index b7016eea90d6..7d606d9c18f9 100644 --- a/t/Makefile.am +++ b/t/Makefile.am @@ -458,7 +458,6 @@ check_LTLIBRARIES = \ shell/plugins/conftest.la \ shell/plugins/invalid-args.la \ shell/plugins/getopt.la \ - shell/plugins/setopt.la \ shell/plugins/log.la \ shell/plugins/test-event.la \ shell/plugins/jobspec-info.la \ @@ -804,14 +803,6 @@ shell_plugins_getopt_la_LIBADD = \ $(top_builddir)/src/common/libtap/libtap.la \ $(top_builddir)/src/common/libflux-core.la -shell_plugins_setopt_la_SOURCES = shell/plugins/setopt.c -shell_plugins_setopt_la_CPPFLAGS = $(test_cppflags) -shell_plugins_setopt_la_LDFLAGS = \ - $(fluxplugin_ldflags) -module -rpath /nowhere -shell_plugins_setopt_la_LIBADD = \ - $(top_builddir)/src/common/libtap/libtap.la \ - $(top_builddir)/src/common/libflux-core.la - shell_plugins_log_la_SOURCES = shell/plugins/log.c shell_plugins_log_la_CPPFLAGS = $(test_cppflags) shell_plugins_log_la_LDFLAGS = \ diff --git a/t/shell/plugins/setopt.c b/t/shell/plugins/setopt.c deleted file mode 100644 index 8b110fcadcd6..000000000000 --- a/t/shell/plugins/setopt.c +++ /dev/null @@ -1,74 +0,0 @@ -/************************************************************\ - * Copyright 2020 Lawrence Livermore National Security, LLC - * (c.f. AUTHORS, NOTICE.LLNS, COPYING) - * - * This file is part of the Flux resource manager framework. - * For details, see https://github.com/flux-framework. - * - * SPDX-License-Identifier: LGPL-3.0 -\************************************************************/ -#define FLUX_SHELL_PLUGIN_NAME "setopt" - -#if HAVE_CONFIG_H -#include "config.h" -#endif -#include -#include -#include -#include - -#include -#include -#include - -#include "src/common/libtap/tap.h" - -static int die (const char *fmt, ...) -{ - va_list ap; - va_start (ap, fmt); - vfprintf (stderr, fmt, ap); - va_end (ap); - return -1; -} - -static int check_setopt (flux_plugin_t *p, - const char *topic, - flux_plugin_arg_t *args, - void *data) -{ - json_t *options = NULL; - - flux_shell_t *shell = flux_plugin_get_shell (p); - if (!p) - return die ("flux_plugin_get_shell\n"); - - ok (flux_shell_info_unpack (shell, - "{s:{s:{s:{s:{s:o}}}}}", - "jobspec", - "attributes", - "system", - "shell", - "options", &options) < 0, - "flux_shell_info_unpack shell options fails"); - - /* A shell plugin should be able to call setopt even though - * no shell options were currently set in jobspec. - */ - ok (flux_shell_setopt (shell, "new", "42") == 0, - "flux_shell_setopt of new option works"); - - return exit_status () == 0 ? 0 : -1; -} - -int flux_plugin_init (flux_plugin_t *p) -{ - plan (NO_PLAN); - ok (flux_plugin_add_handler (p, "shell.init", check_setopt, NULL) == 0, - "flux_plugin_add_handler works"); - return 0; -} - -/* - * vi: ts=4 sw=4 expandtab - */ diff --git a/t/t2603-job-shell-initrc.t b/t/t2603-job-shell-initrc.t index 44f742a1b922..59ed3ed8a91c 100755 --- a/t/t2603-job-shell-initrc.t +++ b/t/t2603-job-shell-initrc.t @@ -51,40 +51,21 @@ test_expect_success 'flux-shell: default initrc obeys FLUX_SHELL_RC_PATH' ' flux run hostname >rcpath.log 2>&1 && grep "plugin loaded from test-dir.d" rcpath.log ' -test_expect_success 'flux-shell: initrc: generate 1-task jobspec and matching R' ' - flux run --dry-run -N1 -n1 echo Hi >j1 && - cat >R1 <<-EOT - {"version": 1, "execution":{ "R_lite":[ - { "children": { "core": "0,1" }, "rank": "0" } - ]}} - EOT -' - -test_expect_success 'flux-shell: initrc: loading missing initrc fails' ' - test_expect_code 1 ${FLUX_SHELL} -v -s -r 0 -j j1 -R R1 \ - --initrc=nosuchfile 0 -' test_expect_success 'flux-shell: initrc: specifying initrc of /dev/null works' ' - ${FLUX_SHELL} -v -s -r 0 -j j1 -R R1 \ - --initrc=/dev/null 0 > devnull.log 2>&1 && + flux run -o verbose -o initrc=/dev/null true > devnull.log 2>&1 && test_debug "cat devnull.log" && grep "Loading /dev/null" devnull.log ' test_expect_success 'flux-shell: initrc: bad initrc in jobspec fails' ' - flux run --dry-run -N1 -n1 echo Hi \ - | jq ".attributes.system.shell.options.initrc = \"nosuchfile\"" \ - > j2 && - test_expect_code 1 ${FLUX_SHELL} -v -s -r 0 -j j2 -R R1 0 + test_must_fail_or_be_terminated \ + flux run -o verbose -o initrc=nosuchfile true ' test_expect_success 'flux-shell: initrc: in jobspec works' ' name=ok && cat >${name}.lua <<-EOT && - print ("jobspec initrc OK") + io.stderr:write ("jobspec initrc OK\n") EOT - flux run --dry-run -N1 -n1 echo Hi \ - | jq ".attributes.system.shell.options.initrc = \"${name}.lua\"" \ - > j3 && - ${FLUX_SHELL} -v -s -r 0 -j j3 -R R1 0 > ${name}.log 2>&1 && + flux run -o initrc=${name}.lua true > ${name}.log 2>&1 && test_debug "cat ${name}.log" && grep "jobspec initrc OK" ${name}.log ' @@ -93,18 +74,18 @@ test_expect_success 'flux-shell: initrc: failed initrc causes termination' ' cat >${name}.lua <<-EOT && = EOT - test_expect_code 1 ${FLUX_SHELL} -v -s -r 0 -j j1 -R R1 \ - --initrc=${name}.lua 0 > ${name}.log 2>&1 && + test_must_fail_or_be_terminated \ + flux run -o verbose -o initrc=${name}.lua true > ${name}.log 2>&1 && test_debug "cat ${name}.log" && grep "unexpected symbol" ${name}.log ' test_expect_success 'flux-shell: initrc: access task in non-task context fails' ' name=invalid-access && - cat >${name}.lua <<-EOT && - print (task.info) + cat >${name}.lua <<-"EOT" && + io.stderr:write (task.info .. "\n") EOT - test_expect_code 1 ${FLUX_SHELL} -v -s -r 0 -j j1 -R R1 \ - --initrc=${name}.lua 0 > ${name}.log 2>&1 && + test_must_fail_or_be_terminated \ + flux run -o verbose -o initrc=${name}.lua true > ${name}.log 2>&1 && test_debug "cat ${name}.log" && grep "attempt to access task outside of task context" ${name}.log ' @@ -113,14 +94,14 @@ test_expect_success 'flux-shell: initrc: bad plugin.register usage fails' ' cat >${name}.lua <<-EOT && plugin.register {} EOT - test_expect_code 1 ${FLUX_SHELL} -v -s -r 0 -j j1 -R R1 \ - --initrc=${name}.lua 0 > ${name}.log 2>&1 && + test_must_fail_or_be_terminated \ + flux run -o verbose -o initrc=${name}.lua true > ${name}.log 2>&1 && test_debug "cat ${name}.log" && grep "required handlers table missing" ${name}.log ' test_expect_success 'flux-shell: initrc: bad plugin.register usage fails' ' name=handlers-not-array && - cat >${name}.lua <<-EOT && + cat >${name}.lua <<-"EOT" && plugin.register { handlers = { topic = "*", @@ -128,8 +109,8 @@ test_expect_success 'flux-shell: initrc: bad plugin.register usage fails' ' } } EOT - test_expect_code 1 ${FLUX_SHELL} -v -s -r 0 -j j1 -R R1 \ - --initrc=${name}.lua 0 > ${name}.log 2>&1 && + test_must_fail_or_be_terminated \ + flux run -o verbose -o initrc=${name}.lua true > ${name}.log 2>&1 && test_debug "cat ${name}.log" && grep "no entries" ${name}.log ' @@ -138,12 +119,11 @@ test_expect_success 'flux-shell: initrc: assignment to shell method fails' ' cat >${name}.lua <<-EOT && shell.getenv = "my data" EOT - test_expect_code 1 ${FLUX_SHELL} -v -s -r 0 -j j1 -R R1 \ - --initrc=${name}.lua 0 > ${name}.log 2>&1 && + test_must_fail_or_be_terminated \ + flux run -o verbose -o initrc=${name}.lua true > ${name}.log 2>&1 && test_debug "cat ${name}.log" && grep " attempt to set read-only field" ${name}.log ' - test_expect_success 'flux-shell: initrc: return false from plugin aborts shell' ' name=failed-return && cat >${name}.lua <<-EOT && @@ -154,30 +134,23 @@ test_expect_success 'flux-shell: initrc: return false from plugin aborts shell' } } EOT - test_expect_code 1 ${FLUX_SHELL} -v -s -r 0 -j j1 -R R1 \ - --initrc=${name}.lua 0 > ${name}.log 2>&1 && + test_must_fail_or_be_terminated \ + flux run -o verbose -o initrc=${name}.lua true > ${name}.log 2>&1 && test_debug "cat ${name}.log" && grep "plugin.*: shell.init failed" ${name}.log ' -test_expect_success 'flux-shell: initrc: add test options to jobspec' " - cat j1 | jq '.attributes.system.shell.options.test = \"test\"' \ - > j.initrc -" - -for initrc in ${INITRC_TESTDIR}/tests/*.lua; do - test_expect_success "flux-shell: initrc: runtest $(basename $initrc)" ' - ${FLUX_SHELL} -v -s -r 0 -j j.initrc -R R1 --initrc=${initrc} 0 - ' -done - +# Submit all test initrcs to instance: +test_expect_success 'flux-shell: initrc: run tests in shell/initrc/tests' ' + flux bulksubmit --quiet --watch -n1 -o initc={} echo run test {./} \ + ::: ${INITRC_TESTDIR}/tests/*.lua >&2 +' test_expect_success 'flux-shell: initrc: loads single .so successfully' ' name=conftest-success && cat >${name}.lua <<-EOT && plugin.searchpath = "${INITRC_PLUGINPATH}" plugin.load { file = "dummy.so", conf = { result = 0 } } EOT - test_expect_code 0 ${FLUX_SHELL} -v -s -r 0 -j j1 -R R1 \ - --initrc=${name}.lua 0 > ${name}.log 2>&1 && + flux run -o verbose -o initrc=${name}.lua true > ${name}.log 2>&1 && test_debug "cat ${name}.log" && grep "dummy: OK result=0" ${name}.log ' @@ -188,8 +161,8 @@ test_expect_success 'flux-shell: initrc: script fails on plugin.load failure' ' plugin.searchpath = "${INITRC_PLUGINPATH}" plugin.load { file = "dummy.so", conf = { result = -1 } } EOT - test_expect_code 1 ${FLUX_SHELL} -v -s -r 0 -j j1 -R R1 \ - --initrc=${name}.lua 0 > ${name}.log 2>&1 && + test_must_fail_or_be_terminated \ + flux run -o verbose -o initrc=${name}.lua true > ${name}.log 2>&1 && test_debug "cat ${name}.log" && grep "dummy: OK result=-1" ${name}.log ' @@ -198,8 +171,8 @@ test_expect_success 'flux-shell: initrc: plugin pattern nomatch not fatal' ' cat >${name}.lua <<-EOT && plugin.load { file = "nofile*.so" } EOT - test_expect_code 0 ${FLUX_SHELL} -v -s -r 0 -j j1 -R R1 \ - --initrc=${name}.lua 0 > ${name}.log 2>&1 && + flux run --label-io -o verbose -o initrc=${name}.lua \ + echo Hi > ${name}.log 2>&1 && test_debug "cat ${name}.log" && grep "0: Hi" ${name}.log ' @@ -208,8 +181,8 @@ test_expect_success 'flux-shell: initrc: plugin nonpattern nomatch fatal' ' cat >${name}.lua <<-EOT && plugin.load { file = "nofile.so" } EOT - test_expect_code 1 ${FLUX_SHELL} -v -s -r 0 -j j1 -R R1 \ - --initrc=${name}.lua 0 > ${name}.log 2>&1 && + test_must_fail_or_be_terminated \ + flux run -o verbose -o initrc=${name}.lua true > ${name}.log 2>&1 && test_debug "cat ${name}.log" && grep "nofile.so: File not found" ${name}.log ' @@ -218,8 +191,8 @@ test_expect_success 'flux-shell: initrc: plugin.load accepts string arg' ' cat >${name}.lua <<-EOT && plugin.load "nomatch-again.so" EOT - test_expect_code 1 ${FLUX_SHELL} -v -s -r 0 -j j1 -R R1 \ - --initrc=${name}.lua 0 > ${name}.log 2>&1 && + test_must_fail_or_be_terminated \ + flux run -o verbose -o initrc=${name}.lua true > ${name}.log 2>&1 && test_debug "cat ${name}.log" && grep "nomatch-again.so: File not found" ${name}.log ' @@ -228,12 +201,11 @@ test_expect_success 'flux-shell: initrc: plugin.load bad argument fatal' ' cat >${name}.lua <<-EOT && plugin.load (true) EOT - test_expect_code 1 ${FLUX_SHELL} -v -s -r 0 -j j1 -R R1 \ - --initrc=${name}.lua 0 > ${name}.log 2>&1 && + test_must_fail_or_be_terminated \ + flux run -o verbose -o initrc=${name}.lua true > ${name}.log 2>&1 && test_debug "cat ${name}.log" && grep "plugin.load: invalid argument" ${name}.log ' - test_expect_success 'flux-shell: initrc: plugin.load passes conf to plugin' ' name=conftest && cat >${name}.lua <<-EOT && @@ -245,8 +217,7 @@ test_expect_success 'flux-shell: initrc: plugin.load passes conf to plugin' ' three = "bar" } } EOT - ${FLUX_SHELL} -v -s -r 0 -j j1 -R R1 \ - --initrc=${name}.lua 0 > ${name}.log 2>&1 && + flux run -o verbose -o initrc=${name}.lua true > ${name}.log 2>&1 && test_debug "cat ${name}.log" && grep "conftest: one=foo" ${name}.log && grep "conftest: two=two" ${name}.log && @@ -258,8 +229,7 @@ test_expect_success 'flux-shell: initrc: load invalid args plugins' ' plugin.searchpath = "${INITRC_PLUGINPATH}" plugin.load { file = "invalid-args.so" } EOT - ${FLUX_SHELL} -v -s -r 0 -j j1 -R R1 \ - --initrc=${name}.lua 0 + flux run -o verbose -o initrc=${name}.lua true ' test_expect_success 'flux-shell: initrc: load getopt plugin' ' name=getopt && @@ -267,36 +237,23 @@ test_expect_success 'flux-shell: initrc: load getopt plugin' ' plugin.searchpath = "${INITRC_PLUGINPATH}" plugin.load { file = "getopt.so" } EOF - cat j1 | jq ".attributes.system.shell.options.test = 1" >j.${name} && - ${FLUX_SHELL} -v -s -r 0 -j j.${name} -R R1 --initrc=${name}.lua 0 \ - > ${name}.log 2>&1 && - test_debug "cat ${name}.log" -' -test_expect_success 'flux-shell: plugins can use setopt with empty options' ' - name=setopt && - cat >${name}.lua <<-EOF && - plugin.searchpath = "${INITRC_PLUGINPATH}" - plugin.load { file = "${name}.so" } - EOF - cat j1 | jq "del(.attributes.system.shell.options)" >j.${name} && - ${FLUX_SHELL} -v -s -r 0 -j j.${name} -R R1 --initrc=${name}.lua 0 \ - > ${name}.log 2>&1 && - test_debug "cat ${name}.log" + flux run -o verbose -o initrc=${name}.lua -o test=1 true ' - test_expect_success 'flux-shell: initrc: jobspec-info plugin works' ' name=jobspec-info && cat >${name}.lua <<-EOF && plugin.searchpath = "${INITRC_PLUGINPATH}" plugin.load { file = "jobspec-info.so" } EOF - cat j1 | \ - jq ".attributes.system.shell.options.jobspec_info = \ - { ntasks: 1, nnodes: 1, nslots: 1, \ - cores_per_slot: 1, \ - slots_per_node: 1 }" \ - >j.${name} && - ${FLUX_SHELL} -v -s -r 0 -j j.${name} -R R1 --initrc=${name}.lua 0 + cat >${name}.json <<-"EOF" && + { "ntasks":1, "nnodes":1, "nslots":1, + "cores_per_slot":1, + "slots_per_node":1 + } + EOF + flux run -N1 -n1 -c1 -o verbose=2 \ + -o initrc=${name}.lua \ + -o ^jobspec_info=${name}.json true ' test_expect_success 'flux-shell: initrc: shell log functions available' ' name=shell.log && @@ -306,11 +263,11 @@ test_expect_success 'flux-shell: initrc: shell log functions available' ' shell.log_error ("test: error") EOF - ${FLUX_SHELL} -v -s -r 0 -j j1 -R R1 --initrc=${name}.lua 0 \ + flux run -o verbose -o initrc=${name}.lua true \ > ${name}.log 2>&1 && - grep "INFO: ${name}.lua:1: test: shell.log" ${name}.log && - grep "DEBUG: ${name}.lua:2: test: debug" ${name}.log && - grep "ERROR: ${name}.lua:4: test: error" ${name}.log + grep "test: shell.log" ${name}.log && + grep "DEBUG: test: debug" ${name}.log && + grep "ERROR: test: error" ${name}.log ' test_expect_success 'flux-shell: initrc: shell.die function works' ' name=shell.die && @@ -318,10 +275,9 @@ test_expect_success 'flux-shell: initrc: shell.die function works' ' -- shell.die test shell.die ("test: shell.die") EOF - test_expect_code 1 \ - ${FLUX_SHELL} -v -s -r 0 -j j1 -R R1 --initrc=${name}.lua 0 \ + test_must_fail_or_be_terminated \ + flux run -o verbose -o initrc=${name}.lua true \ > ${name}.log 2>&1 && - grep "FATAL: ${name}.lua:2: test: shell.die" ${name}.log + grep "FATAL: test: shell.die" ${name}.log ' - test_done From be6b02b64e65f2bffb4354d25f0d38897dda4c6e Mon Sep 17 00:00:00 2001 From: "Mark A. Grondona" Date: Thu, 19 Oct 2023 07:20:19 -0700 Subject: [PATCH 3/6] testsuite: avoid standalone mode in shell log tests Problem: The first set of shell log tests use the job shell standalone mode for testing logging, but the --standalone option is being removed. Remove the tests that use the --standalone option. The testing is duplicated using flux-run later in the test anyway. --- t/t2608-job-shell-log.t | 43 ++--------------------------------------- 1 file changed, 2 insertions(+), 41 deletions(-) diff --git a/t/t2608-job-shell-log.t b/t/t2608-job-shell-log.t index d7419bb6c358..6d6af05ba2e2 100755 --- a/t/t2608-job-shell-log.t +++ b/t/t2608-job-shell-log.t @@ -14,52 +14,13 @@ INITRC_PLUGINPATH="${SHARNESS_TEST_DIRECTORY}/shell/plugins/.libs" # test initrc files need to be able to find fluxometer.lua: export LUA_PATH="$LUA_PATH;${SHARNESS_TEST_DIRECTORY}/?.lua" -test_expect_success 'flux-shell: log: generate 1-task jobspec and matching R' ' - flux run --dry-run -N1 -n1 echo Hi >j1 && - cat >R1 <<-EOT - {"version": 1, "execution":{ "R_lite":[ - { "children": { "core": "0,1" }, "rank": "0" } - ]}} - EOT -' -test_expect_success 'flux-shell: run log testing plugin' ' +test_expect_success 'flux-shell: create log testing initrc' ' name=log && - cat >${name}.lua <<-EOF && + cat >${name}.lua <<-EOF plugin.searchpath = "${INITRC_PLUGINPATH}" plugin.load { file = "log.so" } EOF - ${FLUX_SHELL} -v -v -s -r 0 -j j1 -R R1 --initrc=${name}.lua 0 \ - > ${name}.log 2>&1 && - test_debug "cat ${name}.log" ' -for topic in "shell.init" "shell.exit" \ - "task.init" "task.exit" \ - "task.fork" "task.fork"; do - test_expect_success "$topic: got TRACE level message" " - grep \"TRACE: log: .*: $topic: trace message\" log.log - " - test_expect_success "$topic: got truncated long TRACE level message" " - grep -q \"TRACE: log: .*: $topic: long message.*0000+$\" log.log - " - test_expect_success "$topic: got DEBUG level message" " - grep \"DEBUG: log: .*: $topic: debug message\" log.log - " - test_expect_success "$topic: got INFO level message" " - grep \" INFO: log: .*: $topic: log message\" log.log - " - test_expect_success "$topic: got WARN level message" " - grep \" WARN: log: .*: $topic: warn message\" log.log - " - test_expect_success "$topic: got ERROR level message" " - grep \"ERROR: log: .*: $topic: error message\" log.log - " - test_expect_success "$topic: got log_errn message" " - grep \"ERROR:.*: $topic: log_errn message: Operation not permitted\" log.log - " - test_expect_success "$topic: got log_errno message" " - grep \"ERROR: log: .*: $topic: log_errno message: Invalid argument\" log.log - " -done test_expect_success 'flux-shell: run job with verbose logging to output' ' flux run -o verbose=2 -o initrc=log.lua -n2 -N2 hostname \ From b5e5144425c7c71fcbadff33767a6e024e7be3ac Mon Sep 17 00:00:00 2001 From: "Mark A. Grondona" Date: Thu, 19 Oct 2023 08:10:27 -0700 Subject: [PATCH 4/6] testsuite: avoid standalone shell option in affinity tests Problem: The job shell gpu affinity tests use the shell --standolone option which is going away. Use the alloc-bypass plugin and flux-run(1) to test GPU affinity instead of --standalone. --- t/t2604-job-shell-affinity.t | 75 +++++++++++++++++++++--------------- 1 file changed, 45 insertions(+), 30 deletions(-) diff --git a/t/t2604-job-shell-affinity.t b/t/t2604-job-shell-affinity.t index a9c6fccab34c..5b9c643ca8d8 100755 --- a/t/t2604-job-shell-affinity.t +++ b/t/t2604-job-shell-affinity.t @@ -109,9 +109,12 @@ test_expect_success 'flux-shell: CUDA_VISIBLE_DEVICES=-1 works with existing val test_debug "cat override-gpubind.out" && grep "^-1" override-gpubind.out ' -# GPU affinity tests use standalone shell since simple-sched doesnt +# GPU affinity tests use alloc-bypass shell since simple-sched doesnt # schedule GPUs. # +test_expect_success 'flux-shell: load alloc-bypass jobtap plugin' ' + flux jobtap load alloc-bypass.so +' test_expect_success 'flux-shell: create multi-gpu R' ' cat >R.gpu <<-EOF {"version": 1, "execution":{ "R_lite":[ @@ -121,73 +124,85 @@ test_expect_success 'flux-shell: create multi-gpu R' ' ' test_expect_success 'flux-shell: gpu-affinity works by default' ' name=gpu-basic && - flux run -N1 -n2 --dry-run \ - printenv CUDA_VISIBLE_DEVICES > j.${name} && + flux run -N1 -n2 \ + --label-io \ + --setattr=alloc-bypass.R="$(cat R.gpu)" \ + printenv CUDA_VISIBLE_DEVICES >${name}.output 2>${name}.err && cat >${name}.expected <<-EOF && 0: 0,1,2,3 1: 0,1,2,3 EOF - ${FLUX_SHELL} -s -v -r 0 -j j.${name} -R R.gpu 0 && - ${FLUX_SHELL} -s -v -r 0 -j j.${name} -R R.gpu 0 | sort -k1,1n \ - > ${name}.out 2>${name}.err && + test_debug "cat ${name}.output ${name}.err" && + sort -k1,1n ${name}.output > ${name}.out && test_cmp ${name}.expected ${name}.out ' test_expect_success 'flux-shell: gpu-affinity=on' ' name=gpu-on && - flux run -N1 -n2 --dry-run -o gpu-affinity=on \ - printenv CUDA_VISIBLE_DEVICES > j.${name} && + flux run -N1 -n2 \ + --label-io \ + --setattr=alloc-bypass.R="$(cat R.gpu)" \ + -o gpu-affinity=on \ + printenv CUDA_VISIBLE_DEVICES >${name}.output 2>${name}.err && cat >${name}.expected <<-EOF && 0: 0,1,2,3 1: 0,1,2,3 EOF - ${FLUX_SHELL} -s -v -r 0 -j j.${name} -R R.gpu 0 | sort -k1,1n \ - > ${name}.out 2>${name}.err && + test_debug "cat ${name}.output ${name}.err" && + sort -k1,1n ${name}.output > ${name}.out && test_cmp ${name}.expected ${name}.out ' test_expect_success 'flux-shell: gpu-affinity=per-task' ' name=gpu-per-task && - flux run -N1 -n2 --dry-run -o gpu-affinity=per-task \ - printenv CUDA_VISIBLE_DEVICES > j.${name} && + flux run -N1 -n2 \ + --label-io \ + --setattr=alloc-bypass.R="$(cat R.gpu)" \ + -o gpu-affinity=per-task \ + printenv CUDA_VISIBLE_DEVICES >${name}.output 2>${name}.err && cat >${name}.expected <<-EOF && 0: 0,1 1: 2,3 EOF - ${FLUX_SHELL} -s -v -r 0 -j j.${name} -R R.gpu 0 | sort -k1,1n \ - > ${name}.out 2>${name}.err && + test_debug "cat ${name}.output ${name}.err" && + sort -k1,1n ${name}.output > ${name}.out && test_cmp ${name}.expected ${name}.out ' test_expect_success 'flux-shell: gpu-affinity=map: works' ' name=gpu-map && - flux run -N1 -n2 --dry-run -o gpu-affinity="map:7;4-6" \ - printenv CUDA_VISIBLE_DEVICES > j.${name} && + flux run -N1 -n2 \ + --label-io \ + --setattr=alloc-bypass.R="$(cat R.gpu)" \ + -o gpu-affinity="map:7;4-6" \ + printenv CUDA_VISIBLE_DEVICES >${name}.output 2>${name}.err && cat >${name}.expected <<-EOF && 0: 7 1: 4,5,6 EOF - ${FLUX_SHELL} -s -v -r 0 -j j.${name} -R R.gpu 0 | sort -k1,1n \ - > ${name}.out 2>${name}.err && + test_debug "cat ${name}.output ${name}.err" && + sort -k1,1n ${name}.output > ${name}.out && test_cmp ${name}.expected ${name}.out ' test_expect_success 'flux-shell: gpu-affinity=off' ' - name=gpu-off && ( - unset CUDA_VISIBLE_DEVICES && - flux run -N1 -n2 --dry-run -o gpu-affinity=off \ - printenv CUDA_VISIBLE_DEVICES > j.${name} - ) && + name=gpu-off && + test_expect_code 1 flux run -N1 -n2 \ + --label-io \ + --setattr=alloc-bypass.R="$(cat R.gpu)" \ + -o gpu-affinity=off \ + --env=-CUDA_VISIBLE_DEVICES \ + printenv CUDA_VISIBLE_DEVICES >${name}.output 2>${name}.err && cat >${name}.expected <<-EOF && EOF - test_expect_code 1 ${FLUX_SHELL} -s -v -r 0 -j j.${name} -R R.gpu 0 \ - | sort -k1,1n \ - > ${name}.out 2>${name}.err && + test_debug "cat ${name}.output ${name}.err" && + sort -k1,1n ${name}.output > ${name}.out && test_cmp ${name}.expected ${name}.out ' test_expect_success 'flux-shell: gpu-affinity bad arg is ignored' ' name=gpu-bad-arg && - flux run -N1 -n2 --dry-run -o gpu-affinity="[1]" \ - printenv CUDA_VISIBLE_DEVICES > j.${name} && - ${FLUX_SHELL} -s -v -r 0 -j j.${name} -R R.gpu 0 \ - >${name}.out 2>${name}.err && + flux run -N1 -n2 \ + --label-io \ + --setattr=alloc-bypass.R="$(cat R.gpu)" \ + -o gpu-affinity="[1]" \ + printenv CUDA_VISIBLE_DEVICES >${name}.out 2>${name}.err && test_debug "cat ${name}.out" && test_debug "cat ${name}.err" >&2 && grep "Failed to get gpu-affinity shell option" ${name}.err From 65e26168fbb54bfef2144f565cbe68908a0b7f64 Mon Sep 17 00:00:00 2001 From: "Mark A. Grondona" Date: Thu, 19 Oct 2023 10:48:32 -0700 Subject: [PATCH 5/6] shell: drop job shell standalone mode Problem: The job shell standlone mode (provided via the -s, --standalone option) is no longer necessary and adds extra complexity to the shell code. Drop the job shell standalone mode along with the associated options `-j, --jobspec`, `-R, --resources`, `-r, --broker-rank`, `-v, --verbose` and `--initrc`. --- src/shell/evlog.c | 4 - src/shell/exception.c | 9 +-- src/shell/info.c | 165 ++++++++---------------------------------- src/shell/input.c | 45 +++++------- src/shell/internal.h | 1 - src/shell/log.c | 5 +- src/shell/output.c | 25 ++----- src/shell/pmi/pmi.c | 8 +- src/shell/shell.c | 88 ++++++---------------- src/shell/shell.h | 2 +- src/shell/svc.c | 34 ++++----- src/shell/task.c | 2 +- src/shell/tmpdir.c | 3 +- 13 files changed, 106 insertions(+), 285 deletions(-) diff --git a/src/shell/evlog.c b/src/shell/evlog.c index a7eb9586459a..38404790a1c6 100644 --- a/src/shell/evlog.c +++ b/src/shell/evlog.c @@ -210,10 +210,6 @@ static int log_eventlog_start (flux_plugin_t *p, flux_shell_t *shell = flux_plugin_get_shell (p); struct evlog *evlog = NULL; - /* Do not activate eventlogger in standalone mode */ - if (shell->standalone) - return 0; - if (!(evlog = evlog_create (shell))) return -1; if (flux_plugin_aux_set (p, "evlog", evlog, diff --git a/src/shell/exception.c b/src/shell/exception.c index 1bfe28da8866..8274d402ad20 100644 --- a/src/shell/exception.c +++ b/src/shell/exception.c @@ -63,20 +63,17 @@ static int exception_init (flux_plugin_t *p, flux_t *h; flux_jobid_t id; int shell_rank; - int standalone; flux_shell_t *shell = flux_plugin_get_shell (p); if (!shell) return -1; if (!(h = flux_shell_get_flux (shell))) return -1; if (flux_shell_info_unpack (shell, - "{s:I s:i s:{s:b}}", + "{s:I s:i}", "jobid", &id, - "rank", &shell_rank, - "options", - "standalone", &standalone) < 0) + "rank", &shell_rank) < 0) return -1; - if (standalone || shell_rank != 0) + if (shell_rank != 0) return 0; if (flux_shell_service_register (shell, diff --git a/src/shell/info.c b/src/shell/info.c index e3aec5ba3134..baa377c44fa6 100644 --- a/src/shell/info.c +++ b/src/shell/info.c @@ -29,21 +29,7 @@ #include "info.h" #include "jobspec.h" -/* Append string 's' to JSON array 'array'. - * Return 0 on success, -1 on failure. - */ -static int array_append_string (json_t *array, const char *s) -{ - json_t *o; - - if (!(o = json_string (s)) || json_array_append_new (array, o) < 0) { - json_decref (o); - return -1; - } - return 0; -} - -/* If either *jobspec or *R is NULL, fetch it from future and assign. +/* Get R and jobspec from job-info.lookup future and assign. * Return 0 on success, -1 on failure (and log error). * N.B. assigned values remain valid until future is destroyed. */ @@ -51,17 +37,15 @@ static int lookup_job_info_get (flux_future_t *f, char **jobspec, const char **R) { - if (*jobspec == NULL) { - flux_error_t error; - const char *J; - if (flux_rpc_get_unpack (f, "{s:s}", "J", &J) < 0) - goto error; - if (!(*jobspec = flux_unwrap_string (J, true, NULL, &error))) { - shell_log_error ("failed to unwrap J: %s", error.text); - return -1; - } + flux_error_t error; + const char *J; + if (flux_rpc_get_unpack (f, "{s:s}", "J", &J) < 0) + goto error; + if (!(*jobspec = flux_unwrap_string (J, true, NULL, &error))) { + shell_log_error ("failed to unwrap J: %s", error.text); + return -1; } - if (!*R && flux_rpc_get_unpack (f, "{s:s}", "R", R) < 0) + if (flux_rpc_get_unpack (f, "{s:s}", "R", R) < 0) goto error; return 0; error: @@ -69,83 +53,29 @@ static int lookup_job_info_get (flux_future_t *f, return -1; } -/* If either jobspec or R is NULL, fetch it from the job-info service. +/* Fetch R and J from the job-info service. * Return future on success or NULL on failure (and log error). */ -static flux_future_t *lookup_job_info (flux_t *h, - flux_jobid_t jobid, - const char *jobspec, - const char *R) +static flux_future_t *lookup_job_info (flux_t *h, flux_jobid_t jobid) { - json_t *keys; flux_future_t *f; - - if (!(keys = json_array ()) - || (!R && array_append_string (keys, "R") < 0) - || (!jobspec && array_append_string (keys, "J") < 0)) { - shell_log_error ("error building json array"); - return NULL; - } f = flux_rpc_pack (h, "job-info.lookup", FLUX_NODEID_ANY, 0, - "{s:I s:O s:i}", + "{s:I s:[ss] s:i}", "id", jobid, - "keys", keys, + "keys", "R", "J", "flags", 0); if (!f) shell_log_error ("error sending job-info request"); - json_decref (keys); return f; } -/* Read content of file 'optarg' and return it or NULL on failure (log error). - * Caller must free returned result. - */ -static char *parse_arg_file (const char *optarg) -{ - int fd; - ssize_t size; - void *buf = NULL; - - if (streq (optarg, "-")) - fd = STDIN_FILENO; - else { - if ((fd = open (optarg, O_RDONLY)) < 0) { - shell_log_errno ("error opening %s", optarg); - return NULL; - } - } - if ((size = read_all (fd, &buf)) < 0) - shell_log_errno ("error reading %s", optarg); - if (fd != STDIN_FILENO) - (void)close (fd); - return buf; -} - -/* If option 'name' exists, read it as a file and exit on failure. - * O/w, return NULL. - */ -static char *optparse_check_and_loadfile (optparse_t *p, const char *name) -{ - char *result = NULL; - const char *path = optparse_get_str (p, name, NULL); - if (path) { - if (!(result = parse_arg_file (path))) - exit (1); - return result; - } - return NULL; -} - /* Fetch jobinfo (jobspec, R) from job-info service if not provided on * command line, and parse. */ -static int shell_init_jobinfo (flux_shell_t *shell, - struct shell_info *info, - const char *jobspec_provided, - const char *R_provided) +static int shell_init_jobinfo (flux_shell_t *shell, struct shell_info *info) { int rc = -1; flux_future_t *f_info = NULL; @@ -155,53 +85,31 @@ static int shell_init_jobinfo (flux_shell_t *shell, const char *R; json_error_t error; - R = R_provided; - if (jobspec_provided && !(jobspec = strdup (jobspec_provided))) - shell_die (1, "Out of memory copying provided jobspec"); - - /* If shell is not running standalone, fetch hwloc topology - * from resource module to avoid having to load from scratch - * here. The topology XML is then cached for future shell plugin - * use. + /* fetch hwloc topology from resource module to avoid having to + * load from scratch here. The topology XML is then cached for + * future shell plugin use. */ - if (!shell->standalone - && !(f_hwloc = flux_rpc (shell->h, - "resource.topo-get", - NULL, - FLUX_NODEID_ANY, - 0))) + if (!(f_hwloc = flux_rpc (shell->h, + "resource.topo-get", + NULL, + FLUX_NODEID_ANY, + 0))) goto out; - if (!R || !jobspec) { - /* Fetch missing jobinfo from broker job-info service */ - if (shell->standalone) { - shell_log_error ("Invalid arguments: standalone and R/jobspec are unset"); - goto out; - } - if (!(f_info = lookup_job_info (shell->h, - shell->jobid, - jobspec_provided, - R_provided))) - goto out; - } + /* fetch jobspec (via J) and R for this job + */ + if (!(f_info = lookup_job_info (shell->h, shell->jobid))) + goto out; - if (f_hwloc) { - if (flux_rpc_get (f_hwloc, &xml) < 0 - || !(info->hwloc_xml = strdup (xml))) { - shell_log_error ("error fetching local hwloc xml"); - goto out; - } - } - else { - /* We couldn't fetch hwloc, load a copy manually */ + if (flux_rpc_get (f_hwloc, &xml) < 0 + || !(info->hwloc_xml = strdup (xml))) { + shell_log_error ("error fetching local hwloc xml"); if (!(info->hwloc_xml = rhwloc_local_topology_xml (0))) { shell_log_error ("error loading local hwloc xml"); goto out; } } - - if (f_info && - lookup_job_info_get (f_info, &jobspec, &R) < 0) { + if (lookup_job_info_get (f_info, &jobspec, &R) < 0) { shell_log_error ("error fetching jobspec,R"); goto out; } @@ -295,8 +203,6 @@ int shell_info_set_taskmap (struct shell_info *info, struct shell_info *shell_info_create (flux_shell_t *shell) { struct shell_info *info; - char *R = NULL; - char *jobspec = NULL; const char *per_resource = NULL; int per_resource_count = -1; int broker_rank = shell->broker_rank; @@ -308,18 +214,9 @@ struct shell_info *shell_info_create (flux_shell_t *shell) } info->jobid = shell->jobid; - /* Check for jobspec and/or R on cmdline: - */ - jobspec = optparse_check_and_loadfile (shell->p, "jobspec"); - R = optparse_check_and_loadfile (shell->p, "resources"); - - if (shell_init_jobinfo (shell, info, jobspec, R) < 0) + if (shell_init_jobinfo (shell, info) < 0) goto error; - /* Done with potentially allocated jobspec, R strings */ - free (jobspec); - free (R); - if (get_per_resource_option (info->jobspec, &per_resource, &per_resource_count) < 0) diff --git a/src/shell/input.c b/src/shell/input.c index c6b81125bac5..e4e564d34e14 100644 --- a/src/shell/input.c +++ b/src/shell/input.c @@ -445,30 +445,27 @@ struct shell_input *shell_input_create (flux_shell_t *shell) goto error; if (shell->info->shell_rank == 0) { - /* can't use stdin in standalone, no kvs to write to */ - if (!in->shell->standalone) { - if (in->stdin_type == FLUX_INPUT_TYPE_SERVICE) { - if (flux_shell_service_register (in->shell, - "stdin", - shell_input_stdin_cb, - in) < 0) - shell_die_errno (1, "flux_shell_service_register"); - - /* Do not add a completion reference for the stdin service, we - * don't care if the user ever sends stdin */ - } + if (in->stdin_type == FLUX_INPUT_TYPE_SERVICE) { + if (flux_shell_service_register (in->shell, + "stdin", + shell_input_stdin_cb, + in) < 0) + shell_die_errno (1, "flux_shell_service_register"); + + /* Do not add a completion reference for the stdin service, we + * don't care if the user ever sends stdin */ + } - if (shell_input_header (in) < 0) - goto error; + if (shell_input_header (in) < 0) + goto error; - if (in->stdin_type == FLUX_INPUT_TYPE_FILE) { - if (shell_input_type_file_setup (in) < 0) - goto error; - /* Ok to start fd watcher now since shell_input_header() - * synchronously write guest.input header. - */ - flux_watcher_start (in->stdin_file.w); - } + if (in->stdin_type == FLUX_INPUT_TYPE_FILE) { + if (shell_input_type_file_setup (in) < 0) + goto error; + /* Ok to start fd watcher now since shell_input_header() + * synchronously write guest.input header. + */ + flux_watcher_start (in->stdin_file.w); } } @@ -622,9 +619,7 @@ static int shell_input_task_init (flux_plugin_t *p, task_input->task = task; if (task_input->type == FLUX_TASK_INPUT_KVS) { - /* can't read stdin in standalone mode, no KVS to read from */ - if (!task_input->in->shell->standalone - && shell_task_input_kvs_start (task_input) < 0) + if (shell_task_input_kvs_start (task_input) < 0) shell_die_errno (1, "shell_input_start_task_watch"); } return 0; diff --git a/src/shell/internal.h b/src/shell/internal.h index 15409538ee5a..0d91d81c049e 100644 --- a/src/shell/internal.h +++ b/src/shell/internal.h @@ -47,7 +47,6 @@ struct flux_shell { int rc; int verbose; - bool standalone; int nosetpgrp; struct aux_item *aux; diff --git a/src/shell/log.c b/src/shell/log.c index 4548a7d135e2..5e5b7495bc52 100644 --- a/src/shell/log.c +++ b/src/shell/log.c @@ -291,7 +291,7 @@ void flux_shell_fatal (const char *component, */ flux_shell_killall (shell, SIGKILL); - if (shell && !shell->standalone) + if (shell) flux_shell_raise ("exec", 0, "%s", buf); exit (exit_code); @@ -336,12 +336,9 @@ int flux_shell_log_setlevel (int level, const char *dest) } /* Always set internal dispatch level. - * In standalone mode, also set stderr level by default */ if (level > logger.level) logger.level = level; - if (logger.shell->standalone) - logger.fp_level = level; if (dest == NULL) return 0; diff --git a/src/shell/output.c b/src/shell/output.c index 8a293f8ef9f9..dc3b4260326b 100644 --- a/src/shell/output.c +++ b/src/shell/output.c @@ -34,8 +34,6 @@ * there (checked for error, then destroyed). * - Any outstanding file writes at shell_output_destroy() are * synchronously waited for to complete. - * - In standalone mode, the loop:// connector enables RPCs to work - * - In standalone mode, output is written to the shell's stdout/stderr not KVS * - The number of in-flight write requests on each shell is limited to * shell_output_hwm, to avoid matchtag exhaustion, etc. for chatty tasks. */ @@ -784,9 +782,7 @@ static int shell_output_parse_type (struct shell_output *out, const char *typestr, int *typep) { - if (out->shell->standalone && streq (typestr, "term")) - (*typep) = FLUX_OUTPUT_TYPE_TERM; - else if (streq (typestr, "kvs")) + if (streq (typestr, "kvs")) (*typep) = FLUX_OUTPUT_TYPE_KVS; else if (streq (typestr, "file")) (*typep) = FLUX_OUTPUT_TYPE_FILE; @@ -1039,13 +1035,10 @@ static int shell_output_header (struct shell_output *out) shell_log_errno ("shell_output_term_init"); } /* emit initial output events. - * Call this as long as we're not standalone. */ - if (!out->shell->standalone) { - if (shell_output_kvs_init (out, o) < 0) { - shell_log_errno ("shell_output_kvs_init"); - goto error; - } + if (shell_output_kvs_init (out, o) < 0) { + shell_log_errno ("shell_output_kvs_init"); + goto error; } rc = 0; error: @@ -1149,14 +1142,8 @@ struct shell_output *shell_output_create (flux_shell_t *shell) if (!(out = calloc (1, sizeof (*out)))) return NULL; out->shell = shell; - if (out->shell->standalone) { - out->stdout_type = FLUX_OUTPUT_TYPE_TERM; - out->stderr_type = FLUX_OUTPUT_TYPE_TERM; - } - else { - out->stdout_type = FLUX_OUTPUT_TYPE_KVS; - out->stderr_type = FLUX_OUTPUT_TYPE_KVS; - } + out->stdout_type = FLUX_OUTPUT_TYPE_KVS; + out->stderr_type = FLUX_OUTPUT_TYPE_KVS; out->stdout_buffer_type = "line"; out->stderr_buffer_type = "none"; diff --git a/src/shell/pmi/pmi.c b/src/shell/pmi/pmi.c index 8e8c2fcedb99..1b40ceff9d8a 100644 --- a/src/shell/pmi/pmi.c +++ b/src/shell/pmi/pmi.c @@ -567,11 +567,9 @@ static struct shell_pmi *pmi_create (flux_shell_t *shell, json_t *config) } if (!nomap && init_clique (pmi) < 0) goto error; - if (!shell->standalone) { - if (set_flux_instance_level (pmi) < 0 - || (!nomap && set_flux_taskmap (pmi) < 0)) - goto error; - } + if (set_flux_instance_level (pmi) < 0 + || (!nomap && set_flux_taskmap (pmi) < 0)) + goto error; return pmi; error: pmi_destroy (pmi); diff --git a/src/shell/shell.c b/src/shell/shell.c index 8c23ba7f3fa7..f400da929259 100644 --- a/src/shell/shell.c +++ b/src/shell/shell.c @@ -47,18 +47,6 @@ static char *shell_name = "flux-shell"; static const char *shell_usage = "[OPTIONS] JOBID"; static struct optparse_option shell_opts[] = { - { .name = "jobspec", .key = 'j', .has_arg = 1, .arginfo = "FILE", - .usage = "Get jobspec from FILE, not job-info service", }, - { .name = "resources", .key = 'R', .has_arg = 1, .arginfo = "FILE", - .usage = "Get R from FILE, not job-info service", }, - { .name = "broker-rank", .key = 'r', .has_arg = 1, .arginfo = "RANK", - .usage = "Set broker rank, rather than asking broker", }, - { .name = "verbose", .key = 'v', .has_arg = 0, - .usage = "Log actions to stderr", }, - { .name = "standalone", .key = 's', .has_arg = 0, - .usage = "Run local program without Flux instance", }, - { .name = "initrc", .has_arg = 1, .arginfo = "FILE", - .usage = "Load shell initrc from FILE instead of the system default" }, { .name = "reconnect", .has_arg = 0, .usage = "Attempt to reconnect if broker connection is lost" }, OPTPARSE_TABLE_END @@ -211,20 +199,6 @@ static void shell_parse_cmdline (flux_shell_t *shell, int argc, char *argv[]) if (parse_jobid (argv[optindex++], &shell->jobid) < 0) exit (1); - /* In standalone mode, jobspec, resources and broker-rank must be - * set on command line: - */ - if ((shell->standalone = optparse_hasopt (p, "standalone"))) { - if ( !optparse_hasopt (p, "jobspec") - || !optparse_hasopt (p, "resources") - || !optparse_hasopt (p, "broker-rank")) - shell_die (1, "standalone mode requires --jobspec, " - "--resources and --broker-rank"); - } - - if ((shell->verbose = optparse_getopt (p, "verbose", NULL))) - shell_set_verbose (shell->verbose); - shell->broker_rank = optparse_get_int (p, "broker-rank", -1); shell->p = p; } @@ -281,13 +255,10 @@ static int reconnect (flux_t *h, void *arg) static void shell_connect_flux (flux_shell_t *shell) { + uint32_t rank; int flags = optparse_hasopt (shell->p, "reconnect") ? FLUX_O_RPCTRACK : 0; - if (shell->standalone) - shell->h = flux_open ("loop://", FLUX_O_TEST_NOSUB); - else - shell->h = flux_open (NULL, flags); - if (!shell->h) + if (!(shell->h = flux_open (NULL, flags))) shell_die_errno (1, "flux_open"); if (optparse_hasopt (shell->p, "reconnect")) @@ -297,14 +268,12 @@ static void shell_connect_flux (flux_shell_t *shell) */ flux_set_reactor (shell->h, shell->r); - /* Fetch local rank if not already set + /* Fetch local rank */ - if (shell->broker_rank < 0) { - uint32_t rank; - if (flux_get_rank (shell->h, &rank) < 0) - shell_log_errno ("error fetching broker rank"); - shell->broker_rank = rank; - } + if (flux_get_rank (shell->h, &rank) < 0) + shell_log_errno ("error fetching broker rank"); + shell->broker_rank = rank; + if (plugstack_call (shell->plugstack, "shell.connect", NULL) < 0) shell_log_errno ("shell.connect"); } @@ -458,7 +427,7 @@ static json_t *flux_shell_get_info_object (flux_shell_t *shell) return o; if (!(o = json_pack_ex (&err, 0, - "{ s:I s:i s:i s:i s:s s:O s:O s:{ s:i s:b }}", + "{ s:I s:i s:i s:i s:s s:O s:O s:{ s:i }}", "jobid", shell->info->jobid, "rank", shell->info->shell_rank, "size", shell->info->shell_size, @@ -467,8 +436,7 @@ static json_t *flux_shell_get_info_object (flux_shell_t *shell) "jobspec", shell->info->jobspec->jobspec, "R", shell->info->R, "options", - "verbose", shell->verbose, - "standalone", shell->standalone))) + "verbose", shell->verbose))) return NULL; if (flux_shell_aux_set (shell, "shell::info", @@ -1239,7 +1207,7 @@ static int shell_barrier (flux_shell_t *shell, const char *name) { char buf [8]; - if (shell->standalone || shell->info->shell_size == 1) + if (shell->info->shell_size == 1) return 0; // NO-OP if (shell->protocol_fd[1] < 0) @@ -1271,16 +1239,15 @@ static int load_initrc (flux_shell_t *shell, const char *default_rcfile) /* If initrc is set on command line or in jobspec, then * it is required, O/w initrc is treated as empty file. */ - if (optparse_getopt (shell->p, "initrc", &rcfile) > 0 - || flux_shell_getopt_unpack (shell, "initrc", "s", &rcfile) > 0) + if (flux_shell_getopt_unpack (shell, "initrc", "s", &rcfile) > 0) required = true; else rcfile = default_rcfile; - /* Skip loading initrc file if it is not required and either the shell - * is running in standalone mode, or the file isn't readable. + /* Skip loading initrc file if it is not required or the file isn't + * readable. */ - if (!required && (shell->standalone || access (rcfile, R_OK) < 0)) + if (!required && access (rcfile, R_OK) < 0) return 0; shell_debug ("Loading %s", rcfile); @@ -1299,17 +1266,12 @@ static int load_initrc (flux_shell_t *shell, const char *default_rcfile) static int shell_initrc (flux_shell_t *shell) { const char *default_rcfile = shell_conf_get ("shell_initrc"); + const char *result; - /* Override pluginpath, default rcfile from broker attribute - * if not in standalone mode. - */ - if (!shell->standalone) { - const char *result; - if ((result = flux_attr_get (shell->h, "conf.shell_pluginpath"))) - plugstack_set_searchpath (shell->plugstack, result); - if ((result = flux_attr_get (shell->h, "conf.shell_initrc"))) - default_rcfile = result; - } + if ((result = flux_attr_get (shell->h, "conf.shell_pluginpath"))) + plugstack_set_searchpath (shell->plugstack, result); + if ((result = flux_attr_get (shell->h, "conf.shell_initrc"))) + default_rcfile = result; /* Change current working directory once before all tasks are * created, so that each task does not need to chdir(). @@ -1499,7 +1461,7 @@ static int shell_register_event_context (flux_shell_t *shell) { int rc = -1; json_t *o = NULL; - if (shell->standalone || shell->info->shell_rank != 0) + if (shell->info->shell_rank != 0) return 0; o = taskmap_encode_json (shell->info->taskmap, TASKMAP_ENCODE_WRAPPED); if (o == NULL @@ -1580,7 +1542,7 @@ int main (int argc, char *argv[]) if (!(shell.r = flux_reactor_create (FLUX_REACTOR_SIGCHLD))) shell_die_errno (1, "flux_reactor_create"); - /* Connect to broker, or if standalone, open loopback connector. + /* Connect to broker: */ shell_connect_flux (&shell); @@ -1650,11 +1612,9 @@ int main (int argc, char *argv[]) if (shell_barrier (&shell, "init") < 0) shell_die_errno (1, "shell_barrier"); - /* Emit an event after barrier completion from rank 0 if not in - * standalone mode. + /* Emit an event after barrier completion from rank 0 */ if (shell.info->shell_rank == 0 - && !shell.standalone && shell_eventlogger_emit_event (shell.ev, "shell.init") < 0) shell_die_errno (1, "failed to emit event shell.init"); @@ -1727,11 +1687,9 @@ int main (int argc, char *argv[]) if (shell_barrier (&shell, "start") < 0) shell_die_errno (1, "shell_barrier"); - /* Emit an event after barrier completion from rank 0 if not in - * standalone mode. + /* Emit an event after barrier completion from rank 0 */ if (shell.info->shell_rank == 0 - && !shell.standalone && shell_eventlogger_emit_event (shell.ev, "shell.start") < 0) shell_die_errno (1, "failed to emit event shell.start"); diff --git a/src/shell/shell.h b/src/shell/shell.h index 1b4eea171067..b84591927401 100644 --- a/src/shell/shell.h +++ b/src/shell/shell.h @@ -109,7 +109,7 @@ const struct taskmap *flux_shell_get_taskmap (flux_shell_t *shell); * "size":i, * "ntasks";i, * "service":s, - * "options": { "verbose":b, "standalone":b }, + * "options": { "verbose":b }, * "jobspec":o, * "R":o * } diff --git a/src/shell/svc.c b/src/shell/svc.c index f7b842db9eb5..dc74ed8d9de2 100644 --- a/src/shell/svc.c +++ b/src/shell/svc.c @@ -157,6 +157,7 @@ struct shell_svc *shell_svc_create (flux_shell_t *shell) struct shell_svc *svc; struct rcalc_rankinfo ri; int shell_size = shell->info->shell_size; + flux_future_t *f; int i; if (!(svc = calloc (1, sizeof (*svc)))) @@ -170,26 +171,23 @@ struct shell_svc *shell_svc_create (flux_shell_t *shell) goto error; svc->rank_table[i] = ri.rank; } - if (!shell->standalone) { - flux_future_t *f; - if (build_topic (svc, NULL, svc->name, sizeof (svc->name)) < 0) - goto error; - if (!(f = flux_service_register (shell->h, svc->name))) - goto error; - if (flux_future_get (f, NULL) < 0) { - flux_future_destroy (f); - goto error; - } + if (build_topic (svc, NULL, svc->name, sizeof (svc->name)) < 0) + goto error; + if (!(f = flux_service_register (shell->h, svc->name))) + goto error; + if (flux_future_get (f, NULL) < 0) { flux_future_destroy (f); - if (flux_shell_add_event_context (shell, - "shell.init", - 0, - "{s:s}", - "service", - svc->name) < 0) - goto error; - svc->registered = 1; + goto error; } + flux_future_destroy (f); + if (flux_shell_add_event_context (shell, + "shell.init", + 0, + "{s:s}", + "service", + svc->name) < 0) + goto error; + svc->registered = 1; return svc; error: shell_svc_destroy (svc); diff --git a/src/shell/task.c b/src/shell/task.c index 3a8b92153e27..f9c8bdeb9d58 100644 --- a/src/shell/task.c +++ b/src/shell/task.c @@ -21,7 +21,7 @@ * . FLUX_JOB_SIZE * . FLUX_JOB_NNODES * . FLUX_JOB_ID - * . FLUX_URI (if not running standalone) + * . FLUX_URI * . correct HOSTNAME if set in job environment * * Current working directory diff --git a/src/shell/tmpdir.c b/src/shell/tmpdir.c index 32b403ac62f7..8b21abf1af07 100644 --- a/src/shell/tmpdir.c +++ b/src/shell/tmpdir.c @@ -57,8 +57,7 @@ static int mkjobtmp_rundir (flux_shell_t *shell, char *buf, size_t size) { const char *rundir; - if (shell->standalone - || !(rundir = flux_attr_get (shell->h, "rundir")) + if (!(rundir = flux_attr_get (shell->h, "rundir")) || make_job_path (shell, rundir, buf, size) < 0 || mkdir_exist_ok (buf, true) < 0) return -1; From 9659ef8cfde48d5024e08e008d64da5fe7d4ca26 Mon Sep 17 00:00:00 2001 From: "Mark A. Grondona" Date: Thu, 19 Oct 2023 10:49:39 -0700 Subject: [PATCH 6/6] doc: update job shell options in flux-shell(1) Problem: The job shell `-s, --standalone` option and other options associated with its use are no longer supported, but they're still documented in the flux-shell(1) man page. Drop the mention of -s, --standalone and related options (-j, -R, -v, and --initrc) from the man page. Document the `--reconnect` option since it was missing. --- doc/man1/flux-shell.rst | 30 ++---------------------------- 1 file changed, 2 insertions(+), 28 deletions(-) diff --git a/doc/man1/flux-shell.rst b/doc/man1/flux-shell.rst index 422b3e36e32c..348f935bbd52 100644 --- a/doc/man1/flux-shell.rst +++ b/doc/man1/flux-shell.rst @@ -32,35 +32,14 @@ even extend the shell itself via simple shell plugins developed directly in Lua. See the SHELL INITRC section below for details of the ``initrc`` format and features. -Most Flux users will interact with flux-shell(1) indirectly through -the execution of Flux jobs, however flux-shell(1) accepts the following -OPTIONS in standalone mode (``-s, --standalone``), for testing purposes. - OPTIONS ======= **-h, --help** Summarize available options. -**-v, --verbose** - Log actions to stderr. - -**--initrc**\ =\ *FILE* - Load shell initrc from FILE instead of the system default. - -**-R, --resources**\ =\ *FILE* - Load resource set **R** from a file instead of job-info service. This is - used for testing. - -**-j, --jobspec**\ =\ *FILE* - Load jobspec from FILE instead of job-info service. This is used for - testing. - -**-s, --standalone** - Run as as a local program without Flux instance. Used for testing. - In standalone mode an initrc file is not loaded unless specifically - requested via the ``--initrc`` option or specified in jobspec. - +**--reconnect** + Attempt to reconnect if broker connection is lost. OPERATION ========= @@ -485,9 +464,6 @@ supported. Job shell specific functions and tables are described below: Current flux-shell verbosity. This value may be changed at runtime, e.g. ``shell.options.verbose = 2`` to set maximum verbosity. -**shell.options.standalone** - True if the shell is running in "standalone" mode for testing. - **shell.info** Returns a Lua table of shell information obtained via :man3:`flux_shell_get_info`. This table includes @@ -504,8 +480,6 @@ supported. Job shell specific functions and tables are described below: The service string advertised by the shell. **options.verbose** True if the shell is running in verbose mode. - **options.standalone** - True if the shell was run in standalone mode. **jobspec** The jobspec of the current job **R**