Virtualization tab, phase 1: Incus per machine — detect, install, instances, consoles, snapshots, images
The tab reports one of four states for the selected machine (ready, repair, installable, unavailable) from what it finds — /dev/kvm, the package manager's incus candidate, the pool drivers the kernel has — and acts on that machine only. Install is one followed task: packages, a pool whose backing file sits in Ham Lab's own virt/ folder (zfs pool on a file, btrfs on a loop mount, or a plain dir), a bridge on a subnet picked clear of the machine's routes and Docker's pools (never 10.x on a /8 LAN), the DOCKER-USER rules that keep Docker's FORWARD drop off the bridge, the incus-admin group for Ham Lab's account, and a restart. Instances list with live CPU and memory, create from the images: catalogue or a local image (container or VM, limits, cloud-init), start/stop/restart/force-stop/rename/ delete, console and shell as terminal tabs, snapshots with Incus's own schedule and expiry, limits editing. Images: local store, catalogue search and download (exported into the library too), import a tarball or a VM disk from a path, publish an instance. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5.1
parent
af53b45b67
commit
240129c83f
@@ -34,6 +34,7 @@ import (
|
||||
"hamlab/internal/cron"
|
||||
"hamlab/internal/files"
|
||||
"hamlab/internal/hardware"
|
||||
"hamlab/internal/incus"
|
||||
"hamlab/internal/metrics"
|
||||
"hamlab/internal/network"
|
||||
"hamlab/internal/nodes"
|
||||
@@ -75,6 +76,7 @@ type Server struct {
|
||||
update updateState
|
||||
events eventLog
|
||||
kvms kvmProxies
|
||||
virt *incus.Manager
|
||||
fsLocal files.FS
|
||||
fsSudo files.FS // nil without passwordless sudo
|
||||
nodes *nodes.Manager
|
||||
@@ -104,6 +106,7 @@ func New(cfg *config.Config, sessions *auth.Sessions, mgr *term.Manager, col *me
|
||||
if s.user == "" {
|
||||
s.user = "?"
|
||||
}
|
||||
s.virt = incus.New(cfg.DataDir(), s.user, version)
|
||||
s.migrateUsers()
|
||||
// The speed test and the outside view. Its history outlives a restart, and its last result
|
||||
// is published as sensors, so the line is graphable and alertable like anything else.
|
||||
@@ -239,6 +242,20 @@ func (s *Server) routes() *http.ServeMux {
|
||||
m.HandleFunc("GET /api/docker/containers/{id}/events", s.auth(s.dockerEvents))
|
||||
m.HandleFunc("POST /api/docker/containers/{id}/exec", s.auth(s.dockerExec))
|
||||
m.HandleFunc("POST /api/docker/containers/{id}/limits", s.auth(s.dockerUpdate))
|
||||
m.HandleFunc("GET /api/virt", s.auth(s.virtOverview))
|
||||
m.HandleFunc("POST /api/virt/install", s.auth(s.virtInstall))
|
||||
m.HandleFunc("GET /api/virt/images/remote", s.auth(s.virtRemoteImages))
|
||||
m.HandleFunc("POST /api/virt/images/download", s.auth(s.virtImageDownload))
|
||||
m.HandleFunc("POST /api/virt/images/import", s.auth(s.virtImageImport))
|
||||
m.HandleFunc("POST /api/virt/images/publish", s.auth(s.virtImagePublish))
|
||||
m.HandleFunc("POST /api/virt/images/delete", s.auth(s.virtImageDelete))
|
||||
m.HandleFunc("POST /api/virt/instances", s.auth(s.virtCreate))
|
||||
m.HandleFunc("GET /api/virt/instances/{name}", s.auth(s.virtInstance))
|
||||
m.HandleFunc("POST /api/virt/instances/{name}/rename", s.auth(s.virtRename))
|
||||
m.HandleFunc("PUT /api/virt/instances/{name}/config", s.auth(s.virtConfig))
|
||||
m.HandleFunc("POST /api/virt/instances/{name}/snapshots", s.auth(s.virtSnapshotCreate))
|
||||
m.HandleFunc("POST /api/virt/instances/{name}/snapshots/{snap}/{action}", s.auth(s.virtSnapshotAction))
|
||||
m.HandleFunc("POST /api/virt/instances/{name}/{action}", s.auth(s.virtAction))
|
||||
m.HandleFunc("GET /api/alerts", s.auth(s.alertsGet))
|
||||
m.HandleFunc("PUT /api/alerts", s.auth(s.alertsPut))
|
||||
m.HandleFunc("POST /api/alerts/test", s.auth(s.alertsTest))
|
||||
|
||||
Reference in New Issue
Block a user