nodes split to meshviewernodes
This commit is contained in:
parent
bc525f2636
commit
dc47ab8719
|
@ -1,80 +1,101 @@
|
|||
package api
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"encoding/json"
|
||||
"github.com/julienschmidt/httprouter"
|
||||
"fmt"
|
||||
"github.com/FreifunkBremen/respond-collector/models"
|
||||
"github.com/julienschmidt/httprouter"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
type ApiAliases struct {
|
||||
aliases *models.Aliases
|
||||
config *models.Config
|
||||
nodes *models.Nodes
|
||||
config *models.Config
|
||||
nodes *models.Nodes
|
||||
}
|
||||
|
||||
func NewAliases (config *models.Config, router *httprouter.Router,prefix string,nodes *models.Nodes) {
|
||||
func NewAliases(config *models.Config, router *httprouter.Router, prefix string, nodes *models.Nodes) {
|
||||
api := &ApiAliases{
|
||||
aliases: models.NewAliases(config),
|
||||
nodes: nodes,
|
||||
config: config,
|
||||
nodes: nodes,
|
||||
config: config,
|
||||
}
|
||||
router.GET(prefix, api.GetAll)
|
||||
router.GET(prefix+"/ansible", api.AnsibleDiff)
|
||||
router.GET(prefix+"/cleanup", api.Cleanup)
|
||||
router.GET(prefix+"/auth", BasicAuth(api.Cleanup, []byte(config.Webserver.Api.Passphrase)))
|
||||
router.GET(prefix+"/alias/:nodeid", api.GetOne)
|
||||
router.POST(prefix+"/alias/:nodeid", BasicAuth(api.SaveOne,[]byte(config.Webserver.Api.Passphrase)))
|
||||
router.GET(prefix+"/auth", BasicAuth(api.Cleanup, []byte(config.Webserver.Api.Passphrase)))
|
||||
router.GET(prefix+"/alias/:nodeid", api.GetOne)
|
||||
router.POST(prefix+"/alias/:nodeid", BasicAuth(api.SaveOne, []byte(config.Webserver.Api.Passphrase)))
|
||||
}
|
||||
|
||||
// clean up the aliases by correct values in nodes
|
||||
func (api *ApiAliases) cleaner(){
|
||||
for key,alias := range api.aliases.List {
|
||||
if node := api.nodes.List[key]; node !=nil {
|
||||
if nodeinfo := node.Nodeinfo; nodeinfo !=nil {
|
||||
func (api *ApiAliases) cleaner() {
|
||||
for key, alias := range api.aliases.List {
|
||||
if node := api.nodes.List[key]; node != nil {
|
||||
if nodeinfo := node.Nodeinfo; nodeinfo != nil {
|
||||
//counter for the diffrent attribute
|
||||
count := 1
|
||||
count := 3
|
||||
if alias.Hostname == nodeinfo.Hostname {
|
||||
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
|
||||
if count <= 0 {
|
||||
delete(api.aliases.List,key)
|
||||
delete(api.aliases.List, key)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
func (api *ApiAliases) GetAll(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
|
||||
jsonOutput(w,r,api.aliases.List)
|
||||
jsonOutput(w, r, api.aliases.List)
|
||||
}
|
||||
|
||||
func (api *ApiAliases) GetOne(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
|
||||
if alias := api.aliases.List[ps.ByName("nodeid")]; alias !=nil{
|
||||
jsonOutput(w,r,alias)
|
||||
if alias := api.aliases.List[ps.ByName("nodeid")]; alias != nil {
|
||||
jsonOutput(w, r, alias)
|
||||
return
|
||||
}
|
||||
fmt.Fprint(w, "Not found: ", ps.ByName("nodeid"),"\n")
|
||||
fmt.Fprint(w, "Not found: ", ps.ByName("nodeid"), "\n")
|
||||
}
|
||||
|
||||
func (api *ApiAliases) SaveOne(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
|
||||
var alias models.Alias
|
||||
|
||||
err := json.NewDecoder(r.Body).Decode(&alias)
|
||||
if err != nil{
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
fmt.Fprint(w, "Decode: ", ps.ByName("nodeid"),"\n")
|
||||
fmt.Fprint(w, "Decode: ", ps.ByName("nodeid"), "\n")
|
||||
return
|
||||
}
|
||||
api.aliases.Update(ps.ByName("nodeid"),&alias)
|
||||
jsonOutput(w,r,alias)
|
||||
api.aliases.Update(ps.ByName("nodeid"), &alias)
|
||||
jsonOutput(w, r, alias)
|
||||
}
|
||||
|
||||
func (api *ApiAliases) Cleanup(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
|
||||
api.cleaner()
|
||||
jsonOutput(w,r,api.aliases.List)
|
||||
jsonOutput(w, r, api.aliases.List)
|
||||
}
|
||||
func (api *ApiAliases) AnsibleDiff(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
|
||||
api.cleaner()
|
||||
jsonOutput(w,r,models.GenerateAnsible(api.nodes,api.aliases.List))
|
||||
jsonOutput(w, r, models.GenerateAnsible(api.nodes, api.aliases.List))
|
||||
}
|
||||
|
|
16
api/nodes.go
16
api/nodes.go
|
@ -1,24 +1,24 @@
|
|||
package api
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"github.com/julienschmidt/httprouter"
|
||||
"github.com/FreifunkBremen/respond-collector/models"
|
||||
"github.com/julienschmidt/httprouter"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
type ApiNodes struct {
|
||||
config *models.Config
|
||||
nodes *models.Nodes
|
||||
config *models.Config
|
||||
nodes *models.Nodes
|
||||
}
|
||||
|
||||
func NewNodes (config *models.Config, router *httprouter.Router,prefix string,nodes *models.Nodes) {
|
||||
func NewNodes(config *models.Config, router *httprouter.Router, prefix string, nodes *models.Nodes) {
|
||||
api := &ApiNodes{
|
||||
nodes: nodes,
|
||||
nodes: nodes,
|
||||
config: config,
|
||||
}
|
||||
router.GET(prefix, api.GetAll)
|
||||
router.GET(prefix, api.GetAll)
|
||||
}
|
||||
|
||||
func (api *ApiNodes) GetAll(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
|
||||
jsonOutput(w,r,api.nodes.List)
|
||||
jsonOutput(w, r, api.nodes.List)
|
||||
}
|
||||
|
|
|
@ -3,20 +3,31 @@ package models
|
|||
import (
|
||||
"encoding/json"
|
||||
"io/ioutil"
|
||||
"sync"
|
||||
"log"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/FreifunkBremen/respond-collector/data"
|
||||
)
|
||||
|
||||
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
|
||||
type Aliases struct {
|
||||
List map[string]*Alias `json:"nodes"` // the current nodemap, indexed by node ID
|
||||
config *Config
|
||||
List map[string]*Alias `json:"nodes"` // the current nodemap, indexed by node ID
|
||||
config *Config
|
||||
sync.Mutex
|
||||
}
|
||||
|
||||
// NewNodes create Nodes structs
|
||||
func NewAliases(config *Config) *Aliases {
|
||||
aliases := &Aliases{
|
||||
|
|
|
@ -2,27 +2,39 @@ package models
|
|||
|
||||
type Ansible struct {
|
||||
Nodes []string `json:"nodes"`
|
||||
Meta struct {
|
||||
Meta struct {
|
||||
HostVars []*AnsibleHostVars `json:"hostvars"`
|
||||
} `json:"_meta"`
|
||||
}
|
||||
type AnsibleHostVars struct {
|
||||
Address string `json:"ansible_ssh_host"`
|
||||
Hostname string `json:"node_name"`
|
||||
Address string `json:"ansible_ssh_host"`
|
||||
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{
|
||||
ansible := &Ansible{Nodes:make([]string,0)}
|
||||
for nodeid,alias := range aliases{
|
||||
func GenerateAnsible(nodes *Nodes, aliases map[string]*Alias) *Ansible {
|
||||
ansible := &Ansible{Nodes: make([]string, 0)}
|
||||
for nodeid, alias := range aliases {
|
||||
if node := nodes.List[nodeid]; node != nil {
|
||||
|
||||
ansible.Nodes = append(ansible.Nodes,nodeid)
|
||||
ansible.Nodes = append(ansible.Nodes, nodeid)
|
||||
|
||||
vars := &AnsibleHostVars{
|
||||
Address: node.Nodeinfo.Network.Addresses[0],
|
||||
Hostname: alias.Hostname,
|
||||
Address: node.Nodeinfo.Network.Addresses[0],
|
||||
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""`
|
||||
}
|
123
models/nodes.go
123
models/nodes.go
|
@ -10,21 +10,17 @@ import (
|
|||
|
||||
"github.com/FreifunkBremen/respond-collector/data"
|
||||
"github.com/FreifunkBremen/respond-collector/jsontime"
|
||||
"github.com/FreifunkBremen/respond-collector/meshviewer"
|
||||
)
|
||||
|
||||
// Node struct
|
||||
type Node struct {
|
||||
Firstseen jsontime.Time `json:"firstseen"`
|
||||
Lastseen jsontime.Time `json:"lastseen"`
|
||||
Flags *Flags `json:"flags,omitempty"`
|
||||
Statistics *MeshviewerStatistics `json:"statistics"`
|
||||
Nodeinfo *data.NodeInfo `json:"nodeinfo"`
|
||||
Neighbours *data.Neighbours `json:"-"`
|
||||
}
|
||||
|
||||
type Flags struct {
|
||||
Online bool `json:"online"`
|
||||
Gateway bool `json:"gateway"`
|
||||
Firstseen jsontime.Time `json:"firstseen"`
|
||||
Lastseen jsontime.Time `json:"lastseen"`
|
||||
Flags *meshviewer.Flags `json:"flags,omitempty"`
|
||||
Statistics *data.Statistics `json:"statistics"`
|
||||
Nodeinfo *data.NodeInfo `json:"nodeinfo"`
|
||||
Neighbours *data.Neighbours `json:"-"`
|
||||
}
|
||||
|
||||
// Nodes struct: cache DB of Node's structs
|
||||
|
@ -62,8 +58,8 @@ func (nodes *Nodes) Update(nodeID string, res *data.ResponseData) {
|
|||
if node == nil {
|
||||
node = &Node{
|
||||
Firstseen: now,
|
||||
Flags: &Flags{
|
||||
Online: true,
|
||||
Flags: &meshviewer.Flags{
|
||||
Online: true,
|
||||
Gateway: false,
|
||||
},
|
||||
}
|
||||
|
@ -73,7 +69,7 @@ func (nodes *Nodes) Update(nodeID string, res *data.ResponseData) {
|
|||
|
||||
node.Lastseen = now
|
||||
|
||||
if node.Flags !=nil {
|
||||
if node.Flags != nil {
|
||||
node.Flags.Online = true
|
||||
}
|
||||
|
||||
|
@ -90,22 +86,45 @@ func (nodes *Nodes) Update(nodeID string, res *data.ResponseData) {
|
|||
|
||||
// Update statistics
|
||||
if val := res.Statistics; val != nil {
|
||||
node.Statistics = &MeshviewerStatistics{
|
||||
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
|
||||
node.Statistics = val
|
||||
}
|
||||
}
|
||||
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
|
||||
func (nodes *Nodes) worker() {
|
||||
|
@ -115,21 +134,17 @@ func (nodes *Nodes) worker() {
|
|||
log.Println("saving", len(nodes.List), "nodes")
|
||||
nodes.Timestamp = jsontime.Now()
|
||||
nodes.Lock()
|
||||
//
|
||||
//
|
||||
// set node as offline (without statistics)
|
||||
for _,node := range nodes.List {
|
||||
if node.Statistics != nil && node.Lastseen.Unix()+int64(1000*nodes.config.Respondd.CollectInterval) < nodes.Timestamp.Unix() {
|
||||
node.Statistics = &MeshviewerStatistics{
|
||||
NodeId: node.Statistics.NodeId,
|
||||
Clients: 0,
|
||||
}
|
||||
for _, node := range nodes.List {
|
||||
if node.Statistics != nil && node.Lastseen.Unix()+int64(5*nodes.config.Respondd.CollectInterval) < nodes.Timestamp.Unix() {
|
||||
if node.Flags != nil {
|
||||
node.Flags.Online = false
|
||||
}
|
||||
}
|
||||
}
|
||||
// serialize nodes
|
||||
save(nodes, nodes.config.Nodes.NodesPath)
|
||||
save(nodes.GetMeshviewer(), nodes.config.Nodes.NodesPath)
|
||||
|
||||
if path := nodes.config.Nodes.GraphsPath; path != "" {
|
||||
save(nodes.BuildGraph(), path)
|
||||
|
@ -143,8 +158,40 @@ func (nodes *Nodes) load() {
|
|||
path := nodes.config.Nodes.NodesPath
|
||||
log.Println("loading", path)
|
||||
|
||||
if data, err := ioutil.ReadFile(path); err == nil {
|
||||
if err := json.Unmarshal(data, nodes); err == nil {
|
||||
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,
|
||||
}
|
||||
}
|
||||
log.Println("loaded", len(nodes.List), "nodes")
|
||||
} else {
|
||||
log.Println("failed to unmarshal nodes:", err)
|
||||
|
|
Loading…
Reference in New Issue