From 67c6031fff544634f441b76f7de7911271c70b14 Mon Sep 17 00:00:00 2001 From: Martin Geno Date: Thu, 16 Jun 2016 18:03:45 +0200 Subject: [PATCH] multi nodes --- config_example.yml | 4 ++- main.go | 21 +++++++------ models/config.go | 31 ++++++++++---------- models/graph.go | 70 ++++++++++++++++++++++---------------------- models/nodes.go | 43 ++++----------------------- respond/collector.go | 7 +++-- 6 files changed, 73 insertions(+), 103 deletions(-) diff --git a/config_example.yml b/config_example.yml index 80978d4..b28551c 100644 --- a/config_example.yml +++ b/config_example.yml @@ -1,6 +1,7 @@ --- respondd: enable: true + interface: eth0 collectinterval: 15 webserver: enable: false @@ -12,7 +13,8 @@ webserver: aliases: true nodes: enable: true - nodes_path: /var/www/html/meshviewer/data/nodes.json + nodes_path: /var/www/html/meshviewer/data/nodes_all.json + nodesmini_path: /var/www/html/meshviewer/data/nodes.json graphs_path: /var/www/html/meshviewer/data/graph.json saveinterval: 5 aliases_enable: false diff --git a/main.go b/main.go index d336558..a494737 100644 --- a/main.go +++ b/main.go @@ -10,21 +10,21 @@ import ( "syscall" "time" - "github.com/julienschmidt/httprouter" "github.com/NYTimes/gziphandler" + "github.com/julienschmidt/httprouter" + "github.com/FreifunkBremen/respond-collector/api" "github.com/FreifunkBremen/respond-collector/data" "github.com/FreifunkBremen/respond-collector/models" "github.com/FreifunkBremen/respond-collector/respond" - "github.com/FreifunkBremen/respond-collector/api" ) var ( - configFile string - config *models.Config - collector *respond.Collector - statsDb *StatsDb - nodes *models.Nodes + configFile string + config *models.Config + collector *respond.Collector + statsDb *StatsDb + nodes *models.Nodes ) func main() { @@ -39,18 +39,17 @@ func main() { if config.Respondd.Enable { collectInterval := time.Second * time.Duration(config.Respondd.CollectInterval) - collector = respond.NewCollector("nodeinfo statistics neighbours", collectInterval, onReceive) + collector = respond.NewCollector("nodeinfo statistics neighbours", collectInterval, onReceive, config.Respondd.Interface) } - if config.Webserver.Enable { router := httprouter.New() if config.Webserver.Api.NewNodes { - api.NewNodes(config,router,"/api/nodes",nodes) + api.NewNodes(config, router, "/api/nodes", nodes) log.Println("api nodes started") } if config.Webserver.Api.Aliases { - api.NewAliases(config,router,"/api/aliases",nodes) + api.NewAliases(config, router, "/api/aliases", nodes) log.Println("api aliases started") } router.NotFound = gziphandler.GzipHandler(http.FileServer(http.Dir(config.Webserver.Webroot))) diff --git a/models/config.go b/models/config.go index 963b4f3..8e04e0c 100644 --- a/models/config.go +++ b/models/config.go @@ -11,32 +11,31 @@ import ( type Config struct { Respondd struct { Enable bool `yaml:"enable"` - Port string `yaml:"port"` - Address string `yaml:"address"` + Interface string `yaml:"interface"` CollectInterval int `yaml:"collectinterval"` } `yaml:"respondd"` Webserver struct { - Enable bool `yaml:"enable"` - Port string `yaml:"port"` - Address string `yaml:"address"` - Webroot string `yaml:"webroot"` - Api struct { + Enable bool `yaml:"enable"` + Port string `yaml:"port"` + Address string `yaml:"address"` + Webroot string `yaml:"webroot"` + Api struct { Passphrase string `yaml:"passphrase"` - NewNodes bool `yaml:"newnodes"` - Aliases bool `yaml:"aliases"` + NewNodes bool `yaml:"newnodes"` + Aliases bool `yaml:"aliases"` } `yaml:"api"` } `yaml:"webserver"` Nodes struct { - Enable bool `yaml:"enable"` - NodesPath string `yaml:"nodes_path"` - GraphsPath string `yaml:"graphs_path"` - AliasesPath string `yaml:"aliases_path"` - SaveInterval int `yaml:"saveinterval"` - VpnAddresses []string `yaml:"vpn_addresses"` + Enable bool `yaml:"enable"` + NodesPath string `yaml:"nodes_path"` + NodesMiniPath string `yaml:"nodesmini_path"` + GraphsPath string `yaml:"graphs_path"` + AliasesPath string `yaml:"aliases_path"` + SaveInterval int `yaml:"saveinterval"` } `yaml:"nodes"` Influxdb struct { Enable bool `yaml:"enable"` - Addr string `yaml:"host"` + Addr string `yaml:"host"` Database string `yaml:"database"` Username string `yaml:"username"` Password string `yaml:"password"` diff --git a/models/graph.go b/models/graph.go index af59207..4e4e2c9 100644 --- a/models/graph.go +++ b/models/graph.go @@ -8,23 +8,23 @@ import ( type Graph struct { Version int `json:"version"` Batadv struct { - Directed bool `json:"directed"` - Graph []string `json:"graph"` - Nodes []*GraphNode `json:"nodes"` - Links []*GraphLink `json:"links"` + Directed bool `json:"directed"` + Graph []string `json:"graph"` + Nodes []*GraphNode `json:"nodes"` + Links []*GraphLink `json:"links"` } `json:"batadv"` } type GraphNode struct { - ID string `json:"id"` - NodeID string `json:"node_id"` + ID string `json:"id"` + NodeID string `json:"node_id"` } type GraphLink struct { - Source interface{} `json:"source"` - Target interface{} `json:"target"` - VPN bool `json:"vpn"` - TQ float32 `json:"tq"` - Bidirect bool `json:"bidirect"` + Source interface{} `json:"source"` + Target interface{} `json:"target"` + VPN bool `json:"vpn"` + TQ float32 `json:"tq"` + Bidirect bool `json:"bidirect"` } type GraphBuilder struct { @@ -50,30 +50,30 @@ func (nodes *Nodes) BuildGraph() *Graph { func (builder *GraphBuilder) readNodes(nodes map[string]*Node) { // Fill mac->id map - for sourceId, node := range nodes { + for sourceID, node := range nodes { if nodeinfo := node.Nodeinfo; nodeinfo != nil { // is VPN address? if nodeinfo.VPN { - builder.vpn[sourceId] = nil + builder.vpn[sourceID] = nil } - for _,batinterface := range nodeinfo.Network.Mesh { + for _, batinterface := range nodeinfo.Network.Mesh { interfaces := batinterface.Interfaces addresses := append(append(interfaces.Other, interfaces.Tunnel...), interfaces.Wireless...) for _, sourceAddress := range addresses { - builder.macToID[sourceAddress] = sourceId + builder.macToID[sourceAddress] = sourceID } } } } // Add links - for sourceId, node := range nodes { + for sourceID, node := range nodes { if neighbours := node.Neighbours; neighbours != nil { for _, batadvNeighbours := range neighbours.Batadv { for targetAddress, link := range batadvNeighbours.Neighbours { - if targetId, found := builder.macToID[targetAddress]; found { - builder.addLink(targetId, sourceId, link.Tq) + if targetID, found := builder.macToID[targetAddress]; found { + builder.addLink(targetID, sourceID, link.Tq) } } } @@ -81,7 +81,7 @@ func (builder *GraphBuilder) readNodes(nodes map[string]*Node) { } } -func (builder *GraphBuilder) Extract() ([]*GraphNode,[]*GraphLink) { +func (builder *GraphBuilder) Extract() ([]*GraphNode, []*GraphLink) { iNodes := 0 iLinks := 0 links := make([]*GraphLink, len(builder.links)) @@ -89,32 +89,32 @@ func (builder *GraphBuilder) Extract() ([]*GraphNode,[]*GraphLink) { for mac, nodeID := range builder.macToID { nodes[iNodes] = &GraphNode{ - ID: mac, + ID: mac, NodeID: nodeID, } - iNodes += 1 + iNodes++ } for key, link := range builder.links { - linkPart :=strings.Split(key,"-") + linkPart := strings.Split(key, "-") both := 0 - for i,node := range nodes{ - if(linkPart[0] == node.NodeID){ + for i, node := range nodes { + if linkPart[0] == node.NodeID { link.Source = i - both += 1 + both++ continue } - if(linkPart[1]==node.NodeID){ + if linkPart[1] == node.NodeID { link.Target = i - both += 1 + both++ break } } if both == 2 { links[iLinks] = link - iLinks += 1 + iLinks++ } } - return nodes, links[:iLinks] + return nodes, links[:iLinks] } func (builder *GraphBuilder) isVPN(ids ...string) bool { @@ -126,13 +126,13 @@ func (builder *GraphBuilder) isVPN(ids ...string) bool { return false } -func (builder *GraphBuilder) addLink(targetId string, sourceId string, linkTq int) { +func (builder *GraphBuilder) addLink(targetID string, sourceID string, linkTq int) { // Sort IDs to generate the key var key string - if strings.Compare(sourceId, targetId) > 0 { - key = fmt.Sprintf("%s-%s", sourceId, targetId) + if strings.Compare(sourceID, targetID) > 0 { + key = fmt.Sprintf("%s-%s", sourceID, targetID) } else { - key = fmt.Sprintf("%s-%s", targetId, sourceId) + key = fmt.Sprintf("%s-%s", targetID, sourceID) } var tq float32 @@ -142,8 +142,8 @@ func (builder *GraphBuilder) addLink(targetId string, sourceId string, linkTq in if link, ok := builder.links[key]; !ok { builder.links[key] = &GraphLink{ - VPN: builder.isVPN(sourceId, targetId), - TQ: tq, + VPN: builder.isVPN(sourceID, targetID), + TQ: tq, } } else { // Use lowest of both link qualities diff --git a/models/nodes.go b/models/nodes.go index 6887fc4..db9d0dd 100644 --- a/models/nodes.go +++ b/models/nodes.go @@ -44,7 +44,7 @@ func NewNodes(config *Config) *Nodes { } go nodes.worker() - nodes.Version = 1 + nodes.Version = 2 return nodes } @@ -89,9 +89,9 @@ func (nodes *Nodes) Update(nodeID string, res *data.ResponseData) { node.Statistics = val } } -func (nodes *Nodes) GetMeshviewer() *meshviewer.Nodes { +func (nodes *Nodes) GetNodesMini() *meshviewer.Nodes { meshviewerNodes := &meshviewer.Nodes{ - Version: nodes.Version, + Version: 1, List: make(map[string]*meshviewer.Node), Timestamp: nodes.Timestamp, } @@ -144,7 +144,8 @@ func (nodes *Nodes) worker() { } } // serialize nodes - save(nodes.GetMeshviewer(), nodes.config.Nodes.NodesPath) + save(nodes, nodes.config.Nodes.NodesPath) + save(nodes.GetNodesMini(), nodes.config.Nodes.NodesMiniPath) if path := nodes.config.Nodes.GraphsPath; path != "" { save(nodes.BuildGraph(), path) @@ -159,39 +160,7 @@ func (nodes *Nodes) load() { log.Println("loading", path) if filedata, err := ioutil.ReadFile(path); err == nil { - meshviewerNodes := &meshviewer.Nodes{} - if err := json.Unmarshal(filedata, meshviewerNodes); err == nil { - nodes.Version = meshviewerNodes.Version - nodes.Timestamp = meshviewerNodes.Timestamp - nodes.List = make(map[string]*Node) - for nodeID, _ := range meshviewerNodes.List { - nodes.Lock() - node, _ := nodes.List[nodeID] - - if node == nil { - node = &Node{ - Firstseen: meshviewerNodes.List[nodeID].Firstseen, - Lastseen: meshviewerNodes.List[nodeID].Lastseen, - Flags: meshviewerNodes.List[nodeID].Flags, - Nodeinfo: meshviewerNodes.List[nodeID].Nodeinfo, - } - nodes.List[nodeID] = node - } - nodes.Unlock() - node.Statistics = &data.Statistics{ - NodeId: meshviewerNodes.List[nodeID].Statistics.NodeId, - Clients: data.Clients{Total: meshviewerNodes.List[nodeID].Statistics.Clients}, - Gateway: meshviewerNodes.List[nodeID].Statistics.Gateway, - RootFsUsage: meshviewerNodes.List[nodeID].Statistics.RootFsUsage, - LoadAverage: meshviewerNodes.List[nodeID].Statistics.LoadAverage, - Memory: meshviewerNodes.List[nodeID].Statistics.Memory, - Uptime: meshviewerNodes.List[nodeID].Statistics.Uptime, - Idletime: meshviewerNodes.List[nodeID].Statistics.Idletime, - Processes: meshviewerNodes.List[nodeID].Statistics.Processes, - MeshVpn: meshviewerNodes.List[nodeID].Statistics.MeshVpn, - Traffic: meshviewerNodes.List[nodeID].Statistics.Traffic, - } - } + if err := json.Unmarshal(filedata, nodes); err == nil { log.Println("loaded", len(nodes.List), "nodes") } else { log.Println("failed to unmarshal nodes:", err) diff --git a/respond/collector.go b/respond/collector.go index 5b32204..4b93035 100644 --- a/respond/collector.go +++ b/respond/collector.go @@ -19,7 +19,7 @@ type Collector struct { queue chan *Response // received responses onReceive OnReceive msgType reflect.Type - + intface string // Ticker and stopper ticker *time.Ticker stop chan interface{} @@ -28,7 +28,7 @@ type Collector struct { type OnReceive func(net.UDPAddr, *data.ResponseData) //NewCollector creates a Collector struct -func NewCollector(CollectType string, interval time.Duration, onReceive OnReceive) *Collector { +func NewCollector(CollectType string, interval time.Duration, onReceive OnReceive, intface string) *Collector { // Parse address addr, err := net.ResolveUDPAddr("udp", "[::]:0") if err != nil { @@ -49,6 +49,7 @@ func NewCollector(CollectType string, interval time.Duration, onReceive OnReceiv ticker: time.NewTicker(interval), stop: make(chan interface{}, 1), onReceive: onReceive, + intface: intface, } go collector.receiver() @@ -74,7 +75,7 @@ func (coll *Collector) Close() { } func (coll *Collector) sendOnce() { - coll.sendPacket(net.JoinHostPort(multiCastGroup, port)) + coll.sendPacket(net.JoinHostPort(multiCastGroup+"%"+coll.intface, port)) log.Println("request", coll.CollectType) }