sdwan: add hub node selection and auto fallback to mesh

This commit is contained in:
2026-03-05 22:03:26 +08:00
parent 5fe5c76375
commit e96a2e5dd9
5 changed files with 60 additions and 5 deletions

View File

@@ -1,6 +1,7 @@
package server
import (
"errors"
"log"
"net/netip"
@@ -24,6 +25,15 @@ func (s *Server) SetSDWAN(cfg protocol.SDWANConfig) error {
}
func (s *Server) SetSDWANTenant(tenantID int64, cfg protocol.SDWANConfig) error {
if cfg.Mode == "hub" {
if cfg.HubNode == "" {
return errors.New("hub mode requires hubNode")
}
hub := s.GetNode(cfg.HubNode)
if hub == nil || !hub.IsOnline() || hub.TenantID != tenantID || !hub.RelayEnabled {
return errors.New("hub node must be online and relay-enabled")
}
}
if err := s.sdwan.saveTenant(tenantID, cfg); err != nil {
return err
}

View File

@@ -10,8 +10,8 @@ import (
"time"
"github.com/gorilla/websocket"
"github.com/openp2p-cn/inp2p/pkg/auth"
"github.com/openp2p-cn/inp2p/internal/store"
"github.com/openp2p-cn/inp2p/pkg/auth"
"github.com/openp2p-cn/inp2p/pkg/config"
"github.com/openp2p-cn/inp2p/pkg/protocol"
"github.com/openp2p-cn/inp2p/pkg/signal"
@@ -77,6 +77,15 @@ func New(cfg config.ServerConfig) *Server {
st, err := store.Open(cfg.DBPath)
if err != nil {
log.Printf("[server] open store failed: %v", err)
} else {
// bootstrap default admin/admin in tenant 1
if _, gErr := st.GetTenantByID(1); gErr != nil {
if _, _, _, cErr := st.CreateTenantWithUsers("default", "admin", "admin"); cErr != nil {
log.Printf("[server] bootstrap default tenant failed: %v", cErr)
} else {
log.Printf("[server] bootstrap default tenant created (tenant=1, admin/admin)")
}
}
}
return &Server{
cfg: cfg,
@@ -86,7 +95,7 @@ func New(cfg config.ServerConfig) *Server {
store: st,
tokens: tokens,
upgrader: websocket.Upgrader{
CheckOrigin: func(r *http.Request) bool { return true },
CheckOrigin: func(r *http.Request) bool { return true },
ReadBufferSize: 4096,
WriteBufferSize: 4096,
},
@@ -550,7 +559,7 @@ func (s *Server) broadcastNodeOnline(nodeName string) {
}
}
// StartCleanup periodically removes stale nodes.
// StartCleanup periodically removes stale nodes and checks SDWAN hub health.
func (s *Server) StartCleanup() {
go func() {
ticker := time.NewTicker(30 * time.Second)
@@ -567,6 +576,32 @@ func (s *Server) StartCleanup() {
}
}
s.mu.Unlock()
// hub offline -> auto mesh (tenant configs)
if s.sdwan != nil {
sd := s.sdwan
sd.mu.RLock()
m := make(map[int64]protocol.SDWANConfig, len(sd.multi))
for k, v := range sd.multi {
m[k] = v
}
sd.mu.RUnlock()
for tid, cfg := range m {
if cfg.Mode != "hub" || cfg.HubNode == "" {
continue
}
hub := s.GetNode(cfg.HubNode)
if hub != nil && hub.IsOnline() && hub.TenantID == tid {
continue
}
// auto fallback to mesh
cfg.Mode = "mesh"
cfg.HubNode = ""
_ = s.sdwan.saveTenant(tid, cfg)
s.broadcastSDWANTenant(tid, cfg)
log.Printf("[sdwan] hub offline, auto fallback to mesh (tenant=%d)", tid)
}
}
case <-s.quit:
return
}