Power: say why a BMC command failed (CLI, UI); certificate changes are events
Found in the lab test of certificate pinning: the CLI printed only 'ipmitool failed on 1 machine(s)'. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
9ab081aa5a
commit
d0ea29d2a9
4 files changed
+21
-5
No files matched your search
@@ -232,13 +232,16 @@ func runClient(cmd string, args []string) error {
|
||||
if len(ids) > 1 {
|
||||
fmt.Printf("%s: ", id)
|
||||
}
|
||||
fmt.Println(str(d["output"]))
|
||||
if o := str(d["output"]); o != "" {
|
||||
fmt.Println(o)
|
||||
}
|
||||
if ok, _ := d["ok"].(bool); !ok {
|
||||
fmt.Println("error:", orDefault(str(d["error"]), "the BMC command failed"))
|
||||
failed++
|
||||
}
|
||||
}
|
||||
if failed > 0 {
|
||||
return fmt.Errorf("ipmitool failed on %d machine(s)", failed)
|
||||
return fmt.Errorf("power %s failed on %d machine(s)", args[1], failed)
|
||||
}
|
||||
case "bootdev":
|
||||
_ = need(2)
|
||||
|
||||
+10
-1
@@ -72,7 +72,16 @@ func (a *App) power(ctx context.Context, m *Machine, op, arg string) (string, er
|
||||
if c, err = a.pinBMC(ctx, m, c); err != nil {
|
||||
return "", err
|
||||
}
|
||||
return a.powerVia(ctx, a.rackOf(m), c, op, arg)
|
||||
out, err := a.powerVia(ctx, a.rackOf(m), c, op, arg)
|
||||
a.noteCertChange(ctx, m, err)
|
||||
return out, err
|
||||
}
|
||||
|
||||
// noteCertChange puts a refused BMC certificate on the machine's events.
|
||||
func (a *App) noteCertChange(ctx context.Context, m *Machine, err error) {
|
||||
if err != nil && strings.Contains(err.Error(), "certificate changed") {
|
||||
_ = a.store.AddEvent(ctx, m.ID, "bmc certificate changed", oneLine(err.Error()))
|
||||
}
|
||||
}
|
||||
|
||||
// pinBMC records the certificate of an HTTPS BMC (Redfish, Proxmox) before
|
||||
|
||||
@@ -786,7 +786,11 @@ func (a *App) handlePower(w http.ResponseWriter, r *http.Request) {
|
||||
if action != "status" {
|
||||
_ = a.store.AddEvent(r.Context(), m.ID, "power "+action, out)
|
||||
}
|
||||
writeJSON(w, 200, obj{"id": m.ID, "action": action, "ok": err == nil, "output": out})
|
||||
res := obj{"id": m.ID, "action": action, "ok": err == nil, "output": out}
|
||||
if err != nil {
|
||||
res["error"] = err.Error()
|
||||
}
|
||||
writeJSON(w, 200, res)
|
||||
}
|
||||
|
||||
func (a *App) handleBootdev(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
@@ -355,7 +355,7 @@ async function each(ids, label, fn) {
|
||||
await refresh(true);
|
||||
}
|
||||
const act = {
|
||||
power: (ids, action) => each(ids, `power ${action}`, async id => { const r = await api('POST', `/api/v1/machines/${id}/power`, { action }); return r.output || (r.ok ? 'ok' : 'failed'); }),
|
||||
power: (ids, action) => each(ids, `power ${action}`, async id => { const r = await api('POST', `/api/v1/machines/${id}/power`, { action }); if (!r.ok) throw new Error(r.error || r.output || 'the BMC command failed'); return r.output || 'ok'; }),
|
||||
bootdev: (ids, device) => each(ids, `bootdev ${device}`, async id => { const r = await api('POST', `/api/v1/machines/${id}/bootdev`, { device }); return r.output || (r.ok ? 'ok' : 'failed'); }),
|
||||
async deploy(ids) {
|
||||
const one = ids.length === 1 ? S.machines.find(m => m.id === ids[0]) : null;
|
||||
|
||||
Reference in new issue
Block a user