Host power-off for the household (R-998): POST /host/poweroff
gates / gates (push) Successful in 34s
gates / gates (push) Successful in 34s
The guest's controller asks; the agent refuses in the first 10 min after boot, a second time in one boot (persisted, keyed by /proc/stat btime), and while a backup, restore test, OS step, controller update, drive format, NAS verify, escrow ceremony or vzdump runs (each a named 409 reason). On acceptance: the record first, a host report carrying deliberate_off accepted by the hub (bounded 60 s), then pct shutdown --timeout 120, then systemctl poweroff. Sudoers: two exact vectors (pct ^shutdown N --timeout N$, systemctl poweroff) in FELHOM_POWEROFF; nine injection cases. New TestEveryAliasIsGranted: a defined alias missing from the grant line passed the coverage check before. Every new test red-proofed.
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
package localapi
|
||||
|
||||
import (
|
||||
"time"
|
||||
"context"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
@@ -104,6 +105,26 @@ func (b *GuestBinder) RebootGuest(ctx context.Context, vmid int) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// ShutdownGuest stops the guest cleanly with a time limit (R-998 host power-off, step 2). `pct shutdown`
|
||||
// blocks until the guest is down or the limit passes; then it fails and the guest is still running.
|
||||
func (b *GuestBinder) ShutdownGuest(ctx context.Context, vmid int, timeout time.Duration) error {
|
||||
secs := int(timeout / time.Second)
|
||||
if secs < 1 {
|
||||
secs = 1
|
||||
}
|
||||
b.logger.Warn("host-poweroff: shutting the guest down", "vmid", vmid, "timeout_s", secs)
|
||||
if err := b.run(ctx, "pct", "shutdown", strconv.Itoa(vmid), "--timeout", strconv.Itoa(secs)); err != nil {
|
||||
return fmt.Errorf("host-poweroff: pct shutdown %d: %w", vmid, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// PowerOffHost powers the Proxmox host off (R-998, step 3). The one fixed vector `/usr/bin/systemctl poweroff`.
|
||||
func (b *GuestBinder) PowerOffHost(ctx context.Context) error {
|
||||
b.logger.Warn("host-poweroff: powering the host off")
|
||||
return b.run(ctx, "/usr/bin/systemctl", "poweroff")
|
||||
}
|
||||
|
||||
func (b *GuestBinder) run(ctx context.Context, name string, args ...string) error {
|
||||
_, stderr, err := b.runner.Run(ctx, name, args...)
|
||||
if err != nil {
|
||||
|
||||
Reference in New Issue
Block a user