sql rewrite

This commit is contained in:
Martin/Geno 2018-07-26 14:14:23 +02:00
parent 50a109dee0
commit 21c398ca42
No known key found for this signature in database
GPG Key ID: 9D7D3C6BFF600C6A
15 changed files with 188 additions and 238 deletions

View File

@ -1,4 +1,5 @@
state_path = "/tmp/freifunkmanager.json"
db_type = "sqlite3"
db_connection = "/tmp/freifunkmanager.db"
webserver_bind = ":8080"
webroot = "./webroot"
@ -6,14 +7,15 @@ webroot = "./webroot"
secret = "passw0rd"
ssh_key = "~/.ssh/id_rsa"
ssh_interface = "wlp4s0"
ssh_ipaddress_suffix = "fe80:"
ssh_ipaddress_suffix = "fd2f:"
ssh_timeout = "1m"
ssh_config_all = false
ssh_yanic_update = true
# enable receiving
yanic_enable = true
# yanic_synchronize = "1m"
yanic_collect_interval = "1m"
yanic_collect_interval = "10s"
[yanic]
ifname = "wlp4s0"
@ -22,4 +24,4 @@ ifname = "wlp4s0"
# ifname = "lo"
# ip_address = "::1"
# send_no_request = no
# port
# port = 1001

41
main.go
View File

@ -8,15 +8,16 @@ import (
"syscall"
"time"
"dev.sum7.eu/genofire/golang-lib/file"
"github.com/NYTimes/gziphandler"
"github.com/genofire/golang-lib/file"
httpLib "github.com/genofire/golang-lib/http"
"github.com/genofire/golang-lib/worker"
log "github.com/sirupsen/logrus"
respondYanic "github.com/FreifunkBremen/yanic/respond"
runtimeYanic "github.com/FreifunkBremen/yanic/runtime"
"github.com/jinzhu/gorm"
_ "github.com/jinzhu/gorm/dialects/sqlite"
"github.com/FreifunkBremen/freifunkmanager/runtime"
"github.com/FreifunkBremen/freifunkmanager/ssh"
"github.com/FreifunkBremen/freifunkmanager/websocket"
@ -25,7 +26,6 @@ import (
var (
configFile string
config = &runtime.Config{}
nodes *runtime.Nodes
collector *respondYanic.Collector
verbose bool
)
@ -44,19 +44,18 @@ func main() {
log.Info("starting...")
db, err := gorm.Open(config.DatabaseType, config.DatabaseConnection)
if err != nil {
log.Panic("failed to connect database")
}
db.AutoMigrate(&runtime.Node{}, &websocket.Auth{})
sshmanager := ssh.NewManager(config.SSHPrivateKey, config.SSHTimeout.Duration)
nodes = runtime.NewNodes(config.StatePath, config.SSHInterface, sshmanager)
nodesSaveWorker := worker.NewWorker(time.Duration(3)*time.Second, nodes.Saver)
nodesUpdateWorker := worker.NewWorker(time.Duration(3)*time.Minute, nodes.Updater)
nodesYanic := runtimeYanic.NewNodes(&runtimeYanic.NodesConfig{})
db := runtime.NewYanicDB(nodes, config.SSHIPAddressSuffix)
go nodesSaveWorker.Start()
go nodesUpdateWorker.Start()
ws := websocket.NewWebsocketServer(config.Secret, db, nodesYanic)
ws := websocket.NewWebsocketServer(config.Secret, nodes)
nodes.AddNotifyStats(ws.SendStats)
nodes.AddNotifyNode(ws.SendNode)
yanic := runtime.NewYanicDB(db, sshmanager, ws.SendNode, ws.SendStats, config.SSHIPAddressSuffix)
if config.YanicEnable {
if duration := config.YanicSynchronize.Duration; duration > 0 {
@ -65,7 +64,7 @@ func main() {
log.Printf("delaying %0.1f seconds", delay.Seconds())
time.Sleep(delay)
}
collector = respondYanic.NewCollector(db, nodesYanic, make(map[string][]string), []respondYanic.InterfaceConfig{config.Yanic})
collector = respondYanic.NewCollector(yanic, nodesYanic, make(map[string][]string), []respondYanic.InterfaceConfig{config.Yanic})
if duration := config.YanicCollectInterval.Duration; duration > 0 {
collector.Start(config.YanicCollectInterval.Duration)
}
@ -74,12 +73,6 @@ func main() {
}
// Startwebserver
http.HandleFunc("/nodes", func(w http.ResponseWriter, r *http.Request) {
httpLib.Write(w, nodes)
})
http.HandleFunc("/stats", func(w http.ResponseWriter, r *http.Request) {
httpLib.Write(w, nodes.Statistics)
})
http.Handle("/", gziphandler.GzipHandler(http.FileServer(http.Dir(config.Webroot))))
srv := &http.Server{
@ -99,12 +92,14 @@ func main() {
signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)
sig := <-sigs
log.Debug("stop recieve:", sig)
ws.Close()
// Stop services
srv.Close()
nodesSaveWorker.Close()
nodesUpdateWorker.Close()
db.Close()
log.Info("stop freifunkmanager")
log.Info("stop recieve:", sig)
}

View File

@ -9,7 +9,8 @@ import (
//config file of this daemon (for more the config_example.conf in git repository)
type Config struct {
// prevent crashes
StatePath string `toml:"state_path"`
DatabaseType string `toml:"db_type"`
DatabaseConnection string `toml:"db_connection"`
// address on which the api and static content webserver runs
WebserverBind string `toml:"webserver_bind"`
@ -21,7 +22,6 @@ type Config struct {
// SSH private key
SSHPrivateKey string `toml:"ssh_key"`
SSHInterface string `toml:"ssh_interface"`
SSHIPAddressSuffix string `toml:"ssh_ipaddress_suffix"`
SSHTimeout duration.Duration `toml:"ssh_timeout"`

View File

@ -1,7 +1,6 @@
package runtime
import (
"bytes"
"net"
"strings"
@ -11,14 +10,15 @@ import (
)
type Node struct {
Lastseen jsontime.Time `json:"lastseen" mapstructure:"-"`
NodeID string `json:"node_id" mapstructure:"node_id"`
Hostname string `json:"hostname"`
Location yanicData.Location `json:"location"`
Wireless yanicData.Wireless `json:"wireless"`
Owner string `json:"owner"`
Address net.IP `json:"ip" mapstructure:"-"`
Stats struct {
Lastseen jsontime.Time `json:"lastseen" mapstructure:"-"`
NodeID string `json:"node_id" gorm:"primary_key" mapstructure:"node_id"`
Hostname string `json:"hostname"`
Location yanicData.Location `json:"location" gorm:"embedded;embedded_prefix:location_"`
Wireless yanicData.Wireless `json:"wireless" gorm:"embedded;embedded_prefix:wireless_"`
Owner string `json:"owner"`
Blacklist bool `json:"blacklist" gorm:"-" mapstructure:"-"`
Address string `json:"ip" mapstructure:"-"`
Stats struct {
Wireless yanicData.WirelessStatistics `json:"wireless"`
Clients yanicData.Clients `json:"clients"`
} `json:"statistics" mapstructure:"-"`
@ -35,8 +35,8 @@ func NewNode(nodeOrigin *yanicRuntime.Node, ipPrefix string) *Node {
continue
}
ipAddr := net.ParseIP(ip)
if node.Address == nil || ipAddr.IsGlobalUnicast() {
node.Address = ipAddr
if node.Address == "" || ipAddr.IsGlobalUnicast() {
node.Address = ipAddr.String()
}
}
if owner := nodeinfo.Owner; owner != nil {
@ -56,14 +56,14 @@ func NewNode(nodeOrigin *yanicRuntime.Node, ipPrefix string) *Node {
}
return nil
}
func (n *Node) GetAddress(iface string) net.TCPAddr {
return net.TCPAddr{IP: n.Address, Port: 22, Zone: iface}
func (n *Node) GetAddress() net.TCPAddr {
return net.TCPAddr{IP: net.ParseIP(n.Address), Port: 22}
}
func (n *Node) Update(node *yanicRuntime.Node) {
if nodeinfo := node.Nodeinfo; nodeinfo != nil {
n.Hostname = nodeinfo.Hostname
n.NodeID = nodeinfo.NodeID
n.Address = node.Address.IP
n.Address = node.Address.IP.String()
if owner := nodeinfo.Owner; owner != nil {
n.Owner = owner.Contact
@ -80,7 +80,7 @@ func (n *Node) IsEqual(node *Node) bool {
if n.NodeID != node.NodeID {
return false
}
if !bytes.Equal(n.Address, node.Address) {
if n.Address != node.Address {
return false
}
if n.Hostname != node.Hostname {

View File

@ -9,30 +9,27 @@ import (
"github.com/FreifunkBremen/freifunkmanager/ssh"
)
func (n *Node) SSHUpdate(sshmgmt *ssh.Manager, iface string, oldnode *Node) {
addr := n.GetAddress(iface)
client, err := sshmgmt.ConnectTo(addr)
func (n *Node) SSHUpdate(sshmgmt *ssh.Manager, oldnode *Node) {
client, err := sshmgmt.ConnectTo(n.GetAddress())
if err != nil {
return
}
defer client.Close()
if oldnode == nil || n.Hostname != oldnode.Hostname {
ssh.Execute(n.Address.String(), client, fmt.Sprintf(`
ssh.Execute(n.Address, client, fmt.Sprintf(`
uci set system.@system[0].hostname='%s';
uci set wireless.priv_radio0.ssid="offline-$(uci get system.@system[0].hostname)";
uci set wireless.priv_radio1.ssid="offline-$(uci get system.@system[0].hostname)";
uci commit; echo $(uci get system.@system[0].hostname) > /proc/sys/kernel/hostname;`,
n.Hostname))
}
if oldnode == nil || n.Owner != oldnode.Owner {
ssh.Execute(n.Address.String(), client, fmt.Sprintf(`
ssh.Execute(n.Address, client, fmt.Sprintf(`
uci set gluon-node-info.@owner[0].contact='%s';
uci commit gluon-node-info;`,
n.Owner))
}
if oldnode == nil || !locationEqual(n.Location, oldnode.Location) {
ssh.Execute(n.Address.String(), client, fmt.Sprintf(`
ssh.Execute(n.Address, client, fmt.Sprintf(`
uci set gluon-node-info.@location[0].latitude='%f';
uci set gluon-node-info.@location[0].longitude='%f';
uci set gluon-node-info.@location[0].share_location=1;
@ -43,13 +40,13 @@ func (n *Node) SSHUpdate(sshmgmt *ssh.Manager, iface string, oldnode *Node) {
runWifi := false
defer func() {
if runWifi {
ssh.Execute(n.Address.String(), client, "wifi")
ssh.Execute(n.Address, client, "wifi")
// send warning for running wifi, because it kicks clients from node
log.Warn("[cmd] wifi ", n.NodeID)
}
}()
result, err := ssh.Run(n.Address.String(), client, `
result, err := ssh.Run(n.Address, client, `
if [ "$(uci get wireless.radio0.hwmode | grep -c g)" -ne 0 ]; then
echo "radio0";
elif [ "$(uci get wireless.radio1.hwmode | grep -c g)" -ne 0 ]; then
@ -60,16 +57,16 @@ func (n *Node) SSHUpdate(sshmgmt *ssh.Manager, iface string, oldnode *Node) {
}
radio := ssh.SSHResultToString(result)
ch := GetChannel(n.Wireless.Channel24)
if radio != "" || ch == nil {
if radio != "" && ch != nil {
if oldnode == nil || n.Wireless.TxPower24 != oldnode.Wireless.TxPower24 {
ssh.Execute(n.Address.String(), client, fmt.Sprintf(`
ssh.Execute(n.Address, client, fmt.Sprintf(`
uci set wireless.%s.txpower='%d';
uci commit wireless;`,
radio, n.Wireless.TxPower24))
runWifi = true
}
if oldnode == nil || n.Wireless.Channel24 != oldnode.Wireless.Channel24 {
ssh.Execute(n.Address.String(), client, fmt.Sprintf(`
ssh.Execute(n.Address, client, fmt.Sprintf(`
ubus call hostapd.%s switch_chan '{"freq":%d}'
uci set wireless.%s.channel='%d';
uci commit wireless;`,
@ -78,7 +75,7 @@ func (n *Node) SSHUpdate(sshmgmt *ssh.Manager, iface string, oldnode *Node) {
}
}
result, err = ssh.Run(n.Address.String(), client, `
result, err = ssh.Run(n.Address, client, `
if [ "$(uci get wireless.radio0.hwmode | grep -c a)" -ne 0 ]; then
echo "radio0";
elif [ "$(uci get wireless.radio1.hwmode | grep -c a)" -ne 0 ]; then
@ -89,16 +86,16 @@ func (n *Node) SSHUpdate(sshmgmt *ssh.Manager, iface string, oldnode *Node) {
}
radio = ssh.SSHResultToString(result)
ch = GetChannel(n.Wireless.Channel5)
if radio != "" || ch == nil {
if radio != "" && ch != nil {
if oldnode == nil || n.Wireless.TxPower5 != oldnode.Wireless.TxPower5 {
ssh.Execute(n.Address.String(), client, fmt.Sprintf(`
ssh.Execute(n.Address, client, fmt.Sprintf(`
uci set wireless.%s.txpower='%d';
uci commit wireless;`,
radio, n.Wireless.TxPower5))
runWifi = true
}
if oldnode == nil || n.Wireless.Channel5 != oldnode.Wireless.Channel5 {
ssh.Execute(n.Address.String(), client, fmt.Sprintf(`
ssh.Execute(n.Address, client, fmt.Sprintf(`
ubus call hostapd.%s switch_chan '{"freq":%d}'
uci set wireless.%s.channel='%d';
uci commit wireless;`,

View File

@ -1,101 +0,0 @@
package runtime
import (
"sync"
log "github.com/sirupsen/logrus"
runtimeYanic "github.com/FreifunkBremen/yanic/runtime"
"github.com/genofire/golang-lib/file"
"github.com/FreifunkBremen/freifunkmanager/ssh"
)
type Nodes struct {
List map[string]*Node `json:"nodes"`
Current map[string]*Node `json:"-"`
Statistics *runtimeYanic.GlobalStats `json:"-"`
ssh *ssh.Manager
statePath string
iface string
notifyNodeFunc []func(*Node, bool)
notifyStatsFunc []func(*runtimeYanic.GlobalStats)
ListMux sync.RWMutex
CurrentMux sync.RWMutex
}
func NewNodes(path string, iface string, mgmt *ssh.Manager) *Nodes {
nodes := &Nodes{
List: make(map[string]*Node),
Current: make(map[string]*Node),
ssh: mgmt,
statePath: path,
iface: iface,
}
file.ReadJSON(path, nodes)
return nodes
}
func (nodes *Nodes) AddNotifyNode(f func(*Node, bool)) {
nodes.notifyNodeFunc = append(nodes.notifyNodeFunc, f)
}
func (nodes *Nodes) notifyNode(node *Node, system bool) {
for _, f := range nodes.notifyNodeFunc {
f(node, system)
}
}
func (nodes *Nodes) AddNotifyStats(f func(stats *runtimeYanic.GlobalStats)) {
nodes.notifyStatsFunc = append(nodes.notifyStatsFunc, f)
}
func (nodes *Nodes) notifyStats(stats *runtimeYanic.GlobalStats) {
nodes.Statistics = stats
for _, f := range nodes.notifyStatsFunc {
f(stats)
}
}
func (nodes *Nodes) UpdateNode(node *Node) bool {
if node == nil {
log.Warn("no new node to update")
return false
}
if GetChannel(node.Wireless.Channel24) == nil {
log.Warnf("wrong wifi24 channel for '%s'", node.NodeID)
return false
}
if GetChannel(node.Wireless.Channel5) == nil {
log.Warnf("wrong wifi5 channel for '%s'", node.NodeID)
return false
}
nodes.ListMux.Lock()
if n, ok := nodes.List[node.NodeID]; ok {
node.Address = n.Address
go node.SSHUpdate(nodes.ssh, nodes.iface, n)
log.Info("update node", node.NodeID)
}
nodes.List[node.NodeID] = node
nodes.ListMux.Unlock()
nodes.notifyNode(node, true)
return true
}
func (nodes *Nodes) Updater() {
nodes.ListMux.RLock()
nodes.CurrentMux.RLock()
for nodeid, node := range nodes.List {
if n, ok := nodes.Current[nodeid]; ok {
go node.SSHUpdate(nodes.ssh, nodes.iface, n)
}
}
nodes.ListMux.RUnlock()
nodes.CurrentMux.RUnlock()
log.Info("updater per ssh")
}
func (nodes *Nodes) Saver() {
nodes.ListMux.RLock()
file.SaveJSON(nodes.statePath, nodes)
nodes.ListMux.RUnlock()
log.Debug("saved state file")
}

View File

@ -3,6 +3,7 @@ package runtime
import (
"time"
"github.com/jinzhu/gorm"
log "github.com/sirupsen/logrus"
databaseYanic "github.com/FreifunkBremen/yanic/database"
@ -14,14 +15,20 @@ import (
type YanicDB struct {
databaseYanic.Connection
nodes *Nodes
prefix string
db *gorm.DB
ssh *ssh.Manager
sendNode func(*Node, bool)
sendStats func(*runtimeYanic.GlobalStats)
prefix string
}
func NewYanicDB(nodes *Nodes, prefix string) *YanicDB {
func NewYanicDB(db *gorm.DB, ssh *ssh.Manager, sendNode func(*Node, bool), sendStats func(*runtimeYanic.GlobalStats), prefix string) *YanicDB {
return &YanicDB{
nodes: nodes,
prefix: prefix,
db: db,
ssh: ssh,
sendNode: sendNode,
sendStats: sendStats,
prefix: prefix,
}
}
@ -32,40 +39,42 @@ func (conn *YanicDB) InsertNode(n *runtimeYanic.Node) {
}
node.Lastseen = jsontime.Now()
logger := log.WithField("method", "LearnNode").WithField("node_id", node.NodeID)
conn.nodes.ListMux.Lock()
if lNode := conn.nodes.List[node.NodeID]; lNode != nil {
lNode.Lastseen = jsontime.Now()
lNode.Stats = node.Stats
} else {
conn.nodes.List[node.NodeID] = node
conn.nodes.notifyNode(node, true)
lNode := Node{
NodeID: node.NodeID,
}
conn.nodes.ListMux.Unlock()
conn.nodes.CurrentMux.Lock()
if _, ok := conn.nodes.Current[node.NodeID]; ok {
conn.nodes.Current[node.NodeID] = node
conn.nodes.notifyNode(node, false)
conn.nodes.CurrentMux.Unlock()
if conn.db.First(&lNode).Error == nil {
conn.db.Model(&lNode).Update(map[string]interface{}{
"Lastseen": jsontime.Now(),
//"StatsWireless": node.StatsWireless,
//"StatsClients": node.StatsClients,
"Address": node.Address,
})
conn.sendNode(node, false)
if lNode.Blacklist {
logger.Debug("on blacklist")
return
}
if !node.IsEqual(&lNode) {
lNode.SSHUpdate(conn.ssh, node)
logger.Debug("run sshupdate again")
}
logger.Debug("yanic update")
return
}
// session := nodes.ssh.ConnectTo(node.Address)
result, err := conn.nodes.ssh.RunOn(node.GetAddress(conn.nodes.iface), "uptime")
if err != nil {
logger.Debug("init ssh command not run", err)
return
}
uptime := ssh.SSHResultToString(result)
logger.Infof("new node with uptime: %s", uptime)
conn.nodes.Current[node.NodeID] = node
conn.nodes.CurrentMux.Unlock()
conn.nodes.ListMux.Lock()
if lNode := conn.nodes.List[node.NodeID]; lNode != nil {
lNode.Address = node.Address
go lNode.SSHUpdate(conn.nodes.ssh, conn.nodes.iface, node)
node.Lastseen = jsontime.Now()
_, err := conn.ssh.RunOn(node.GetAddress(), "uptime")
if err != nil {
logger.Debug("set on blacklist")
node.Blacklist = true
}
conn.db.Create(&node)
conn.sendNode(node, true)
if err == nil {
lNode.SSHUpdate(conn.ssh, node)
logger.Debug("run sshupdate")
}
conn.nodes.ListMux.Unlock()
conn.nodes.notifyNode(node, false)
}
func (conn *YanicDB) InsertLink(link *runtimeYanic.Link, time time.Time) {
@ -73,7 +82,7 @@ func (conn *YanicDB) InsertLink(link *runtimeYanic.Link, time time.Time) {
func (conn *YanicDB) InsertGlobals(stats *runtimeYanic.GlobalStats, time time.Time, site string, domain string) {
if runtimeYanic.GLOBAL_SITE == site && runtimeYanic.GLOBAL_DOMAIN == domain {
conn.nodes.notifyStats(stats)
conn.sendStats(stats)
}
}

View File

@ -66,11 +66,11 @@ table.nodes tbody tr:nth-child(odd) {
table.nodes tbody tr:hover {
background: #ccc;
}
table.nodes tbody tr.offline,
table.nodes tbody tr.offline:hover{
table.nodes tbody tr.offline:first-child,
table.nodes tbody tr.offline:hover:first-child{
background: #dc0067;
}
table.nodes tbody tr.unseen{
table.nodes tbody tr.unseen:first-child{
background: #009ee0;
}

View File

@ -281,8 +281,6 @@ export class ListView extends View {
channel5Input.value = node.wireless.channel5 || '';
channel5Input.type = 'number';
channel5Input.min = 36;
channel5Input.max = 165;
channel5Input.step = 4;
channel5Input.readOnly = true;
channel5Input.setAttribute('placeholder', '-');
channel5Input.addEventListener('dblclick', () => {

View File

@ -3,7 +3,7 @@ package websocket
import (
log "github.com/sirupsen/logrus"
"github.com/genofire/golang-lib/websocket"
"dev.sum7.eu/genofire/golang-lib/websocket"
)
type WebsocketHandlerFunc func(*log.Entry, *websocket.Message) error

View File

@ -1,14 +1,30 @@
package websocket
import (
"github.com/google/uuid"
log "github.com/sirupsen/logrus"
"github.com/genofire/golang-lib/websocket"
"dev.sum7.eu/genofire/golang-lib/websocket"
)
type Auth struct {
SessionID uuid.UUID
}
func (ws *WebsocketServer) IsLoggedIn(msg *websocket.Message) bool {
auth := Auth{
SessionID: msg.Session,
}
err := ws.db.First(&auth)
return err.Error == nil
}
func (ws *WebsocketServer) loginHandler(logger *log.Entry, msg *websocket.Message) error {
_, ok := ws.loggedIn[msg.Session]
if ok {
auth := Auth{
SessionID: msg.Session,
}
err := ws.db.First(&auth)
if err.Error == nil {
msg.Answer(msg.Subject, true)
logger.Warn("already loggedIn")
return nil
@ -21,7 +37,12 @@ func (ws *WebsocketServer) loginHandler(logger *log.Entry, msg *websocket.Messag
}
ok = (ws.secret == secret)
if ok {
ws.loggedIn[msg.Session] = true
err = ws.db.Create(&auth)
if err.Error != nil {
log.Warnf("database error: %s", err.Error.Error())
msg.Answer(msg.Subject, false)
return err.Error
}
logger.Debug("done")
} else {
logger.Warn("wrong secret")
@ -31,25 +52,23 @@ func (ws *WebsocketServer) loginHandler(logger *log.Entry, msg *websocket.Messag
}
func (ws *WebsocketServer) authStatusHandler(logger *log.Entry, msg *websocket.Message) error {
login, ok := ws.loggedIn[msg.Session]
defer logger.Debug("done")
if !ok {
msg.Answer(msg.Subject, false)
return nil
}
msg.Answer(msg.Subject, login)
msg.Answer(msg.Subject, ws.IsLoggedIn(msg))
return nil
}
func (ws *WebsocketServer) logoutHandler(logger *log.Entry, msg *websocket.Message) error {
_, ok := ws.loggedIn[msg.Session]
if !ok {
auth := Auth{
SessionID: msg.Session,
}
err := ws.db.First(&auth)
if err.Error != nil {
msg.Answer(msg.Subject, false)
logger.Warn("logout without login")
return nil
}
ws.loggedIn[msg.Session] = false
delete(ws.loggedIn, msg.Session)
err = ws.db.Delete(&auth)
logger.Debug("done")
msg.Answer(msg.Subject, true)
return nil
msg.Answer(msg.Subject, err.Error == nil)
return err.Error
}

View File

@ -3,7 +3,7 @@ package websocket
import (
log "github.com/sirupsen/logrus"
wsLib "github.com/genofire/golang-lib/websocket"
wsLib "dev.sum7.eu/genofire/golang-lib/websocket"
"github.com/FreifunkBremen/freifunkmanager/runtime"
)
@ -12,20 +12,25 @@ var wifi24Channels []uint32
var wifi5Channels []uint32
func (ws *WebsocketServer) connectHandler(logger *log.Entry, msg *wsLib.Message) error {
msg.From.Write(&wsLib.Message{Subject: MessageTypeStats, Body: ws.nodes.Statistics})
ws.nodes.ListMux.RLock()
//msg.From.Write(&wsLib.Message{Subject: MessageTypeStats, Body: ws.nodes.Statistics})
var nodes []*runtime.Node
var count int
ws.db.Find(&nodes).Count(&count)
ws.nodes.Lock()
i := 0
for _, node := range ws.nodes.List {
msg.From.Write(&wsLib.Message{Subject: MessageTypeCurrentNode, Body: node})
i++
}
ws.nodes.Unlock()
for _, node := range nodes {
msg.From.Write(&wsLib.Message{Subject: MessageTypeSystemNode, Body: node})
}
ws.nodes.ListMux.RUnlock()
ws.nodes.CurrentMux.RLock()
for _, node := range ws.nodes.Current {
msg.From.Write(&wsLib.Message{Subject: MessageTypeCurrentNode, Body: node})
}
ws.nodes.CurrentMux.RUnlock()
msg.From.Write(&wsLib.Message{Subject: MessageTypeChannelsWifi24, Body: wifi24Channels})
msg.From.Write(&wsLib.Message{Subject: MessageTypeChannelsWifi5, Body: wifi5Channels})
logger.Debug("done")
logger.Debugf("done - fetch %d nodes and send %d", count, i)
return nil
}

View File

@ -4,18 +4,18 @@ import (
"github.com/mitchellh/mapstructure"
log "github.com/sirupsen/logrus"
wsLib "github.com/genofire/golang-lib/websocket"
wsLib "dev.sum7.eu/genofire/golang-lib/websocket"
"github.com/FreifunkBremen/freifunkmanager/runtime"
)
func (ws *WebsocketServer) nodeHandler(logger *log.Entry, msg *wsLib.Message) error {
if ok, exists := ws.loggedIn[msg.Session]; !ok || !exists {
if !ws.IsLoggedIn(msg) {
msg.Answer(msg.Subject, false)
logger.Warn("not logged in")
return nil
}
node := runtime.Node{}
var node runtime.Node
if err := mapstructure.Decode(msg.Body, &node); err != nil {
msg.Answer(msg.Subject, false)
logger.Warnf("not able to decode data: %s", err)
@ -27,7 +27,30 @@ func (ws *WebsocketServer) nodeHandler(logger *log.Entry, msg *wsLib.Message) er
logger.Debugf("%v", node)
return nil
}
msg.Answer(msg.Subject, ws.nodes.UpdateNode(&node))
originNode := runtime.Node{
NodeID: node.NodeID,
}
err := ws.db.First(&originNode)
originNode.Hostname = node.Hostname
originNode.Owner = node.Owner
originNode.Wireless = node.Wireless
originNode.Location = node.Location
if err.Error == nil {
err = ws.db.Save(&originNode)
} else {
logger.Debug(err.Error.Error(), err)
err = ws.db.Create(&originNode)
}
hasError := (err.Error != nil)
msg.Answer(msg.Subject, !hasError)
if hasError {
logger.Warnf("could not change %s: %s", node.NodeID, err.Error.Error())
return err.Error
}
ws.SendNode(&node, true)
logger.Infof("change %s", node.NodeID)
return nil
}

View File

@ -1,7 +1,7 @@
package websocket
import (
wsLib "github.com/genofire/golang-lib/websocket"
wsLib "dev.sum7.eu/genofire/golang-lib/websocket"
yanicRuntime "github.com/FreifunkBremen/yanic/runtime"

View File

@ -3,14 +3,16 @@ package websocket
import (
"net/http"
wsLib "github.com/genofire/golang-lib/websocket"
wsLib "dev.sum7.eu/genofire/golang-lib/websocket"
"github.com/google/uuid"
"github.com/jinzhu/gorm"
"github.com/FreifunkBremen/freifunkmanager/runtime"
"github.com/FreifunkBremen/yanic/runtime"
)
type WebsocketServer struct {
nodes *runtime.Nodes
db *gorm.DB
secret string
loggedIn map[uuid.UUID]bool
@ -19,9 +21,10 @@ type WebsocketServer struct {
handlers map[string]WebsocketHandlerFunc
}
func NewWebsocketServer(secret string, nodes *runtime.Nodes) *WebsocketServer {
func NewWebsocketServer(secret string, db *gorm.DB, nodes *runtime.Nodes) *WebsocketServer {
ownWS := WebsocketServer{
nodes: nodes,
db: db,
handlers: make(map[string]WebsocketHandlerFunc),
loggedIn: make(map[uuid.UUID]bool),
inputMSG: make(chan *wsLib.Message),