nodes split to meshviewernodes
This commit is contained in:
		
							parent
							
								
									bc525f2636
								
							
						
					
					
						commit
						dc47ab8719
					
				| @ -1,11 +1,11 @@ | ||||
| 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 { | ||||
| @ -14,7 +14,7 @@ type ApiAliases struct { | ||||
| 	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, | ||||
| @ -25,56 +25,77 @@ func NewAliases (config *models.Config, router *httprouter.Router,prefix string, | ||||
| 	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.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)) | ||||
| } | ||||
|  | ||||
| @ -1,9 +1,9 @@ | ||||
| package api | ||||
| 
 | ||||
| import ( | ||||
| 	"net/http" | ||||
| 	"github.com/julienschmidt/httprouter" | ||||
| 	"github.com/FreifunkBremen/respond-collector/models" | ||||
| 	"github.com/julienschmidt/httprouter" | ||||
| 	"net/http" | ||||
| ) | ||||
| 
 | ||||
| type ApiNodes struct { | ||||
| @ -11,7 +11,7 @@ type ApiNodes struct { | ||||
| 	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, | ||||
| 		config: config, | ||||
| @ -20,5 +20,5 @@ func NewNodes (config *models.Config, router *httprouter.Router,prefix string,no | ||||
| } | ||||
| 
 | ||||
| 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"` | ||||
| 	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 | ||||
| 	sync.Mutex | ||||
| } | ||||
| 
 | ||||
| // NewNodes create Nodes structs
 | ||||
| func NewAliases(config *Config) *Aliases { | ||||
| 	aliases := &Aliases{ | ||||
|  | ||||
| @ -9,20 +9,32 @@ type Ansible struct { | ||||
| type AnsibleHostVars struct { | ||||
| 	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, | ||||
| 				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""` | ||||
| } | ||||
							
								
								
									
										111
									
								
								models/nodes.go
									
									
									
									
									
								
							
							
						
						
									
										111
									
								
								models/nodes.go
									
									
									
									
									
								
							| @ -10,23 +10,19 @@ 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"` | ||||
| 	Flags      *meshviewer.Flags `json:"flags,omitempty"` | ||||
| 	Statistics *data.Statistics  `json:"statistics"` | ||||
| 	Nodeinfo   *data.NodeInfo    `json:"nodeinfo"` | ||||
| 	Neighbours *data.Neighbours  `json:"-"` | ||||
| } | ||||
| 
 | ||||
| type Flags struct { | ||||
| 	Online bool	`json:"online"` | ||||
| 	Gateway bool	`json:"gateway"` | ||||
| } | ||||
| 
 | ||||
| // Nodes struct: cache DB of Node's structs
 | ||||
| type Nodes struct { | ||||
| 	Version   int              `json:"version"` | ||||
| @ -62,7 +58,7 @@ func (nodes *Nodes) Update(nodeID string, res *data.ResponseData) { | ||||
| 	if node == nil { | ||||
| 		node = &Node{ | ||||
| 			Firstseen: now, | ||||
| 			Flags: &Flags{ | ||||
| 			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,21 +86,44 @@ 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 = val | ||||
| 	} | ||||
| 		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
 | ||||
| @ -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
	
	Block a user