clusterviz/cluster.go

91 lines
1.9 KiB
Go
Raw Normal View History

2018-06-19 13:06:42 +00:00
package main
import (
2018-06-20 14:45:05 +00:00
"context"
2018-06-19 13:06:42 +00:00
"log"
2018-06-19 15:40:46 +00:00
"sort"
2018-06-20 17:17:33 +00:00
"sync"
2018-06-19 13:06:42 +00:00
)
// ClusterSource represents knowledge source of
// cluster configuration.
type ClusterSource interface {
2018-06-20 16:42:24 +00:00
IPs(ctx context.Context, tag string) ([]string, error)
2018-06-19 13:06:42 +00:00
}
2018-06-19 15:40:46 +00:00
// Fetched implements data fetching from multiple sources
// to get the needed peers data.
type Fetcher struct {
cluster ClusterSource
rpc RPCClient
2018-06-19 13:06:42 +00:00
}
2018-06-19 15:40:46 +00:00
// NewFetcher creates new Fetcher.
func NewFetcher(cluster ClusterSource, rpc RPCClient) *Fetcher {
return &Fetcher{
cluster: cluster,
rpc: rpc,
2018-06-19 13:06:42 +00:00
}
}
2018-06-19 15:40:46 +00:00
// Nodes returns the list of nodes for the given datacentre 'dc' and tag.
2018-06-20 16:42:24 +00:00
func (f *Fetcher) Nodes(ctx context.Context, tag string) ([]*ClusterNode, error) {
ips, err := f.cluster.IPs(ctx, tag)
2018-06-19 13:06:42 +00:00
if err != nil {
2018-06-19 15:40:46 +00:00
return nil, err
2018-06-19 13:06:42 +00:00
}
2018-06-19 15:40:46 +00:00
var ret []*ClusterNode
2018-06-19 13:06:42 +00:00
for _, ip := range ips {
2018-06-20 14:45:05 +00:00
nodeInfo, err := f.rpc.NodeInfo(ctx, ip)
2018-06-19 13:06:42 +00:00
if err != nil {
2018-06-19 15:40:46 +00:00
return nil, err
2018-06-19 13:06:42 +00:00
}
2018-06-19 15:40:46 +00:00
node := NewClusterNode(ip, nodeInfo)
ret = append(ret, node)
2018-06-19 13:06:42 +00:00
}
return ret, nil
}
2018-06-19 15:40:46 +00:00
// NodePeers runs `admin_peers` command for each node.
2018-06-20 14:45:05 +00:00
func (f *Fetcher) NodePeers(ctx context.Context, nodes []*ClusterNode) ([]*Node, []*Link, error) {
2018-06-20 17:17:33 +00:00
var (
m sync.Map
wg sync.WaitGroup
linksMu sync.Mutex
links []*Link
)
2018-06-19 15:40:46 +00:00
for _, node := range nodes {
2018-06-20 17:17:33 +00:00
wg.Add(1)
go func(node *ClusterNode) {
defer wg.Done()
peers, err := f.rpc.AdminPeers(ctx, node.IP)
if err != nil {
log.Printf("[ERROR] Failed to get peers from %s\n", node.IP)
return
}
2018-06-19 13:06:42 +00:00
2018-06-20 17:17:33 +00:00
for _, peer := range peers {
m.Store(peer.ID(), peer)
2018-06-19 13:06:42 +00:00
2018-06-20 17:17:33 +00:00
link := NewLink(node.ID, peer.ID())
linksMu.Lock()
links = append(links, link)
linksMu.Unlock()
}
}(node)
2018-06-19 13:06:42 +00:00
}
2018-06-20 17:17:33 +00:00
wg.Wait()
2018-06-19 13:06:42 +00:00
2018-06-19 15:40:46 +00:00
var ret []*Node
2018-06-20 17:17:33 +00:00
m.Range(func(k, v interface{}) bool {
ret = append(ret, v.(*Node))
return true
})
2018-06-19 15:40:46 +00:00
sort.Slice(ret, func(i, j int) bool {
return ret[i].ID() < ret[j].ID()
})
return ret, links, nil
2018-06-19 13:06:42 +00:00
}