nodes split to meshviewernodes
This commit is contained in:
parent
bc525f2636
commit
dc47ab8719
|
@ -1,11 +1,11 @@
|
||||||
package api
|
package api
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"net/http"
|
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"github.com/julienschmidt/httprouter"
|
"fmt"
|
||||||
"github.com/FreifunkBremen/respond-collector/models"
|
"github.com/FreifunkBremen/respond-collector/models"
|
||||||
|
"github.com/julienschmidt/httprouter"
|
||||||
|
"net/http"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ApiAliases struct {
|
type ApiAliases struct {
|
||||||
|
@ -27,16 +27,37 @@ func NewAliases (config *models.Config, router *httprouter.Router,prefix string,
|
||||||
router.GET(prefix+"/alias/:nodeid", api.GetOne)
|
router.GET(prefix+"/alias/:nodeid", api.GetOne)
|
||||||
router.POST(prefix+"/alias/:nodeid", BasicAuth(api.SaveOne, []byte(config.Webserver.Api.Passphrase)))
|
router.POST(prefix+"/alias/:nodeid", BasicAuth(api.SaveOne, []byte(config.Webserver.Api.Passphrase)))
|
||||||
}
|
}
|
||||||
|
|
||||||
// clean up the aliases by correct values in nodes
|
// clean up the aliases by correct values in nodes
|
||||||
func (api *ApiAliases) cleaner() {
|
func (api *ApiAliases) cleaner() {
|
||||||
for key, alias := range api.aliases.List {
|
for key, alias := range api.aliases.List {
|
||||||
if node := api.nodes.List[key]; node != nil {
|
if node := api.nodes.List[key]; node != nil {
|
||||||
if nodeinfo := node.Nodeinfo; nodeinfo != nil {
|
if nodeinfo := node.Nodeinfo; nodeinfo != nil {
|
||||||
//counter for the diffrent attribute
|
//counter for the diffrent attribute
|
||||||
count := 1
|
count := 3
|
||||||
if alias.Hostname == nodeinfo.Hostname {
|
if alias.Hostname == nodeinfo.Hostname {
|
||||||
count -= 1
|
count -= 1
|
||||||
}
|
}
|
||||||
|
if alias.Location.Latitude == nodeinfo.Location.Latitude {
|
||||||
|
count -= 1
|
||||||
|
}
|
||||||
|
if alias.Location.Longtitude == nodeinfo.Location.Longtitude {
|
||||||
|
count -= 1
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
if alias.Freq24.TxPower == nodeinfo.Freq24.TxPower {
|
||||||
|
count -= 1
|
||||||
|
}
|
||||||
|
if alias.Freq24.Channel == nodeinfo.Freq24.Channel {
|
||||||
|
count -= 1
|
||||||
|
}
|
||||||
|
if alias.Freq5.TxPower == nodeinfo.Freq5.TxPower {
|
||||||
|
count -= 1
|
||||||
|
}
|
||||||
|
if alias.Freq5.Channel == nodeinfo.Freq5.Channel {
|
||||||
|
count -= 1
|
||||||
|
}
|
||||||
|
*/
|
||||||
//delete element
|
//delete element
|
||||||
if count <= 0 {
|
if count <= 0 {
|
||||||
delete(api.aliases.List, key)
|
delete(api.aliases.List, key)
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
package api
|
package api
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net/http"
|
|
||||||
"github.com/julienschmidt/httprouter"
|
|
||||||
"github.com/FreifunkBremen/respond-collector/models"
|
"github.com/FreifunkBremen/respond-collector/models"
|
||||||
|
"github.com/julienschmidt/httprouter"
|
||||||
|
"net/http"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ApiNodes struct {
|
type ApiNodes struct {
|
||||||
|
|
|
@ -3,20 +3,31 @@ package models
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"sync"
|
|
||||||
"log"
|
"log"
|
||||||
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/FreifunkBremen/respond-collector/data"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Alias struct {
|
type Alias struct {
|
||||||
Hostname string `json:"hostname"`
|
Hostname string `json:"hostname"`
|
||||||
|
Location *data.Location `json:"location"`
|
||||||
|
Freq24 *Frequence `json:"freq24"`
|
||||||
|
Freq5 *Frequence `json:"freq5"`
|
||||||
}
|
}
|
||||||
|
type Frequence struct {
|
||||||
|
TxPower int `json:"txpower"`
|
||||||
|
Channel int `json:"channel"`
|
||||||
|
}
|
||||||
|
|
||||||
// Nodes struct: cache DB of Node's structs
|
// Nodes struct: cache DB of Node's structs
|
||||||
type Aliases struct {
|
type Aliases struct {
|
||||||
List map[string]*Alias `json:"nodes"` // the current nodemap, indexed by node ID
|
List map[string]*Alias `json:"nodes"` // the current nodemap, indexed by node ID
|
||||||
config *Config
|
config *Config
|
||||||
sync.Mutex
|
sync.Mutex
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewNodes create Nodes structs
|
// NewNodes create Nodes structs
|
||||||
func NewAliases(config *Config) *Aliases {
|
func NewAliases(config *Config) *Aliases {
|
||||||
aliases := &Aliases{
|
aliases := &Aliases{
|
||||||
|
|
|
@ -9,6 +9,12 @@ type Ansible struct {
|
||||||
type AnsibleHostVars struct {
|
type AnsibleHostVars struct {
|
||||||
Address string `json:"ansible_ssh_host"`
|
Address string `json:"ansible_ssh_host"`
|
||||||
Hostname string `json:"node_name"`
|
Hostname string `json:"node_name"`
|
||||||
|
Channel24 int `json:"radio24_channel"`
|
||||||
|
TxPower24 int `json:"radio24_txpower"`
|
||||||
|
Channel5 int `json:"radio5_channel"`
|
||||||
|
TxPower5 int `json:"radio5_txpower"`
|
||||||
|
GeoLatitude float64 `json:"geo_latitude"`
|
||||||
|
GeoLongitude float64 `json:"geo_longitude"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func GenerateAnsible(nodes *Nodes, aliases map[string]*Alias) *Ansible {
|
func GenerateAnsible(nodes *Nodes, aliases map[string]*Alias) *Ansible {
|
||||||
|
@ -21,6 +27,12 @@ func GenerateAnsible(nodes *Nodes,aliases map[string]*Alias) *Ansible{
|
||||||
vars := &AnsibleHostVars{
|
vars := &AnsibleHostVars{
|
||||||
Address: node.Nodeinfo.Network.Addresses[0],
|
Address: node.Nodeinfo.Network.Addresses[0],
|
||||||
Hostname: alias.Hostname,
|
Hostname: alias.Hostname,
|
||||||
|
Channel24: alias.Freq24.Channel,
|
||||||
|
Channel5: alias.Freq5.Channel,
|
||||||
|
TxPower24: alias.Freq24.TxPower,
|
||||||
|
TxPower5: alias.Freq5.TxPower,
|
||||||
|
GeoLatitude: alias.Location.Latitude,
|
||||||
|
GeoLongitude: alias.Location.Longtitude,
|
||||||
}
|
}
|
||||||
ansible.Meta.HostVars = append(ansible.Meta.HostVars, vars)
|
ansible.Meta.HostVars = append(ansible.Meta.HostVars, vars)
|
||||||
|
|
||||||
|
|
|
@ -1,26 +0,0 @@
|
||||||
package models
|
|
||||||
|
|
||||||
import "github.com/FreifunkBremen/respond-collector/data"
|
|
||||||
|
|
||||||
type MeshviewerStatistics struct {
|
|
||||||
NodeId string `json:"node_id"`
|
|
||||||
Clients uint32 `json:"clients"`
|
|
||||||
RootFsUsage float64 `json:"rootfs_usage,omitempty""`
|
|
||||||
LoadAverage float64 `json:"loadavg,omitempty""`
|
|
||||||
Memory data.Memory `json:"memory,omitempty""`
|
|
||||||
Uptime float64 `json:"uptime,omitempty""`
|
|
||||||
Idletime float64 `json:"idletime,omitempty""`
|
|
||||||
Gateway string `json:"gateway,omitempty"`
|
|
||||||
Processes struct {
|
|
||||||
Total uint32 `json:"total"`
|
|
||||||
Running uint32 `json:"running"`
|
|
||||||
} `json:"processes,omitempty""`
|
|
||||||
MeshVpn *data.MeshVPN `json:"mesh_vpn,omitempty"`
|
|
||||||
Traffic struct {
|
|
||||||
Tx *data.Traffic `json:"tx"`
|
|
||||||
Rx *data.Traffic `json:"rx"`
|
|
||||||
Forward *data.Traffic `json:"forward"`
|
|
||||||
MgmtTx *data.Traffic `json:"mgmt_tx"`
|
|
||||||
MgmtRx *data.Traffic `json:"mgmt_rx"`
|
|
||||||
} `json:"traffic,omitempty""`
|
|
||||||
}
|
|
105
models/nodes.go
105
models/nodes.go
|
@ -10,23 +10,19 @@ import (
|
||||||
|
|
||||||
"github.com/FreifunkBremen/respond-collector/data"
|
"github.com/FreifunkBremen/respond-collector/data"
|
||||||
"github.com/FreifunkBremen/respond-collector/jsontime"
|
"github.com/FreifunkBremen/respond-collector/jsontime"
|
||||||
|
"github.com/FreifunkBremen/respond-collector/meshviewer"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Node struct
|
// Node struct
|
||||||
type Node struct {
|
type Node struct {
|
||||||
Firstseen jsontime.Time `json:"firstseen"`
|
Firstseen jsontime.Time `json:"firstseen"`
|
||||||
Lastseen jsontime.Time `json:"lastseen"`
|
Lastseen jsontime.Time `json:"lastseen"`
|
||||||
Flags *Flags `json:"flags,omitempty"`
|
Flags *meshviewer.Flags `json:"flags,omitempty"`
|
||||||
Statistics *MeshviewerStatistics `json:"statistics"`
|
Statistics *data.Statistics `json:"statistics"`
|
||||||
Nodeinfo *data.NodeInfo `json:"nodeinfo"`
|
Nodeinfo *data.NodeInfo `json:"nodeinfo"`
|
||||||
Neighbours *data.Neighbours `json:"-"`
|
Neighbours *data.Neighbours `json:"-"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type Flags struct {
|
|
||||||
Online bool `json:"online"`
|
|
||||||
Gateway bool `json:"gateway"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// Nodes struct: cache DB of Node's structs
|
// Nodes struct: cache DB of Node's structs
|
||||||
type Nodes struct {
|
type Nodes struct {
|
||||||
Version int `json:"version"`
|
Version int `json:"version"`
|
||||||
|
@ -62,7 +58,7 @@ func (nodes *Nodes) Update(nodeID string, res *data.ResponseData) {
|
||||||
if node == nil {
|
if node == nil {
|
||||||
node = &Node{
|
node = &Node{
|
||||||
Firstseen: now,
|
Firstseen: now,
|
||||||
Flags: &Flags{
|
Flags: &meshviewer.Flags{
|
||||||
Online: true,
|
Online: true,
|
||||||
Gateway: false,
|
Gateway: false,
|
||||||
},
|
},
|
||||||
|
@ -90,21 +86,44 @@ func (nodes *Nodes) Update(nodeID string, res *data.ResponseData) {
|
||||||
|
|
||||||
// Update statistics
|
// Update statistics
|
||||||
if val := res.Statistics; val != nil {
|
if val := res.Statistics; val != nil {
|
||||||
node.Statistics = &MeshviewerStatistics{
|
node.Statistics = val
|
||||||
NodeId: val.NodeId,
|
|
||||||
Clients: 0,
|
|
||||||
Gateway: val.Gateway,
|
|
||||||
RootFsUsage: val.RootFsUsage,
|
|
||||||
LoadAverage: val.LoadAverage,
|
|
||||||
Memory: val.Memory,
|
|
||||||
Uptime: val.Uptime,
|
|
||||||
Idletime: val.Idletime,
|
|
||||||
Processes: val.Processes,
|
|
||||||
MeshVpn: val.MeshVpn,
|
|
||||||
Traffic: val.Traffic,
|
|
||||||
}
|
}
|
||||||
node.Statistics.Clients = val.Clients.Total
|
|
||||||
}
|
}
|
||||||
|
func (nodes *Nodes) GetMeshviewer() *meshviewer.Nodes {
|
||||||
|
meshviewerNodes := &meshviewer.Nodes{
|
||||||
|
Version: nodes.Version,
|
||||||
|
List: make(map[string]*meshviewer.Node),
|
||||||
|
Timestamp: nodes.Timestamp,
|
||||||
|
}
|
||||||
|
for nodeID, _ := range nodes.List {
|
||||||
|
meshviewerNodes.Lock()
|
||||||
|
node, _ := meshviewerNodes.List[nodeID]
|
||||||
|
|
||||||
|
if node == nil {
|
||||||
|
node = &meshviewer.Node{
|
||||||
|
Firstseen: nodes.List[nodeID].Firstseen,
|
||||||
|
Lastseen: nodes.List[nodeID].Lastseen,
|
||||||
|
Flags: nodes.List[nodeID].Flags,
|
||||||
|
Nodeinfo: nodes.List[nodeID].Nodeinfo,
|
||||||
|
}
|
||||||
|
meshviewerNodes.List[nodeID] = node
|
||||||
|
}
|
||||||
|
meshviewerNodes.Unlock()
|
||||||
|
node.Statistics = &meshviewer.Statistics{
|
||||||
|
NodeId: nodes.List[nodeID].Statistics.NodeId,
|
||||||
|
Clients: nodes.List[nodeID].Statistics.Clients.Total,
|
||||||
|
Gateway: nodes.List[nodeID].Statistics.Gateway,
|
||||||
|
RootFsUsage: nodes.List[nodeID].Statistics.RootFsUsage,
|
||||||
|
LoadAverage: nodes.List[nodeID].Statistics.LoadAverage,
|
||||||
|
Memory: nodes.List[nodeID].Statistics.Memory,
|
||||||
|
Uptime: nodes.List[nodeID].Statistics.Uptime,
|
||||||
|
Idletime: nodes.List[nodeID].Statistics.Idletime,
|
||||||
|
Processes: nodes.List[nodeID].Statistics.Processes,
|
||||||
|
MeshVpn: nodes.List[nodeID].Statistics.MeshVpn,
|
||||||
|
Traffic: nodes.List[nodeID].Statistics.Traffic,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return meshviewerNodes
|
||||||
}
|
}
|
||||||
|
|
||||||
// Periodically saves the cached DB to json file
|
// Periodically saves the cached DB to json file
|
||||||
|
@ -118,18 +137,14 @@ func (nodes *Nodes) worker() {
|
||||||
//
|
//
|
||||||
// set node as offline (without statistics)
|
// set node as offline (without statistics)
|
||||||
for _, node := range nodes.List {
|
for _, node := range nodes.List {
|
||||||
if node.Statistics != nil && node.Lastseen.Unix()+int64(1000*nodes.config.Respondd.CollectInterval) < nodes.Timestamp.Unix() {
|
if node.Statistics != nil && node.Lastseen.Unix()+int64(5*nodes.config.Respondd.CollectInterval) < nodes.Timestamp.Unix() {
|
||||||
node.Statistics = &MeshviewerStatistics{
|
|
||||||
NodeId: node.Statistics.NodeId,
|
|
||||||
Clients: 0,
|
|
||||||
}
|
|
||||||
if node.Flags != nil {
|
if node.Flags != nil {
|
||||||
node.Flags.Online = false
|
node.Flags.Online = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// serialize nodes
|
// serialize nodes
|
||||||
save(nodes, nodes.config.Nodes.NodesPath)
|
save(nodes.GetMeshviewer(), nodes.config.Nodes.NodesPath)
|
||||||
|
|
||||||
if path := nodes.config.Nodes.GraphsPath; path != "" {
|
if path := nodes.config.Nodes.GraphsPath; path != "" {
|
||||||
save(nodes.BuildGraph(), path)
|
save(nodes.BuildGraph(), path)
|
||||||
|
@ -143,8 +158,40 @@ func (nodes *Nodes) load() {
|
||||||
path := nodes.config.Nodes.NodesPath
|
path := nodes.config.Nodes.NodesPath
|
||||||
log.Println("loading", path)
|
log.Println("loading", path)
|
||||||
|
|
||||||
if data, err := ioutil.ReadFile(path); err == nil {
|
if filedata, err := ioutil.ReadFile(path); err == nil {
|
||||||
if err := json.Unmarshal(data, nodes); 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,
|
||||||
|
}
|
||||||
|
}
|
||||||
log.Println("loaded", len(nodes.List), "nodes")
|
log.Println("loaded", len(nodes.List), "nodes")
|
||||||
} else {
|
} else {
|
||||||
log.Println("failed to unmarshal nodes:", err)
|
log.Println("failed to unmarshal nodes:", err)
|
||||||
|
|
Loading…
Reference in New Issue