platform/app/webui: ship the power-watch scenario baked into the image
platform.LocalScenariosDir (/usr/share/bee/scenarios, populated from iso/overlay/usr/share/bee/scenarios/ by build.sh's overlay rsync) is now checked before removable media for both `bee run <name>` and the "6. Scenario" page — a scenario shipped with the image works with no USB stick required. ReadScenario/ListAvailableScenarios merge local + USB; the removable-media-only functions from the previous commit are kept as-is (still used directly where that's actually what's wanted) rather than renamed out from under existing callers/tests. iso/overlay/usr/share/bee/scenarios/nvbandwidth-all-gpu-power-watch.json is a copy of scenarios/nvbandwidth-all-gpu-power-watch.json — the two aren't auto-synced (documented in scenarios/README.md), so shipping a scenario baked-in means checking it into both places. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
bcf02e0515
commit
5a780e96b4
@@ -582,7 +582,7 @@ func (h *handler) handleAPIScenarioList(w http.ResponseWriter, _ *http.Request)
|
||||
writeError(w, http.StatusServiceUnavailable, "app not configured")
|
||||
return
|
||||
}
|
||||
files, err := h.opts.App.ListScenarioFilesOnRemovableMedia()
|
||||
files, err := h.opts.App.ListAvailableScenarios()
|
||||
if err != nil {
|
||||
writeError(w, http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
|
||||
@@ -1,28 +1,31 @@
|
||||
package webui
|
||||
|
||||
// renderScenario renders the "6. Scenario" page: scenarios/*.json files
|
||||
// found on any mounted removable media (e.g. the blackbox USB stick),
|
||||
// each runnable with one click. A run is enqueued as a normal Task
|
||||
// (target "scenario") — progress/logs live in Tasks like every other SAT
|
||||
// pack, no separate live-output UI needed here.
|
||||
// renderScenario renders the "6. Scenario" page: every scenarios/*.json
|
||||
// runnable via platform.System.ReadScenario — the ones shipped with the
|
||||
// image (platform.LocalScenariosDir) plus anything found on mounted
|
||||
// removable media (e.g. the blackbox USB stick) — each runnable with one
|
||||
// click. A run is enqueued as a normal Task (target "scenario") —
|
||||
// progress/logs live in Tasks like every other SAT pack, no separate
|
||||
// live-output UI needed here.
|
||||
//
|
||||
// See audit/internal/platform/scenario.go for the scenario file format and
|
||||
// scenarios/README.md for the drop-a-file-on-the-USB-stick workflow this
|
||||
// page is built around.
|
||||
// scenarios/README.md for how to add one (shipped in the image, or dropped
|
||||
// on the USB stick for a one-off/air-gapped run).
|
||||
func renderScenario(opts HandlerOptions) string {
|
||||
return `<p style="color:var(--muted);font-size:13px;margin-bottom:16px">
|
||||
Scripted, ad-hoc test scenarios — commands plus background samplers (IPMI
|
||||
sensors, nvidia-smi, ...), described in a small JSON file instead of a
|
||||
hardcoded test. Drop a <code><name>.json</code> file under
|
||||
<code>scenarios/</code> on a removable drive (e.g. the same USB stick
|
||||
already plugged in for blackbox) and it shows up below — no rebuild
|
||||
needed. Runs are enqueued like any other task; watch progress in
|
||||
hardcoded test. The list below includes scenarios shipped with this image
|
||||
as well as any <code><name>.json</code> dropped under
|
||||
<code>scenarios/</code> on a mounted removable drive (e.g. the same USB
|
||||
stick already plugged in for blackbox) — no rebuild needed for the
|
||||
latter. Runs are enqueued like any other task; watch progress in
|
||||
<a href="/tasks">Tasks</a>.
|
||||
</p>
|
||||
|
||||
<div class="card">
|
||||
<div class="card-head">
|
||||
<span>Scenarios found on removable media</span>
|
||||
<span>Available scenarios</span>
|
||||
<button class="btn btn-sm btn-secondary" type="button" onclick="scenarioRefresh()">↻ Refresh</button>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
@@ -38,7 +41,7 @@ function scenarioRefresh() {
|
||||
.then(r => r.json())
|
||||
.then(files => {
|
||||
if (!files || !files.length) {
|
||||
list.innerHTML = '<p style="color:var(--muted);font-size:13px">No scenarios/*.json found on any mounted removable media.</p>';
|
||||
list.innerHTML = '<p style="color:var(--muted);font-size:13px">No scenarios found — none shipped with this image and none under scenarios/ on mounted removable media.</p>';
|
||||
return;
|
||||
}
|
||||
let html = '<table class="table"><thead><tr><th>Name</th><th>Found on</th><th></th></tr></thead><tbody>';
|
||||
|
||||
@@ -995,7 +995,7 @@ func (q *taskQueue) runTask(t *Task, j *jobState, ctx context.Context) {
|
||||
break
|
||||
}
|
||||
var data []byte
|
||||
data, err = a.ReadScenarioFromRemovableMedia(t.params.ScenarioName)
|
||||
data, err = a.ReadScenario(t.params.ScenarioName)
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user