freifunkmanager/runtime/nodes.go

117 lines
2.7 KiB
Go

package runtime
import (
"sync"
"github.com/FreifunkBremen/yanic/lib/jsontime"
log "github.com/sirupsen/logrus"
yanicRuntime "github.com/FreifunkBremen/yanic/runtime"
"github.com/genofire/golang-lib/file"
"github.com/FreifunkBremen/freifunkmanager/ssh"
)
type Nodes struct {
List map[string]*Node `json:"nodes"`
Current map[string]*Node `json:"-"`
ssh *ssh.Manager
statePath string
iface string
notifyFunc []func(*Node, bool)
sync.Mutex
}
func NewNodes(path string, iface string, mgmt *ssh.Manager) *Nodes {
nodes := &Nodes{
List: make(map[string]*Node),
Current: make(map[string]*Node),
ssh: mgmt,
statePath: path,
iface: iface,
}
file.ReadJSON(path, nodes)
return nodes
}
func (nodes *Nodes) LearnNode(n *yanicRuntime.Node) {
node := NewNode(n)
if node == nil {
return
}
node.Lastseen = jsontime.Now()
logger := log.WithField("method", "LearnNode").WithField("node_id", node.NodeID)
nodes.Lock()
defer nodes.Unlock()
if lNode := nodes.List[node.NodeID]; lNode != nil {
lNode.Lastseen = jsontime.Now()
lNode.Stats = node.Stats
} else {
nodes.List[node.NodeID] = node
nodes.notify(node, true)
}
if _, ok := nodes.Current[node.NodeID]; ok {
nodes.Current[node.NodeID] = node
nodes.notify(node, false)
return
}
// session := nodes.ssh.ConnectTo(node.Address)
result, err := nodes.ssh.RunOn(node.GetAddress(nodes.iface), "uptime")
if err != nil {
logger.Debug("init ssh command not run", err)
return
}
uptime := ssh.SSHResultToString(result)
logger.Infof("new node with uptime: %s", uptime)
nodes.Current[node.NodeID] = node
if lNode := nodes.List[node.NodeID]; lNode != nil {
lNode.Address = node.Address
go lNode.SSHUpdate(nodes.ssh, nodes.iface, node)
}
nodes.notify(node, false)
}
func (nodes *Nodes) AddNotify(f func(*Node, bool)) {
nodes.notifyFunc = append(nodes.notifyFunc, f)
}
func (nodes *Nodes) notify(node *Node, system bool) {
for _, f := range nodes.notifyFunc {
f(node, system)
}
}
func (nodes *Nodes) UpdateNode(node *Node) {
if node == nil {
log.Warn("no new node to update")
return
}
nodes.Lock()
defer nodes.Unlock()
if n, ok := nodes.List[node.NodeID]; ok {
node.Address = n.Address
go node.SSHUpdate(nodes.ssh, nodes.iface, n)
log.Info("update node", node.NodeID)
}
nodes.List[node.NodeID] = node
nodes.notify(node, true)
}
func (nodes *Nodes) Updater() {
nodes.Lock()
defer nodes.Unlock()
for nodeid, node := range nodes.List {
if n, ok := nodes.Current[nodeid]; ok {
go node.SSHUpdate(nodes.ssh, nodes.iface, n)
}
}
log.Info("updater per ssh")
}
func (nodes *Nodes) Saver() {
nodes.Lock()
file.SaveJSON(nodes.statePath, nodes)
nodes.Unlock()
log.Debug("saved state file")
}