Add backend pinger

This commit is contained in:
Martin/Geno 2019-06-03 15:38:46 +02:00 committed by genofire
parent eddae7806f
commit aa2917b1a0
4 changed files with 119 additions and 2 deletions

6
data/ping_result.go Normal file
View File

@ -0,0 +1,6 @@
package data
type PingResult struct {
True []string `json:"true"`
False []string `json:"false"`
}

View File

@ -56,6 +56,12 @@ func main() {
ws := websocket.NewWebsocketServer(config.Secret, config.SSHIPAddressPrefix, db, config.BlacklistFor.Duration, nodesYanic)
yanic := runtime.NewYanicDB(db, sshmanager, config.BlacklistFor.Duration, ws.SendNode, ws.SendStats, config.SSHIPAddressPrefix)
pinger, err := runtime.NewPinger(db, config.BlacklistFor.Duration, ws.SendPing)
if err != nil {
log.Panic(err)
}
go pinger.Start()
if config.YanicEnable {
if duration := config.YanicSynchronize.Duration; duration > 0 {

104
runtime/ping.go Normal file
View File

@ -0,0 +1,104 @@
package runtime
import (
"net"
"time"
"sync"
log "github.com/sirupsen/logrus"
"github.com/digineo/go-ping"
"github.com/jinzhu/gorm"
"github.com/FreifunkBremen/freifunkmanager/data"
)
type Pinger struct {
db *gorm.DB
blacklistFor time.Duration
sendResult func(*data.PingResult)
stop bool
wg sync.WaitGroup
p *ping.Pinger
pingTimeout time.Duration
pingCount int
}
func NewPinger(db *gorm.DB, blacklistFor time.Duration, sendResult func(*data.PingResult)) (*Pinger, error) {
ping, err := ping.New("", "::")
if err != nil {
return nil, err
}
return &Pinger{
db: db,
blacklistFor: blacklistFor,
sendResult: sendResult,
stop: false,
p: ping,
pingTimeout: time.Duration(time.Second),
pingCount: 2,
}, nil
}
func (pinger *Pinger) Start() {
pinger.wg.Add(1)
for !pinger.stop {
pinger.run()
}
pinger.wg.Done()
}
func (pinger *Pinger) Stop() {
pinger.stop = true
pinger.wg.Wait()
}
func (pinger *Pinger) run() {
result := &data.PingResult{}
now := time.Now()
count := 0
var nodes []*Node
pinger.db.Find(&nodes).Count(&count)
wg := sync.WaitGroup{}
wg.Add(count)
for _, node := range nodes {
go func(n *Node) {
defer wg.Done()
if n.Blacklist.After(now.Add(-pinger.blacklistFor)) {
return
}
addr, err := net.ResolveIPAddr("ip6", n.Address)
if err != nil {
return
}
_, err = pinger.p.PingAttempts(addr, pinger.pingTimeout, pinger.pingCount)
if err == nil {
result.True = append(result.True, n.NodeID)
} else {
result.False = append(result.False, n.NodeID)
}
}(node)
}
wg.Wait()
log.WithFields(map[string]interface{}{
"count": count,
"count_skipped": count - (len(result.True) + len(result.False)),
"count_false": len(result.False),
"count_true": len(result.True),
}).Debug("pinger complete")
pinger.sendResult(result)
}

View File

@ -6,6 +6,7 @@ import (
yanicRuntime "github.com/FreifunkBremen/yanic/runtime"
"github.com/FreifunkBremen/freifunkmanager/runtime"
"github.com/FreifunkBremen/freifunkmanager/data"
)
func (ws *WebsocketServer) SendNode(node *runtime.Node) {
@ -15,9 +16,9 @@ func (ws *WebsocketServer) SendNode(node *runtime.Node) {
func (ws *WebsocketServer) SendStats(data *yanicRuntime.GlobalStats) {
ws.ws.SendAll(&wsLib.Message{Subject: MessageTypeStats, Body: data})
}
func (ws *WebsocketServer) SendPing(data interface{}) {
func (ws *WebsocketServer) SendPing(pResult *data.PingResult) {
var sessions []*Session
msg := &wsLib.Message{Subject: MessageTypePing, Body: data}
msg := &wsLib.Message{Subject: MessageTypePing, Body: pResult}
ws.db.Find(&sessions)
for _, session := range sessions {