mirror of
https://github.com/datarhei/core.git
synced 2025-10-05 16:07:07 +08:00
Get peer config via cluster API
This commit is contained in:
@@ -721,7 +721,7 @@ func (c *cluster) checkClusterNodes() error {
|
|||||||
return fmt.Errorf("node %s has a different version: %s: %w", id, version, err)
|
return fmt.Errorf("node %s has a different version: %s: %w", id, version, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
config, err := node.Config()
|
config, err := node.CoreConfig()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("node %s has no configuration available: %w", id, err)
|
return fmt.Errorf("node %s has no configuration available: %w", id, err)
|
||||||
}
|
}
|
||||||
@@ -783,6 +783,14 @@ func verifyClusterConfig(local, remote *config.Config) error {
|
|||||||
return fmt.Errorf("srt.passphrase is different")
|
return fmt.Errorf("srt.passphrase is different")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if local.Resources.MaxCPUUsage == 0 || remote.Resources.MaxCPUUsage == 0 {
|
||||||
|
return fmt.Errorf("resources.max_cpu_usage must be defined")
|
||||||
|
}
|
||||||
|
|
||||||
|
if local.Resources.MaxMemoryUsage == 0 || remote.Resources.MaxMemoryUsage == 0 {
|
||||||
|
return fmt.Errorf("resources.max_memory_usage must be defined")
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
100
cluster/node.go
100
cluster/node.go
@@ -10,7 +10,6 @@ import (
|
|||||||
"github.com/datarhei/core/v16/cluster/client"
|
"github.com/datarhei/core/v16/cluster/client"
|
||||||
"github.com/datarhei/core/v16/cluster/proxy"
|
"github.com/datarhei/core/v16/cluster/proxy"
|
||||||
"github.com/datarhei/core/v16/config"
|
"github.com/datarhei/core/v16/config"
|
||||||
"github.com/datarhei/core/v16/config/copy"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type clusterNode struct {
|
type clusterNode struct {
|
||||||
@@ -45,13 +44,10 @@ func NewClusterNode(id, address string) *clusterNode {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
version, err := n.client.Version()
|
if version, err := n.client.Version(); err == nil {
|
||||||
if err != nil {
|
n.version = version
|
||||||
version = "0.0.0"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
n.version = version
|
|
||||||
|
|
||||||
n.start(id)
|
n.start(id)
|
||||||
|
|
||||||
return n
|
return n
|
||||||
@@ -74,8 +70,8 @@ func (n *clusterNode) start(id string) error {
|
|||||||
n.lastCoreContactErr = fmt.Errorf("not started yet")
|
n.lastCoreContactErr = fmt.Errorf("not started yet")
|
||||||
n.lastContactErr = fmt.Errorf("not started yet")
|
n.lastContactErr = fmt.Errorf("not started yet")
|
||||||
|
|
||||||
address, err := n.CoreAPIAddress()
|
address, config, err := n.CoreEssentials()
|
||||||
n.proxyNode = proxy.NewNode(id, address)
|
n.proxyNode = proxy.NewNode(id, address, config)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
n.lastCoreContactErr = err
|
n.lastCoreContactErr = err
|
||||||
@@ -86,10 +82,10 @@ func (n *clusterNode) start(id string) error {
|
|||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case <-ticker.C:
|
case <-ticker.C:
|
||||||
address, err := n.CoreAPIAddress()
|
address, config, err := n.CoreEssentials()
|
||||||
n.pingLock.Lock()
|
n.pingLock.Lock()
|
||||||
if err == nil {
|
if err == nil {
|
||||||
n.proxyNode.SetAddress(address)
|
n.proxyNode.SetEssentials(address, config)
|
||||||
n.lastCoreContactErr = nil
|
n.lastCoreContactErr = nil
|
||||||
} else {
|
} else {
|
||||||
n.lastCoreContactErr = err
|
n.lastCoreContactErr = err
|
||||||
@@ -156,84 +152,22 @@ func (n *clusterNode) LastContact() time.Time {
|
|||||||
return n.lastContact
|
return n.lastContact
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *clusterNode) Config() (*config.Config, error) {
|
func (n *clusterNode) CoreEssentials() (string, *config.Config, error) {
|
||||||
if n.proxyNode == nil {
|
address, err := n.CoreAPIAddress()
|
||||||
return nil, fmt.Errorf("proxy not available")
|
if err != nil {
|
||||||
|
return "", nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
apiconfig := n.proxyNode.Config()
|
config, err := n.CoreConfig()
|
||||||
if apiconfig == nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("no config stored")
|
return "", nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
config := config.New(nil)
|
return address, config, nil
|
||||||
|
}
|
||||||
|
|
||||||
config.Version = apiconfig.Version
|
func (n *clusterNode) CoreConfig() (*config.Config, error) {
|
||||||
config.Version = apiconfig.Version
|
return n.client.CoreConfig()
|
||||||
config.Version = apiconfig.Version
|
|
||||||
config.ID = apiconfig.ID
|
|
||||||
config.Name = apiconfig.Name
|
|
||||||
config.Address = apiconfig.Address
|
|
||||||
config.CheckForUpdates = apiconfig.CheckForUpdates
|
|
||||||
|
|
||||||
config.Log = apiconfig.Log
|
|
||||||
config.DB = apiconfig.DB
|
|
||||||
config.Host = apiconfig.Host
|
|
||||||
config.API.ReadOnly = apiconfig.API.ReadOnly
|
|
||||||
config.API.Access = apiconfig.API.Access
|
|
||||||
config.API.Auth.Enable = apiconfig.API.Auth.Enable
|
|
||||||
config.API.Auth.DisableLocalhost = apiconfig.API.Auth.DisableLocalhost
|
|
||||||
config.API.Auth.Username = apiconfig.API.Auth.Username
|
|
||||||
config.API.Auth.Password = apiconfig.API.Auth.Password
|
|
||||||
config.API.Auth.JWT = apiconfig.API.Auth.JWT
|
|
||||||
config.TLS = apiconfig.TLS
|
|
||||||
config.Storage.MimeTypes = apiconfig.Storage.MimeTypes
|
|
||||||
config.Storage.Disk = apiconfig.Storage.Disk
|
|
||||||
config.Storage.Memory = apiconfig.Storage.Memory
|
|
||||||
config.Storage.CORS = apiconfig.Storage.CORS
|
|
||||||
config.RTMP = apiconfig.RTMP
|
|
||||||
config.SRT = apiconfig.SRT
|
|
||||||
config.FFmpeg = apiconfig.FFmpeg
|
|
||||||
config.Playout = apiconfig.Playout
|
|
||||||
config.Debug = apiconfig.Debug
|
|
||||||
config.Metrics = apiconfig.Metrics
|
|
||||||
config.Sessions = apiconfig.Sessions
|
|
||||||
config.Service = apiconfig.Service
|
|
||||||
config.Router = apiconfig.Router
|
|
||||||
config.Resources = apiconfig.Resources
|
|
||||||
config.Cluster = apiconfig.Cluster
|
|
||||||
|
|
||||||
config.Log.Topics = copy.Slice(apiconfig.Log.Topics)
|
|
||||||
|
|
||||||
config.Host.Name = copy.Slice(apiconfig.Host.Name)
|
|
||||||
|
|
||||||
config.API.Access.HTTP.Allow = copy.Slice(apiconfig.API.Access.HTTP.Allow)
|
|
||||||
config.API.Access.HTTP.Block = copy.Slice(apiconfig.API.Access.HTTP.Block)
|
|
||||||
config.API.Access.HTTPS.Allow = copy.Slice(apiconfig.API.Access.HTTPS.Allow)
|
|
||||||
config.API.Access.HTTPS.Block = copy.Slice(apiconfig.API.Access.HTTPS.Block)
|
|
||||||
|
|
||||||
//config.API.Auth.Auth0.Tenants = copy.TenantSlice(d.API.Auth.Auth0.Tenants)
|
|
||||||
|
|
||||||
config.Storage.CORS.Origins = copy.Slice(apiconfig.Storage.CORS.Origins)
|
|
||||||
config.Storage.Disk.Cache.Types.Allow = copy.Slice(apiconfig.Storage.Disk.Cache.Types.Allow)
|
|
||||||
config.Storage.Disk.Cache.Types.Block = copy.Slice(apiconfig.Storage.Disk.Cache.Types.Block)
|
|
||||||
//config.Storage.S3 = copy.Slice(d.Storage.S3)
|
|
||||||
|
|
||||||
config.FFmpeg.Access.Input.Allow = copy.Slice(apiconfig.FFmpeg.Access.Input.Allow)
|
|
||||||
config.FFmpeg.Access.Input.Block = copy.Slice(apiconfig.FFmpeg.Access.Input.Block)
|
|
||||||
config.FFmpeg.Access.Output.Allow = copy.Slice(apiconfig.FFmpeg.Access.Output.Allow)
|
|
||||||
config.FFmpeg.Access.Output.Block = copy.Slice(apiconfig.FFmpeg.Access.Output.Block)
|
|
||||||
|
|
||||||
config.Sessions.IPIgnoreList = copy.Slice(apiconfig.Sessions.IPIgnoreList)
|
|
||||||
|
|
||||||
config.SRT.Log.Topics = copy.Slice(apiconfig.SRT.Log.Topics)
|
|
||||||
|
|
||||||
config.Router.BlockedPrefixes = copy.Slice(apiconfig.Router.BlockedPrefixes)
|
|
||||||
config.Router.Routes = copy.StringMap(apiconfig.Router.Routes)
|
|
||||||
|
|
||||||
config.Cluster.Peers = copy.Slice(apiconfig.Cluster.Peers)
|
|
||||||
|
|
||||||
return config, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *clusterNode) CoreAPIAddress() (string, error) {
|
func (n *clusterNode) CoreAPIAddress() (string, error) {
|
||||||
|
@@ -12,6 +12,7 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/datarhei/core/v16/config"
|
||||||
"github.com/datarhei/core/v16/restream/app"
|
"github.com/datarhei/core/v16/restream/app"
|
||||||
|
|
||||||
client "github.com/datarhei/core-client-go/v16"
|
client "github.com/datarhei/core-client-go/v16"
|
||||||
@@ -19,11 +20,11 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type Node interface {
|
type Node interface {
|
||||||
SetAddress(address string)
|
SetEssentials(address string, config *config.Config)
|
||||||
IsConnected() (bool, error)
|
IsConnected() (bool, error)
|
||||||
Disconnect()
|
Disconnect()
|
||||||
|
|
||||||
Config() *clientapi.ConfigV3
|
Config() *config.Config
|
||||||
|
|
||||||
StartFiles(updates chan<- NodeFiles) error
|
StartFiles(updates chan<- NodeFiles) error
|
||||||
StopFiles()
|
StopFiles()
|
||||||
@@ -124,7 +125,7 @@ type node struct {
|
|||||||
memLimit uint64
|
memLimit uint64
|
||||||
}
|
}
|
||||||
|
|
||||||
config *clientapi.ConfigV3
|
config *config.Config
|
||||||
|
|
||||||
state nodeState
|
state nodeState
|
||||||
latency float64 // Seconds
|
latency float64 // Seconds
|
||||||
@@ -145,10 +146,11 @@ type node struct {
|
|||||||
srtAddress *url.URL
|
srtAddress *url.URL
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewNode(id, address string) Node {
|
func NewNode(id, address string, config *config.Config) Node {
|
||||||
n := &node{
|
n := &node{
|
||||||
id: id,
|
id: id,
|
||||||
address: address,
|
address: address,
|
||||||
|
config: config,
|
||||||
state: stateDisconnected,
|
state: stateDisconnected,
|
||||||
secure: strings.HasPrefix(address, "https://"),
|
secure: strings.HasPrefix(address, "https://"),
|
||||||
}
|
}
|
||||||
@@ -191,11 +193,12 @@ func NewNode(id, address string) Node {
|
|||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *node) SetAddress(address string) {
|
func (n *node) SetEssentials(address string, config *config.Config) {
|
||||||
n.peerLock.Lock()
|
n.peerLock.Lock()
|
||||||
defer n.peerLock.Unlock()
|
defer n.peerLock.Unlock()
|
||||||
|
|
||||||
n.address = address
|
n.address = address
|
||||||
|
n.config = config
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *node) connect(ctx context.Context) error {
|
func (n *node) connect(ctx context.Context) error {
|
||||||
@@ -210,6 +213,10 @@ func (n *node) connect(ctx context.Context) error {
|
|||||||
return fmt.Errorf("no address provided")
|
return fmt.Errorf("no address provided")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if n.config == nil {
|
||||||
|
return fmt.Errorf("config not available")
|
||||||
|
}
|
||||||
|
|
||||||
u, err := url.Parse(n.address)
|
u, err := url.Parse(n.address)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("invalid address (%s): %w", n.address, err)
|
return fmt.Errorf("invalid address (%s): %w", n.address, err)
|
||||||
@@ -235,34 +242,18 @@ func (n *node) connect(ctx context.Context) error {
|
|||||||
return fmt.Errorf("creating client failed (%s): %w", n.address, err)
|
return fmt.Errorf("creating client failed (%s): %w", n.address, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
version, cfg, err := peer.Config()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if version != 3 {
|
|
||||||
return fmt.Errorf("unsupported core config version: %d", version)
|
|
||||||
}
|
|
||||||
|
|
||||||
config, ok := cfg.Config.(clientapi.ConfigV3)
|
|
||||||
if !ok {
|
|
||||||
return fmt.Errorf("failed to convert config to expected version")
|
|
||||||
}
|
|
||||||
|
|
||||||
n.config = &config
|
|
||||||
|
|
||||||
n.httpAddress = u
|
n.httpAddress = u
|
||||||
|
|
||||||
if config.RTMP.Enable {
|
if n.config.RTMP.Enable {
|
||||||
n.hasRTMP = true
|
n.hasRTMP = true
|
||||||
n.rtmpAddress = &url.URL{}
|
n.rtmpAddress = &url.URL{}
|
||||||
n.rtmpAddress.Scheme = "rtmp"
|
n.rtmpAddress.Scheme = "rtmp"
|
||||||
|
|
||||||
isHostIP := net.ParseIP(nodehost) != nil
|
isHostIP := net.ParseIP(nodehost) != nil
|
||||||
|
|
||||||
address := config.RTMP.Address
|
address := n.config.RTMP.Address
|
||||||
if n.secure && config.RTMP.EnableTLS && !isHostIP {
|
if n.secure && n.config.RTMP.EnableTLS && !isHostIP {
|
||||||
address = config.RTMP.AddressTLS
|
address = n.config.RTMP.AddressTLS
|
||||||
n.rtmpAddress.Scheme = "rtmps"
|
n.rtmpAddress.Scheme = "rtmps"
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -277,17 +268,17 @@ func (n *node) connect(ctx context.Context) error {
|
|||||||
n.rtmpAddress.Host = net.JoinHostPort(host, port)
|
n.rtmpAddress.Host = net.JoinHostPort(host, port)
|
||||||
}
|
}
|
||||||
|
|
||||||
n.rtmpAddress = n.rtmpAddress.JoinPath(config.RTMP.App)
|
n.rtmpAddress = n.rtmpAddress.JoinPath(n.config.RTMP.App)
|
||||||
}
|
}
|
||||||
|
|
||||||
if config.SRT.Enable {
|
if n.config.SRT.Enable {
|
||||||
n.hasSRT = true
|
n.hasSRT = true
|
||||||
n.srtAddress = &url.URL{}
|
n.srtAddress = &url.URL{}
|
||||||
n.srtAddress.Scheme = "srt"
|
n.srtAddress.Scheme = "srt"
|
||||||
|
|
||||||
host, port, err := net.SplitHostPort(config.SRT.Address)
|
host, port, err := net.SplitHostPort(n.config.SRT.Address)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("invalid srt address '%s': %w", config.SRT.Address, err)
|
return fmt.Errorf("invalid srt address '%s': %w", n.config.SRT.Address, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(host) == 0 {
|
if len(host) == 0 {
|
||||||
@@ -299,8 +290,8 @@ func (n *node) connect(ctx context.Context) error {
|
|||||||
v := url.Values{}
|
v := url.Values{}
|
||||||
|
|
||||||
v.Set("mode", "caller")
|
v.Set("mode", "caller")
|
||||||
if len(config.SRT.Passphrase) != 0 {
|
if len(n.config.SRT.Passphrase) != 0 {
|
||||||
v.Set("passphrase", config.SRT.Passphrase)
|
v.Set("passphrase", n.config.SRT.Passphrase)
|
||||||
}
|
}
|
||||||
|
|
||||||
n.srtAddress.RawQuery = v.Encode()
|
n.srtAddress.RawQuery = v.Encode()
|
||||||
@@ -467,7 +458,10 @@ func (n *node) updateResources(ctx context.Context, wg *sync.WaitGroup) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *node) Config() *clientapi.ConfigV3 {
|
func (n *node) Config() *config.Config {
|
||||||
|
n.peerLock.RLock()
|
||||||
|
defer n.peerLock.RUnlock()
|
||||||
|
|
||||||
return n.config
|
return n.config
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user