sql rewrite
This commit is contained in:
parent
50a109dee0
commit
21c398ca42
|
@ -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
41
main.go
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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"`
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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;`,
|
||||
|
|
101
runtime/nodes.go
101
runtime/nodes.go
|
@ -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")
|
||||
}
|
|
@ -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)
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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', () => {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
|
|
@ -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),
|
||||
|
|
Loading…
Reference in New Issue