Virtualization phase 2: ISOs, New VM from ISO, the VGA console in the browser, nightly exports, mounts, instance sensors
- Library: an ISO shelf in virt/isos: upload (the Files uploader), fetch by URL with an optional sha256, import a file from the machine by copying it in, rename, delete (refused while attached), attach to a VM as a CD-ROM live or stopped with boot-first, eject, and New VM from ISO: an empty VM with the ISO as first boot device, Secure Boot on or off. - The VGA console: Ham Lab asks Incus for the VM's SPICE console over its unix socket and bridges the display websocket to the browser, where spice-html5 (vendored from upstream b372aab, LGPL, loaded on demand) draws it; Ctrl+Alt+Del, fit-to-window. - Exports: every instance as a tarball in virt/exports/<name>/, kept to a count, as a cron line in /etc/cron.d/hamlab-virt calling hamlab virt-export, settings and the last run as files beside the data; Export now per instance or for all. - Disks tab per instance: the root disk, attached ISOs with Eject, bind mounts in and out (shift for containers, virtiofs for VMs). - instance.* sensors (running, down, state, cpu, mem) and the VM-or-container-down alert default, offered once to installs seeded before it existed. - cloud-init: Use my SSH keys writes a cloud-config from the account's public keys. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5.1
parent
66498a58c5
commit
43ebacdd92
@@ -71,6 +71,9 @@ type alertSaved struct {
|
||||
Channels []AlertChannel `json:"channels"`
|
||||
Events []AlertEvent `json:"events"`
|
||||
Seeded bool `json:"seeded"`
|
||||
// SawInstanceRule marks that the instance-down default has been offered once; set so that
|
||||
// removing it stays removed.
|
||||
SawInstanceRule bool `json:"saw_instance_rule,omitempty"`
|
||||
// Firing is what was firing when the hub last looked, so a restart (every deploy is one)
|
||||
// carries on where it was and doesn't announce the same alerts all over again.
|
||||
Firing map[string]alertKept `json:"firing,omitempty"`
|
||||
@@ -102,6 +105,7 @@ var defaultRules = []AlertRule{
|
||||
{ID: "machine-offline", Name: "Machine not answering", Sensor: "hamlab.reachable", Op: "==", Value: false, ForSec: 120, Severity: "crit", Enabled: true},
|
||||
{ID: "container-down", Name: "Container down", Sensor: "container.*.down", Op: "==", Value: true, ForSec: 120, Severity: "crit", Enabled: true},
|
||||
{ID: "container-unhealthy", Name: "Container unhealthy", Sensor: "container.*.health", Op: "==", Value: "unhealthy", ForSec: 180, Severity: "warn", Enabled: true},
|
||||
{ID: "instance-down", Name: "VM or container down", Sensor: "instance.*.down", Op: "==", Value: true, ForSec: 120, Severity: "crit", Enabled: true},
|
||||
{ID: "service-failed", Name: "A service has failed", Sensor: "services.failed", Op: ">", Value: 0.0, ForSec: 300, Severity: "warn", Enabled: true},
|
||||
{ID: "disk-full", Name: "Filesystem nearly full", Sensor: "fs.*.used_pct", Op: ">=", Value: 90.0, ForSec: 300, Severity: "warn", Enabled: true},
|
||||
{ID: "pool-unhealthy", Name: "ZFS pool not healthy", Sensor: "zfs.*.healthy", Op: "==", Value: false, ForSec: 60, Severity: "crit", Enabled: true},
|
||||
@@ -122,6 +126,23 @@ func newAlertEngine(s *Server) *alertEngine {
|
||||
for key, k := range e.saved.Firing {
|
||||
e.state[key] = &alertState{pending: time.UnixMilli(k.Since), firing: true, since: time.UnixMilli(k.Since), value: k.Value}
|
||||
}
|
||||
// a default added after an install was seeded joins its rules once; removing it afterwards sticks
|
||||
if e.saved.Seeded && !e.saved.SawInstanceRule {
|
||||
has := false
|
||||
for _, r := range e.saved.Rules {
|
||||
if r.ID == "instance-down" {
|
||||
has = true
|
||||
}
|
||||
}
|
||||
if !has {
|
||||
for _, d := range defaultRules {
|
||||
if d.ID == "instance-down" {
|
||||
e.saved.Rules = append(e.saved.Rules, d)
|
||||
}
|
||||
}
|
||||
}
|
||||
e.saved.SawInstanceRule = true
|
||||
}
|
||||
for i, r := range e.saved.Rules { // the first day's default watched "not running", which a container stopped on purpose also is
|
||||
if r.ID == "container-down" && r.Sensor == "container.*.running" {
|
||||
e.saved.Rules[i].Name, e.saved.Rules[i].Sensor, e.saved.Rules[i].Value = "Container down", "container.*.down", true
|
||||
|
||||
Reference in New Issue
Block a user