mirror of
https://github.com/juanfont/headscale.git
synced 2025-09-25 17:51:11 +02:00
db: add back last_seen to the database
Fixes #2574 Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com>
This commit is contained in:
parent
56db4ed0f1
commit
109e412692
@ -27,14 +27,14 @@ func newHeadscaleServerWithConfig() (*hscontrol.Headscale, error) {
|
|||||||
cfg, err := types.LoadServerConfig()
|
cfg, err := types.LoadServerConfig()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf(
|
return nil, fmt.Errorf(
|
||||||
"failed to load configuration while creating headscale instance: %w",
|
"loading configuration: %w",
|
||||||
err,
|
err,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
app, err := hscontrol.NewHeadscale(cfg)
|
app, err := hscontrol.NewHeadscale(cfg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, fmt.Errorf("creating new headscale: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return app, nil
|
return app, nil
|
||||||
|
@ -145,7 +145,7 @@ func NewHeadscale(cfg *types.Config) (*Headscale, error) {
|
|||||||
registrationCache,
|
registrationCache,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, fmt.Errorf("new database: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
app.ipAlloc, err = db.NewIPAllocator(app.db, cfg.PrefixV4, cfg.PrefixV6, cfg.IPAllocation)
|
app.ipAlloc, err = db.NewIPAllocator(app.db, cfg.PrefixV4, cfg.PrefixV6, cfg.IPAllocation)
|
||||||
@ -160,7 +160,7 @@ func NewHeadscale(cfg *types.Config) (*Headscale, error) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
if err = app.loadPolicyManager(); err != nil {
|
if err = app.loadPolicyManager(); err != nil {
|
||||||
return nil, fmt.Errorf("failed to load ACL policy: %w", err)
|
return nil, fmt.Errorf("loading ACL policy: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
var authProvider AuthProvider
|
var authProvider AuthProvider
|
||||||
|
@ -672,7 +672,24 @@ AND auth_key_id NOT IN (
|
|||||||
{
|
{
|
||||||
ID: "202502171819",
|
ID: "202502171819",
|
||||||
Migrate: func(tx *gorm.DB) error {
|
Migrate: func(tx *gorm.DB) error {
|
||||||
_ = tx.Migrator().DropColumn(&types.Node{}, "last_seen")
|
// This migration originally removed the last_seen column
|
||||||
|
// from the node table, but it was added back in
|
||||||
|
// 202505091439.
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
Rollback: func(db *gorm.DB) error { return nil },
|
||||||
|
},
|
||||||
|
// Add back last_seen column to node table.
|
||||||
|
{
|
||||||
|
ID: "202505091439",
|
||||||
|
Migrate: func(tx *gorm.DB) error {
|
||||||
|
// Add back last_seen column to node table if it does not exist.
|
||||||
|
// This is a workaround for the fact that the last_seen column
|
||||||
|
// was removed in the 202502171819 migration, but only for some
|
||||||
|
// beta testers.
|
||||||
|
if !tx.Migrator().HasColumn(&types.Node{}, "last_seen") {
|
||||||
|
_ = tx.Migrator().AddColumn(&types.Node{}, "last_seen")
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
|
@ -251,6 +251,20 @@ func SetApprovedRoutes(
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetLastSeen sets a node's last seen field indicating that we
|
||||||
|
// have recently communicating with this node.
|
||||||
|
func (hsdb *HSDatabase) SetLastSeen(nodeID types.NodeID, lastSeen time.Time) error {
|
||||||
|
return hsdb.Write(func(tx *gorm.DB) error {
|
||||||
|
return SetLastSeen(tx, nodeID, lastSeen)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetLastSeen sets a node's last seen field indicating that we
|
||||||
|
// have recently communicating with this node.
|
||||||
|
func SetLastSeen(tx *gorm.DB, nodeID types.NodeID, lastSeen time.Time) error {
|
||||||
|
return tx.Model(&types.Node{}).Where("id = ?", nodeID).Update("last_seen", lastSeen).Error
|
||||||
|
}
|
||||||
|
|
||||||
// RenameNode takes a Node struct and a new GivenName for the nodes
|
// RenameNode takes a Node struct and a new GivenName for the nodes
|
||||||
// and renames it. If the name is not unique, it will return an error.
|
// and renames it. If the name is not unique, it will return an error.
|
||||||
func RenameNode(tx *gorm.DB,
|
func RenameNode(tx *gorm.DB,
|
||||||
|
@ -409,6 +409,10 @@ func (h *Headscale) updateNodeOnlineStatus(online bool, node *types.Node) {
|
|||||||
change.LastSeen = &now
|
change.LastSeen = &now
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if node.LastSeen != nil {
|
||||||
|
h.db.SetLastSeen(node.ID, *node.LastSeen)
|
||||||
|
}
|
||||||
|
|
||||||
ctx := types.NotifyCtx(context.Background(), "poll-nodeupdate-onlinestatus", node.Hostname)
|
ctx := types.NotifyCtx(context.Background(), "poll-nodeupdate-onlinestatus", node.Hostname)
|
||||||
h.nodeNotifier.NotifyWithIgnore(ctx, types.UpdatePeerPatch(change), node.ID)
|
h.nodeNotifier.NotifyWithIgnore(ctx, types.UpdatePeerPatch(change), node.ID)
|
||||||
}
|
}
|
||||||
|
@ -98,11 +98,7 @@ type Node struct {
|
|||||||
|
|
||||||
// LastSeen is when the node was last in contact with
|
// LastSeen is when the node was last in contact with
|
||||||
// headscale. It is best effort and not persisted.
|
// headscale. It is best effort and not persisted.
|
||||||
LastSeen *time.Time `gorm:"-"`
|
LastSeen *time.Time `gorm:"column:last_seen"`
|
||||||
|
|
||||||
// DEPRECATED: Use the ApprovedRoutes field instead.
|
|
||||||
// TODO(kradalby): remove when ApprovedRoutes is used all over the code.
|
|
||||||
// Routes []Route `gorm:"constraint:OnDelete:CASCADE;"`
|
|
||||||
|
|
||||||
// ApprovedRoutes is a list of routes that the node is allowed to announce
|
// ApprovedRoutes is a list of routes that the node is allowed to announce
|
||||||
// as a subnet router. They are not necessarily the routes that the node
|
// as a subnet router. They are not necessarily the routes that the node
|
||||||
|
Loading…
Reference in New Issue
Block a user