feat(inventory): record when a reboot became required
This commit is contained in:
@@ -7,6 +7,7 @@ import (
|
||||
"gitea.hostxtra.co.uk/mrhid6/vantage/server/internal/db"
|
||||
"gitea.hostxtra.co.uk/vantage/vantage-shared/grpc/pb"
|
||||
"go.mongodb.org/mongo-driver/v2/bson"
|
||||
"go.mongodb.org/mongo-driver/v2/mongo/options"
|
||||
)
|
||||
|
||||
func StoreInventory(serverID string, r *pb.InventoryReport) error {
|
||||
@@ -29,6 +30,7 @@ func StoreInventory(serverID string, r *pb.InventoryReport) error {
|
||||
set["inventory.boot_time"] = time.Unix(r.BootTimeUnix, 0).UTC()
|
||||
}
|
||||
|
||||
var unset bson.M
|
||||
if r.IncludeStatic {
|
||||
set["inventory.static_at"] = now
|
||||
set["inventory.swap_total_bytes"] = r.SwapTotal
|
||||
@@ -49,8 +51,39 @@ func StoreInventory(serverID string, r *pb.InventoryReport) error {
|
||||
})
|
||||
}
|
||||
set["inventory.partitions"] = parts
|
||||
|
||||
var prev struct {
|
||||
Inventory struct {
|
||||
RebootRequired bool `bson:"reboot_required"`
|
||||
RebootRequiredSince *time.Time `bson:"reboot_required_since"`
|
||||
} `bson:"inventory"`
|
||||
}
|
||||
_ = db.Col("servers").FindOne(ctx, bson.M{"server_id": serverID},
|
||||
options.FindOne().SetProjection(bson.M{"inventory.reboot_required": 1, "inventory.reboot_required_since": 1})).Decode(&prev)
|
||||
if since, clear := rebootSinceUpdate(prev.Inventory.RebootRequired, prev.Inventory.RebootRequiredSince, r.RebootRequired, now); since != nil {
|
||||
set["inventory.reboot_required_since"] = *since
|
||||
} else if clear {
|
||||
unset = bson.M{"inventory.reboot_required_since": ""}
|
||||
}
|
||||
}
|
||||
|
||||
_, err := db.Col("servers").UpdateOne(ctx, bson.M{"server_id": serverID}, bson.M{"$set": set})
|
||||
upd := bson.M{"$set": set}
|
||||
if unset != nil {
|
||||
upd["$unset"] = unset
|
||||
}
|
||||
_, err := db.Col("servers").UpdateOne(ctx, bson.M{"server_id": serverID}, upd)
|
||||
return err
|
||||
}
|
||||
|
||||
// rebootSinceUpdate decides how reboot_required_since changes. The stamp is
|
||||
// kept from the first report that needed a reboot, so "pending for 7 days"
|
||||
// means seven days, not seven days since the last static report.
|
||||
func rebootSinceUpdate(prevRequired bool, prevSince *time.Time, nowRequired bool, now time.Time) (*time.Time, bool) {
|
||||
if !nowRequired {
|
||||
return nil, prevSince != nil || prevRequired
|
||||
}
|
||||
if prevSince == nil {
|
||||
return &now, false
|
||||
}
|
||||
return nil, false
|
||||
}
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
package services
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestRebootSinceUpdate(t *testing.T) {
|
||||
now := time.Date(2026, 9, 17, 0, 0, 0, 0, time.UTC)
|
||||
earlier := now.Add(-72 * time.Hour)
|
||||
|
||||
if set, unset := rebootSinceUpdate(false, nil, true, now); set == nil || !set.Equal(now) || unset {
|
||||
t.Fatal("turning on must stamp now")
|
||||
}
|
||||
if set, unset := rebootSinceUpdate(true, &earlier, true, now); set != nil || unset {
|
||||
t.Fatal("staying on must keep the original stamp")
|
||||
}
|
||||
if set, _ := rebootSinceUpdate(true, nil, true, now); set == nil {
|
||||
t.Fatal("on with no stamp (pre-upgrade data) must stamp now")
|
||||
}
|
||||
if set, unset := rebootSinceUpdate(true, &earlier, false, now); set != nil || !unset {
|
||||
t.Fatal("turning off must clear the stamp")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user