Add structured node config with names/macs/ips and avoid flag
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,21 +1,27 @@
|
||||
locations:
|
||||
stage:
|
||||
- name: Stage
|
||||
children:
|
||||
upstage:
|
||||
- name: Upstage
|
||||
nodes:
|
||||
- lighting-1
|
||||
downstage:
|
||||
- names: ["lighting-1"]
|
||||
- name: Downstage
|
||||
nodes:
|
||||
- lighting-2
|
||||
house:
|
||||
- names: ["lighting-2"]
|
||||
|
||||
- name: House
|
||||
children:
|
||||
house_left:
|
||||
- name: House Left
|
||||
nodes:
|
||||
- audio
|
||||
house_right:
|
||||
- names: ["audio"]
|
||||
- name: House Right
|
||||
nodes:
|
||||
- video
|
||||
booth:
|
||||
- names: ["video"]
|
||||
- name: Booth
|
||||
nodes:
|
||||
- qlab
|
||||
- satellite-1
|
||||
- names: ["qlab"]
|
||||
- names: ["satellite-1"]
|
||||
# Example with MAC and avoid flag:
|
||||
# - names: ["problem-device"]
|
||||
# macs: ["00:11:22:33:44:55"]
|
||||
# ips: ["10.0.1.100"]
|
||||
# avoid: true
|
||||
|
||||
22
config.go
22
config.go
@@ -14,10 +14,17 @@ type Config struct {
|
||||
type Location struct {
|
||||
Name string `yaml:"name" json:"name"`
|
||||
Direction string `yaml:"direction,omitempty" json:"direction,omitempty"`
|
||||
Nodes []string `yaml:"nodes,omitempty" json:"nodes,omitempty"`
|
||||
Nodes []*NodeConfig `yaml:"nodes,omitempty" json:"nodes,omitempty"`
|
||||
Children []*Location `yaml:"children,omitempty" json:"children,omitempty"`
|
||||
}
|
||||
|
||||
type NodeConfig struct {
|
||||
Names []string `yaml:"names,omitempty" json:"names,omitempty"`
|
||||
MACs []string `yaml:"macs,omitempty" json:"macs,omitempty"`
|
||||
IPs []string `yaml:"ips,omitempty" json:"ips,omitempty"`
|
||||
Avoid bool `yaml:"avoid,omitempty" json:"avoid,omitempty"`
|
||||
}
|
||||
|
||||
func LoadConfig(path string) (*Config, error) {
|
||||
if path == "" {
|
||||
return &Config{}, nil
|
||||
@@ -39,3 +46,16 @@ func LoadConfig(path string) (*Config, error) {
|
||||
func (c *Config) ToJSON() ([]byte, error) {
|
||||
return json.Marshal(c)
|
||||
}
|
||||
|
||||
func (c *Config) AllNodeConfigs() []*NodeConfig {
|
||||
var result []*NodeConfig
|
||||
var visit func([]*Location)
|
||||
visit = func(locs []*Location) {
|
||||
for _, loc := range locs {
|
||||
result = append(result, loc.Nodes...)
|
||||
visit(loc.Children)
|
||||
}
|
||||
}
|
||||
visit(c.Locations)
|
||||
return result
|
||||
}
|
||||
|
||||
222
config.yaml
222
config.yaml
@@ -4,168 +4,200 @@ locations:
|
||||
children:
|
||||
- name: LIGHTING-2 Rack
|
||||
nodes:
|
||||
- lighting-2
|
||||
- "48:59:00:41:00:29" # Pixie Driver 8k Port 1
|
||||
- "48:59:00:28:00:27" # Pixie Driver 8k Port 2
|
||||
- "48:59:00:43:00:29" # Pixie Driver 8k Port 3
|
||||
- "48:59:00:42:00:29" # Pixie Driver 8k Port 4
|
||||
- "48:59:00:3c:00:3e" # Pixie Driver 8k Port 5
|
||||
- "48:59:00:3f:00:3e" # Pixie Driver 8k Port 6
|
||||
- "48:59:00:25:00:3e" # Pixie Driver 8k Port 7
|
||||
- "48:59:00:41:00:3e" # Pixie Driver 8k Port 8
|
||||
- DMXG # cyc1
|
||||
- DMXH # cyc2
|
||||
- DMXI # cyc3
|
||||
- DMXJ # cyc4
|
||||
- DMXK # cyc5
|
||||
- DMXL # cyc6
|
||||
- names: ["lighting-2"]
|
||||
- names: ["Pixie Driver 8k 2 Port 1"]
|
||||
macs: ["48:59:00:41:00:29"]
|
||||
avoid: true
|
||||
- names: ["Pixie Driver 8k 2 Port 2"]
|
||||
macs: ["48:59:00:28:00:27"]
|
||||
avoid: true
|
||||
- names: ["Pixie Driver 8k 2 Port 3"]
|
||||
macs: ["48:59:00:43:00:29"]
|
||||
avoid: true
|
||||
- names: ["Pixie Driver 8k 2 Port 4"]
|
||||
macs: ["48:59:00:42:00:29"]
|
||||
avoid: true
|
||||
- names: ["Pixie Driver 8k 2 Port 5"]
|
||||
macs: ["48:59:00:3c:00:3e"]
|
||||
avoid: true
|
||||
- names: ["Pixie Driver 8k 2 Port 6"]
|
||||
macs: ["48:59:00:3f:00:3e"]
|
||||
avoid: true
|
||||
- names: ["Pixie Driver 8k 2 Port 7"]
|
||||
macs: ["48:59:00:25:00:3e"]
|
||||
avoid: true
|
||||
- names: ["Pixie Driver 8k 2 Port 8"]
|
||||
macs: ["48:59:00:41:00:3e"]
|
||||
avoid: true
|
||||
- names: ["DMXG"] # cyc1
|
||||
- names: ["DMXH"] # cyc2
|
||||
- names: ["DMXI"] # cyc3
|
||||
- names: ["DMXJ"] # cyc4
|
||||
- names: ["DMXK"] # cyc5
|
||||
- names: ["DMXL"] # cyc6
|
||||
|
||||
- direction: horizontal
|
||||
children:
|
||||
- nodes:
|
||||
- DMXQ # r2x1
|
||||
- names: ["DMXQ"] # r2x1
|
||||
|
||||
- nodes:
|
||||
- DMXR # r2x2
|
||||
- names: ["DMXR"] # r2x2
|
||||
|
||||
- direction: horizontal
|
||||
children:
|
||||
- nodes:
|
||||
- "MON1-A"
|
||||
- "MON1-B"
|
||||
- names: ["MON1-A"]
|
||||
- names: ["MON1-B"]
|
||||
|
||||
- name: Under Apron
|
||||
direction: horizontal
|
||||
children:
|
||||
- name: AUDIO Rack
|
||||
nodes:
|
||||
- audio
|
||||
- "MICS-A"
|
||||
- "00:0e:dd:a7:29:93" # MICS-A bridge interface
|
||||
- "MICS-B"
|
||||
- "00:0e:dd:a8:3e:b3" # MICS-B bridge interface
|
||||
- "MICS-C"
|
||||
- "00:0e:dd:a7:6f:55" # MICS-C bridge interface
|
||||
- "MICS-D"
|
||||
- "00:0e:dd:64:3d:51" # MICS-D bridge interface
|
||||
- "MICS-E"
|
||||
- "00:0e:dd:ac:fc:7d" # MICS-E bridge interface
|
||||
- names: ["audio"]
|
||||
- names: ["MICS-A"]
|
||||
macs: ["00:0e:dd:a7:29:93"]
|
||||
- names: ["MICS-B"]
|
||||
macs: ["00:0e:dd:a8:3e:b3"]
|
||||
- names: ["MICS-C"]
|
||||
macs: ["00:0e:dd:a7:6f:55"]
|
||||
- names: ["MICS-D"]
|
||||
macs: ["00:0e:dd:64:3d:51"]
|
||||
- names: ["MICS-E"]
|
||||
macs: ["00:0e:dd:ac:fc:7d"]
|
||||
|
||||
- name: LIGHTING-1 Rack
|
||||
nodes:
|
||||
- lighting-1
|
||||
- "48:59:00:27:00:27" # Pixie Driver 8k Port 1
|
||||
- "48:59:00:37:00:27" # Pixie Driver 8k Port 2
|
||||
- "48:59:00:3e:00:27" # Pixie Driver 8k Port 3
|
||||
- "48:59:00:3f:00:27" # Pixie Driver 8k Port 4
|
||||
- "48:59:00:47:00:1a" # Pixie Driver 8k Port 5
|
||||
- "48:59:00:44:00:1a" # Pixie Driver 8k Port 6
|
||||
- "48:59:00:42:00:19" # Pixie Driver 8k Port 7
|
||||
- "48:59:00:44:00:19" # Pixie Driver 8k Port 8
|
||||
- names: ["lighting-1"]
|
||||
- names: ["Pixie Driver 8k 1 Port 1"]
|
||||
macs: ["48:59:00:27:00:27"]
|
||||
avoid: true
|
||||
- names: ["Pixie Driver 8k 1 Port 2"]
|
||||
macs: ["48:59:00:37:00:27"]
|
||||
avoid: true
|
||||
- names: ["Pixie Driver 8k 1 Port 3"]
|
||||
macs: ["48:59:00:3e:00:27"]
|
||||
avoid: true
|
||||
- names: ["Pixie Driver 8k 1 Port 4"]
|
||||
macs: ["48:59:00:3f:00:27"]
|
||||
avoid: true
|
||||
- names: ["Pixie Driver 8k 1 Port 5"]
|
||||
macs: ["48:59:00:47:00:1a"]
|
||||
avoid: true
|
||||
- names: ["Pixie Driver 8k 1 Port 6"]
|
||||
macs: ["48:59:00:44:00:1a"]
|
||||
avoid: true
|
||||
- names: ["Pixie Driver 8k 1 Port 7"]
|
||||
macs: ["48:59:00:42:00:19"]
|
||||
avoid: true
|
||||
- names: ["Pixie Driver 8k 1 Port 8"]
|
||||
macs: ["48:59:00:44:00:19"]
|
||||
avoid: true
|
||||
|
||||
- name: VIDEO Rack
|
||||
nodes:
|
||||
- video
|
||||
- "ATEM 2 M/E Constellation 4K"
|
||||
- "HyperDeck-Studio-4K-Pro"
|
||||
- RX-QLAB-1
|
||||
- RX-QLAB-2
|
||||
- TX-PROJ-1
|
||||
- TX-PROJ-2
|
||||
- TX-M4
|
||||
- TX-M16
|
||||
- TX-MISC
|
||||
- TX-PREVIEW
|
||||
- names: ["video"]
|
||||
- names: ["ATEM 2 M/E Constellation 4K"]
|
||||
- names: ["HyperDeck-Studio-4K-Pro"]
|
||||
- names: ["RX-QLAB-1"]
|
||||
- names: ["RX-QLAB-2"]
|
||||
- names: ["TX-PROJ-1"]
|
||||
- names: ["TX-PROJ-2"]
|
||||
- names: ["TX-M4"]
|
||||
- names: ["TX-M16"]
|
||||
- names: ["TX-MISC"]
|
||||
- names: ["TX-PREVIEW"]
|
||||
|
||||
- direction: horizontal
|
||||
children:
|
||||
- nodes:
|
||||
- "Y001-MAIN1-L-d1e155"
|
||||
- "ac:44:f2:4e:84:d6" # MAIN1-L bridge interface
|
||||
- names: ["Y001-MAIN1-L-d1e155"]
|
||||
macs: ["ac:44:f2:4e:84:d6"]
|
||||
|
||||
- name: Stage 2
|
||||
nodes:
|
||||
- "MON2"
|
||||
- names: ["MON2"]
|
||||
|
||||
- name: Stage 3
|
||||
nodes:
|
||||
- "MON3"
|
||||
- names: ["MON3"]
|
||||
|
||||
- nodes:
|
||||
- "Y001-MAIN1-R-d1e194"
|
||||
- "ac:44:f2:4e:84:d4" # MAIN1-R bridge interface
|
||||
- names: ["Y001-MAIN1-R-d1e194"]
|
||||
macs: ["ac:44:f2:4e:84:d4"]
|
||||
|
||||
- direction: horizontal
|
||||
children:
|
||||
- nodes:
|
||||
- "RX-PROJ-1"
|
||||
- names: ["RX-PROJ-1"]
|
||||
|
||||
- nodes:
|
||||
- "RX-PROJ-2"
|
||||
- names: ["RX-PROJ-2"]
|
||||
|
||||
- direction: horizontal
|
||||
children:
|
||||
- nodes:
|
||||
- satellite-2
|
||||
- "Y001-MAIN2-L-d1e298"
|
||||
- "ac:44:f2:4e:87:2a" # MAIN2-L bridge interface
|
||||
- DMXA # wash1
|
||||
- DMXB # wash2
|
||||
- DMXC # wash3
|
||||
- DMXM # focus{1,2}
|
||||
- names: ["satellite-2"]
|
||||
- names: ["Y001-MAIN2-L-d1e298"]
|
||||
macs: ["ac:44:f2:4e:87:2a"]
|
||||
- names: ["DMXA"] # wash1
|
||||
- names: ["DMXB"] # wash2
|
||||
- names: ["DMXC"] # wash3
|
||||
- names: ["DMXM"] # focus{1,2}
|
||||
|
||||
- nodes:
|
||||
- DMXN # focus{3,4}
|
||||
- DMXP # r3x{1,2}
|
||||
- names: ["DMXN"] # focus{3,4}
|
||||
- names: ["DMXP"] # r3x{1,2}
|
||||
|
||||
- nodes:
|
||||
- satellite-3
|
||||
- "Y001-MAIN2-R-f0dd93"
|
||||
- "ac:44:f2:4e:87:27" # MAIN2-R bridge interface
|
||||
- DMXD # wash4
|
||||
- DMXE # wash5
|
||||
- DMXF # wash6
|
||||
- DMXO # focus{5,6}
|
||||
- names: ["satellite-3"]
|
||||
- names: ["Y001-MAIN2-R-f0dd93"]
|
||||
macs: ["ac:44:f2:4e:87:27"]
|
||||
- names: ["DMXD"] # wash4
|
||||
- names: ["DMXE"] # wash5
|
||||
- names: ["DMXF"] # wash6
|
||||
- names: ["DMXO"] # focus{5,6}
|
||||
|
||||
- name: Booth
|
||||
direction: vertical
|
||||
children:
|
||||
- nodes:
|
||||
- satellite-1
|
||||
- names: ["satellite-1"]
|
||||
|
||||
- direction: horizontal
|
||||
children:
|
||||
- name: Lighting Control
|
||||
nodes:
|
||||
- qlab
|
||||
- TX-QLAB-1
|
||||
- TX-QLAB-2
|
||||
- "SK_PTZEXTREMEV2 [457081]"
|
||||
- "SK_RACKPRO2 [452514]"
|
||||
- pigeon
|
||||
- showpi1
|
||||
- d8:3a:dd:e3:5b:db # showpi2/artmap
|
||||
- names: ["qlab"]
|
||||
- names: ["TX-QLAB-1"]
|
||||
- names: ["TX-QLAB-2"]
|
||||
- names: ["SK_PTZEXTREMEV2 [457081]"]
|
||||
- names: ["SK_RACKPRO2 [452514]"]
|
||||
- names: ["pigeon"]
|
||||
- names: ["showpi1"]
|
||||
- macs: ["d8:3a:dd:e3:5b:db"] # showpi2/artmap
|
||||
|
||||
- name: Sound Control
|
||||
nodes:
|
||||
- SQ-7
|
||||
- "00:04:c4:15:07:a4" # SQ-7 bridge port
|
||||
- BT
|
||||
- names: ["SQ-7"]
|
||||
macs: ["00:04:c4:15:07:a4"]
|
||||
- names: ["BT"]
|
||||
|
||||
- name: Camera Control
|
||||
nodes:
|
||||
- RX-CC-PREVIEW
|
||||
- RX-CC-M16
|
||||
- "AtemPanel-7c2e0da86d22"
|
||||
- "AtemPanel-7c2e0da86d4c"
|
||||
- names: ["RX-CC-PREVIEW"]
|
||||
- names: ["RX-CC-M16"]
|
||||
- names: ["AtemPanel-7c2e0da86d22"]
|
||||
- names: ["AtemPanel-7c2e0da86d4c"]
|
||||
|
||||
- name: Video Control
|
||||
nodes:
|
||||
- RX-VC-M4
|
||||
- RX-VC-M16
|
||||
- "ATEM-2-ME-Advanced-Panel-20"
|
||||
- names: ["RX-VC-M4"]
|
||||
- names: ["RX-VC-M16"]
|
||||
- names: ["ATEM-2-ME-Advanced-Panel-20"]
|
||||
|
||||
- name: Control
|
||||
nodes:
|
||||
- sunset
|
||||
- RX-CONTROL-1
|
||||
- names: ["sunset"]
|
||||
- names: ["RX-CONTROL-1"]
|
||||
|
||||
95
nodes.go
95
nodes.go
@@ -40,19 +40,20 @@ func (n *Nodes) Shutdown() {
|
||||
n.cancelAll()
|
||||
}
|
||||
|
||||
func (n *Nodes) Update(target *Node, mac net.HardwareAddr, ips []net.IP, ifaceName, nodeName, source string) {
|
||||
changed := n.updateLocked(target, mac, ips, ifaceName, nodeName, source)
|
||||
func (n *Nodes) Update(target *Node, mac net.HardwareAddr, ips []net.IP, ifaceName, nodeName, source string) *Node {
|
||||
node, changed := n.updateLocked(target, mac, ips, ifaceName, nodeName, source)
|
||||
if changed {
|
||||
n.t.NotifyUpdate()
|
||||
}
|
||||
return node
|
||||
}
|
||||
|
||||
func (n *Nodes) updateLocked(target *Node, mac net.HardwareAddr, ips []net.IP, ifaceName, nodeName, source string) bool {
|
||||
func (n *Nodes) updateLocked(target *Node, mac net.HardwareAddr, ips []net.IP, ifaceName, nodeName, source string) (*Node, bool) {
|
||||
n.mu.Lock()
|
||||
defer n.mu.Unlock()
|
||||
|
||||
if mac == nil && target == nil && len(ips) == 0 {
|
||||
return false
|
||||
if mac == nil && target == nil && len(ips) == 0 && nodeName == "" {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
node, isNew := n.resolveTargetNode(target, mac, ips, nodeName)
|
||||
@@ -65,7 +66,7 @@ func (n *Nodes) updateLocked(target *Node, mac net.HardwareAddr, ips []net.IP, i
|
||||
n.triggerPoll(node)
|
||||
}
|
||||
|
||||
return isNew || len(added) > 0
|
||||
return node, isNew || len(added) > 0
|
||||
}
|
||||
|
||||
func (n *Nodes) resolveTargetNode(target *Node, mac net.HardwareAddr, ips []net.IP, nodeName string) (*Node, bool) {
|
||||
@@ -119,7 +120,7 @@ func (n *Nodes) findOrMergeByName(target *Node, nodeName string) *Node {
|
||||
if target == nil {
|
||||
return found
|
||||
}
|
||||
if found != target && len(found.Interfaces) == 0 {
|
||||
if found != target {
|
||||
n.mergeNodes(target, found)
|
||||
}
|
||||
return target
|
||||
@@ -368,7 +369,7 @@ func (n *Nodes) Merge(macs []net.HardwareAddr, source string) {
|
||||
}
|
||||
|
||||
func (n *Nodes) mergeNodes(keep, merge *Node) {
|
||||
if keep == nil || merge == nil {
|
||||
if keep == nil || merge == nil || keep == merge {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -380,15 +381,21 @@ func (n *Nodes) mergeNodes(keep, merge *Node) {
|
||||
n.nameIndex[name] = keep
|
||||
}
|
||||
|
||||
for _, iface := range merge.Interfaces {
|
||||
var ips []net.IP
|
||||
for ipStr := range iface.IPs {
|
||||
ips = append(ips, net.ParseIP(ipStr))
|
||||
}
|
||||
for ifaceKey, iface := range merge.Interfaces {
|
||||
if iface.MAC != "" {
|
||||
n.updateNodeInterface(keep, iface.MAC.Parse(), ips, iface.Name)
|
||||
n.macIndex[string(iface.MAC)] = keep
|
||||
}
|
||||
for ipStr := range iface.IPs {
|
||||
n.ipIndex[ipStr] = keep
|
||||
}
|
||||
if _, exists := keep.Interfaces[ifaceKey]; !exists {
|
||||
keep.Interfaces[ifaceKey] = iface
|
||||
} else {
|
||||
keepIface := keep.Interfaces[ifaceKey]
|
||||
for ipStr := range iface.IPs {
|
||||
keepIface.IPs.Add(net.ParseIP(ipStr))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for peerMAC, ifaceName := range merge.MACTable {
|
||||
@@ -620,3 +627,63 @@ func (n *Nodes) LogAll() {
|
||||
n.logArtNet()
|
||||
n.logDante()
|
||||
}
|
||||
|
||||
func (n *Nodes) ApplyConfig(cfg *Config) {
|
||||
if cfg == nil {
|
||||
return
|
||||
}
|
||||
for _, nc := range cfg.AllNodeConfigs() {
|
||||
n.applyNodeConfig(nc)
|
||||
}
|
||||
}
|
||||
|
||||
func (n *Nodes) applyNodeConfig(nc *NodeConfig) {
|
||||
if len(nc.Names) == 0 && len(nc.MACs) == 0 && len(nc.IPs) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
var macs []net.HardwareAddr
|
||||
for _, macStr := range nc.MACs {
|
||||
if mac, err := net.ParseMAC(macStr); err == nil {
|
||||
macs = append(macs, mac)
|
||||
}
|
||||
}
|
||||
|
||||
var ips []net.IP
|
||||
for _, ipStr := range nc.IPs {
|
||||
if ip := net.ParseIP(ipStr); ip != nil {
|
||||
ips = append(ips, ip)
|
||||
}
|
||||
}
|
||||
|
||||
var firstMAC net.HardwareAddr
|
||||
if len(macs) > 0 {
|
||||
firstMAC = macs[0]
|
||||
}
|
||||
firstName := ""
|
||||
if len(nc.Names) > 0 {
|
||||
firstName = nc.Names[0]
|
||||
}
|
||||
|
||||
target := n.Update(nil, firstMAC, ips, "", firstName, "config")
|
||||
if target == nil {
|
||||
return
|
||||
}
|
||||
|
||||
for i := 1; i < len(macs); i++ {
|
||||
n.Update(target, macs[i], nil, "", "", "config")
|
||||
}
|
||||
for i := 1; i < len(nc.Names); i++ {
|
||||
n.Update(target, nil, nil, "", nc.Names[i], "config")
|
||||
}
|
||||
|
||||
if nc.Avoid {
|
||||
n.setAvoid(target)
|
||||
}
|
||||
}
|
||||
|
||||
func (n *Nodes) setAvoid(node *Node) {
|
||||
n.mu.Lock()
|
||||
defer n.mu.Unlock()
|
||||
node.Avoid = true
|
||||
}
|
||||
|
||||
4
ping.go
4
ping.go
@@ -140,6 +140,10 @@ func (pm *PingManager) Ping(ipStr string, timeout time.Duration) bool {
|
||||
|
||||
func (t *Tendrils) pingNode(node *Node) {
|
||||
t.nodes.mu.RLock()
|
||||
if node.Avoid {
|
||||
t.nodes.mu.RUnlock()
|
||||
return
|
||||
}
|
||||
var ips []string
|
||||
nodeName := node.DisplayName()
|
||||
nodeID := node.ID
|
||||
|
||||
@@ -107,7 +107,11 @@ export function buildLocationTree(locations, parent) {
|
||||
name: loc.name || '',
|
||||
anonymous: anonymous,
|
||||
direction: loc.direction || 'horizontal',
|
||||
nodeRefs: (loc.nodes || []).map(n => n.toLowerCase()),
|
||||
nodeRefs: (loc.nodes || []).flatMap(n => [
|
||||
...(n.names || []).map(name => name.toLowerCase()),
|
||||
...(n.macs || []).map(mac => mac.toLowerCase()),
|
||||
...(n.ips || [])
|
||||
]),
|
||||
parent: parent,
|
||||
children: []
|
||||
};
|
||||
|
||||
@@ -125,6 +125,7 @@ func (t *Tendrils) Run() {
|
||||
signal.Notify(sigUsr1Ch, syscall.SIGUSR1)
|
||||
go func() {
|
||||
for range sigUsr1Ch {
|
||||
t.nodes.ApplyConfig(t.config)
|
||||
t.nodes.LogAll()
|
||||
}
|
||||
}()
|
||||
@@ -139,6 +140,7 @@ func (t *Tendrils) Run() {
|
||||
continue
|
||||
}
|
||||
t.config = cfg
|
||||
t.nodes.ApplyConfig(cfg)
|
||||
log.Printf("reloaded config from %s", t.ConfigFile)
|
||||
t.NotifyUpdate()
|
||||
}
|
||||
@@ -149,6 +151,7 @@ func (t *Tendrils) Run() {
|
||||
log.Fatalf("[ERROR] failed to load config: %v", err)
|
||||
}
|
||||
t.config = cfg
|
||||
t.nodes.ApplyConfig(cfg)
|
||||
|
||||
t.populateLocalAddresses()
|
||||
t.startHTTPServer()
|
||||
@@ -312,6 +315,10 @@ func (t *Tendrils) startInterface(ctx context.Context, iface net.Interface) {
|
||||
|
||||
func (t *Tendrils) pollNode(node *Node) {
|
||||
t.nodes.mu.RLock()
|
||||
if node.Avoid {
|
||||
t.nodes.mu.RUnlock()
|
||||
return
|
||||
}
|
||||
var ips []net.IP
|
||||
for _, iface := range node.Interfaces {
|
||||
for ipStr := range iface.IPs {
|
||||
|
||||
1
types.go
1
types.go
@@ -460,6 +460,7 @@ type Node struct {
|
||||
SACNOutputs SACNUniverseSet `json:"sacn_outputs,omitempty"`
|
||||
ArtmapMappings []ArtmapMapping `json:"artmap_mappings,omitempty"`
|
||||
Unreachable bool `json:"unreachable,omitempty"`
|
||||
Avoid bool `json:"avoid,omitempty"`
|
||||
errors *ErrorTracker
|
||||
pollTrigger chan struct{}
|
||||
cancelFunc context.CancelFunc
|
||||
|
||||
Reference in New Issue
Block a user