sdwan: add hub node selection and auto fallback to mesh
This commit is contained in:
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user