freifunkmanager/runtime/nodes.go

131 lines
3.1 KiB
Go
Raw Normal View History

package runtime
import (
2017-05-07 03:37:30 +02:00
"encoding/json"
"os"
2017-05-12 21:32:10 +02:00
"sync"
2017-05-12 21:32:10 +02:00
"github.com/FreifunkBremen/yanic/jsontime"
yanic "github.com/FreifunkBremen/yanic/runtime"
"github.com/FreifunkBremen/freifunkmanager/lib/log"
"github.com/FreifunkBremen/freifunkmanager/ssh"
)
type Nodes struct {
2017-05-08 19:13:29 +02:00
List map[string]*Node `json:"nodes"`
ToUpdate map[string]*Node
ssh *ssh.Manager
statePath string
iface string
notifyFunc []func(*Node, bool)
2017-05-12 21:32:10 +02:00
sync.Mutex
}
2017-05-07 03:37:30 +02:00
func NewNodes(path string, iface string, mgmt *ssh.Manager) *Nodes {
nodes := &Nodes{
List: make(map[string]*Node),
2017-05-08 19:13:29 +02:00
ToUpdate: make(map[string]*Node),
2017-05-07 03:37:30 +02:00
ssh: mgmt,
statePath: path,
iface: iface,
}
2017-05-07 03:37:30 +02:00
nodes.load()
return nodes
}
2017-05-07 03:37:30 +02:00
func (nodes *Nodes) AddNode(n *yanic.Node) {
node := NewNode(n)
if node == nil {
return
}
2017-05-12 21:32:10 +02:00
node.Lastseen = jsontime.Now()
2017-05-07 03:37:30 +02:00
logger := log.Log.WithField("method", "AddNode").WithField("node_id", node.NodeID)
2017-05-12 21:32:10 +02:00
nodes.Lock()
nodes.Unlock()
2017-05-07 03:37:30 +02:00
if cNode := nodes.List[node.NodeID]; cNode != nil {
2017-05-12 21:32:10 +02:00
cNode.Lastseen = jsontime.Now()
cNode.Stats = node.Stats
if uNode, ok := nodes.ToUpdate[node.NodeID]; ok {
2017-05-12 21:32:10 +02:00
uNode.Lastseen = jsontime.Now()
uNode.Stats = node.Stats
2017-05-07 03:37:30 +02:00
if nodes.List[node.NodeID].IsEqual(node) {
delete(nodes.ToUpdate, node.NodeID)
2017-05-08 19:13:29 +02:00
nodes.List[node.NodeID] = node
nodes.notify(node, true)
} else {
nodes.notify(uNode, false)
2017-05-07 03:37:30 +02:00
}
} else {
nodes.List[node.NodeID] = node
2017-05-08 19:13:29 +02:00
nodes.notify(node, true)
2017-05-07 03:37:30 +02:00
}
logger.Debugf("know already these node")
return
}
2017-05-07 03:37:30 +02:00
// session := nodes.ssh.ConnectTo(node.Address)
result, err := nodes.ssh.RunOn(node.GetAddress(nodes.iface), "uptime")
if err != nil {
logger.Error("init ssh command not run")
return
}
uptime := ssh.SSHResultToString(result)
logger.Infof("new node with uptime: %s", uptime)
2017-05-07 03:37:30 +02:00
nodes.List[node.NodeID] = node
2017-05-08 19:13:29 +02:00
nodes.notify(node, true)
}
func (nodes *Nodes) AddNotify(f func(*Node, bool)) {
nodes.notifyFunc = append(nodes.notifyFunc, f)
}
func (nodes *Nodes) notify(node *Node, real bool) {
for _, f := range nodes.notifyFunc {
f(node, real)
}
2017-05-07 03:37:30 +02:00
}
func (nodes *Nodes) UpdateNode(node *Node) {
2017-05-08 19:13:29 +02:00
if node == nil {
log.Log.Warn("no new node to update")
return
}
2017-05-12 21:32:10 +02:00
nodes.Lock()
defer nodes.Unlock()
2017-05-07 03:37:30 +02:00
if n, ok := nodes.List[node.NodeID]; ok {
go node.SSHUpdate(nodes.ssh, nodes.iface, n)
}
2017-05-08 19:13:29 +02:00
nodes.ToUpdate[node.NodeID] = node
nodes.notify(node, false)
2017-05-07 03:37:30 +02:00
}
func (nodes *Nodes) Updater() {
2017-05-12 21:32:10 +02:00
nodes.Lock()
defer nodes.Unlock()
2017-05-07 03:37:30 +02:00
for nodeid := range nodes.ToUpdate {
if node := nodes.List[nodeid]; node != nil {
go node.SSHSet(nodes.ssh, nodes.iface)
}
}
2017-05-08 19:13:29 +02:00
log.Log.Debug("updater per ssh runs")
2017-05-07 03:37:30 +02:00
}
func (nodes *Nodes) load() {
if f, err := os.Open(nodes.statePath); err == nil { // transform data to legacy meshviewer
if err = json.NewDecoder(f).Decode(nodes); err == nil {
2017-05-08 19:13:29 +02:00
log.Log.Infof("loaded %d nodes", len(nodes.List))
2017-05-07 03:37:30 +02:00
} else {
log.Log.Error("failed to unmarshal nodes:", err)
}
} else {
log.Log.Error("failed to load cached nodes:", err)
}
}
func (nodes *Nodes) Saver() {
2017-05-12 21:32:10 +02:00
nodes.Lock()
2017-05-07 03:37:30 +02:00
yanic.SaveJSON(nodes, nodes.statePath)
2017-05-12 21:32:10 +02:00
nodes.Unlock()
2017-05-08 19:13:29 +02:00
log.Log.Debug("saved state file")
}