Show some IPAM status at /status/ipam
This commit is contained in:
1 parent
f2d7a28258
commit
34e7996f2f
3 files changed
+132
-3
No files matched your search
@@ -316,6 +316,26 @@ func (r *Ring) OwnedRanges() (result []address.Range) {
|
||||
return r.splitRangesOverZero(result)
|
||||
}
|
||||
|
||||
func (r *Ring) OwnedRangesByPeer() map[mesh.PeerName][]address.Range {
|
||||
r.assertInvariants()
|
||||
|
||||
result := make(map[mesh.PeerName][]address.Range)
|
||||
for i, entry := range r.Entries {
|
||||
nextEntry := r.Entries.entry(i + 1)
|
||||
resultPeer, found := result[entry.Peer]
|
||||
r := address.Range{Start: entry.Token, End: nextEntry.Token}
|
||||
if !found {
|
||||
result[entry.Peer] = []address.Range{r}
|
||||
} else {
|
||||
result[entry.Peer] = append(resultPeer, r)
|
||||
}
|
||||
}
|
||||
for peer, resultPeer := range result {
|
||||
result[peer] = r.splitRangesOverZero(resultPeer)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// ClaimForPeers claims the entire ring for the array of peers passed
|
||||
// in. Only works for empty rings.
|
||||
func (r *Ring) ClaimForPeers(peers []mesh.PeerName) {
|
||||
|
||||
@@ -2,13 +2,23 @@ package ipam
|
||||
|
||||
import (
|
||||
"github.com/weaveworks/weave/ipam/paxos"
|
||||
"github.com/weaveworks/weave/ipam/ring"
|
||||
"github.com/weaveworks/weave/ipam/space"
|
||||
"github.com/weaveworks/weave/mesh"
|
||||
"github.com/weaveworks/weave/net/address"
|
||||
)
|
||||
|
||||
type Status struct {
|
||||
Paxos *paxos.Status
|
||||
Range string
|
||||
RangeNumIPs int
|
||||
DefaultSubnet string
|
||||
Ring *ring.Ring // information on ranges owned by all peers
|
||||
Space space.Space // more detail on ranges owned by us
|
||||
Owned map[string][]address.Address // addresses by container-ID
|
||||
OurName mesh.PeerName
|
||||
Nicknames map[mesh.PeerName]string `json:"-"`
|
||||
IsKnownPeer func(mesh.PeerName) bool `json:"-"`
|
||||
Entries []EntryStatus
|
||||
PendingClaims []ClaimStatus
|
||||
PendingAllocates []string
|
||||
@@ -40,7 +50,14 @@ func NewStatus(allocator *Allocator, defaultSubnet address.CIDR) *Status {
|
||||
resultChan <- &Status{
|
||||
paxosStatus,
|
||||
allocator.universe.String(),
|
||||
int(allocator.universe.Size()),
|
||||
defaultSubnet.String(),
|
||||
allocator.ring,
|
||||
allocator.space,
|
||||
allocator.owned,
|
||||
allocator.ourName,
|
||||
allocator.nicknames,
|
||||
allocator.isKnownPeer,
|
||||
newEntryStatusSlice(allocator),
|
||||
newClaimStatusSlice(allocator),
|
||||
newAllocateIdentSlice(allocator)}
|
||||
|
||||
+95
-3
@@ -1,8 +1,13 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strings"
|
||||
"text/template"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
. "github.com/weaveworks/weave/common"
|
||||
"github.com/weaveworks/weave/ipam"
|
||||
@@ -10,9 +15,6 @@ import (
|
||||
"github.com/weaveworks/weave/nameserver"
|
||||
"github.com/weaveworks/weave/net/address"
|
||||
weave "github.com/weaveworks/weave/router"
|
||||
"net/http"
|
||||
"strings"
|
||||
"text/template"
|
||||
)
|
||||
|
||||
var rootTemplate = template.New("root").Funcs(map[string]interface{}{
|
||||
@@ -31,6 +33,76 @@ var rootTemplate = template.New("root").Funcs(map[string]interface{}{
|
||||
}
|
||||
return strings.Join(servers, ", ")
|
||||
},
|
||||
"printIPAMRanges": func(status ipam.Status) string {
|
||||
var buffer bytes.Buffer
|
||||
|
||||
type NicknameStats struct {
|
||||
Ranges []address.Range
|
||||
Addresses []address.Address
|
||||
Reachable bool
|
||||
}
|
||||
|
||||
nicknameStats := make(map[string]*NicknameStats)
|
||||
getNickName := func(peer mesh.PeerName) string {
|
||||
name, found := status.Nicknames[peer]
|
||||
if !found {
|
||||
return fmt.Sprintf("%s", peer)
|
||||
}
|
||||
return name
|
||||
}
|
||||
getOrCreateNicknameStats := func(peer mesh.PeerName) *NicknameStats {
|
||||
peerName := getNickName(peer)
|
||||
stats, found := nicknameStats[peerName]
|
||||
if !found {
|
||||
stats = &NicknameStats{
|
||||
Ranges: []address.Range{},
|
||||
Addresses: []address.Address{},
|
||||
Reachable: status.IsKnownPeer(peer),
|
||||
}
|
||||
nicknameStats[peerName] = stats
|
||||
}
|
||||
return stats
|
||||
}
|
||||
|
||||
for _, entry := range status.Ring.Entries {
|
||||
stats := getOrCreateNicknameStats(entry.Peer)
|
||||
stats.Addresses = append(stats.Addresses, entry.Token)
|
||||
}
|
||||
|
||||
for peer, ranges := range status.Ring.OwnedRangesByPeer() {
|
||||
stats := getOrCreateNicknameStats(peer)
|
||||
stats.Ranges = append(stats.Ranges, ranges...)
|
||||
}
|
||||
|
||||
appendAddresses := func(displayName string, reachable bool, addresses []address.Address, ranges []address.Range) {
|
||||
reachableStr := ""
|
||||
if !reachable {
|
||||
reachableStr = "- unreachable!"
|
||||
}
|
||||
ipsInRange := 0
|
||||
for _, chunk := range ranges {
|
||||
ipsInRange += int(chunk.Size())
|
||||
}
|
||||
percentageRanges := float32(ipsInRange) * 100.0 / float32(status.RangeNumIPs)
|
||||
|
||||
fmt.Fprintf(&buffer, "%20s: %8d IPs (%04.1f%% of universe, in %3d ranges) - used: %8d IPs %s\n",
|
||||
displayName, ipsInRange, percentageRanges, len(ranges), len(addresses), reachableStr)
|
||||
}
|
||||
|
||||
// print the local addresses
|
||||
ourNickname := getNickName(status.OurName)
|
||||
ourStats := nicknameStats[ourNickname]
|
||||
appendAddresses("(local)", true, ourStats.Addresses, ourStats.Ranges)
|
||||
|
||||
// and then the rest
|
||||
for nickname, stats := range nicknameStats {
|
||||
if nickname != ourNickname {
|
||||
appendAddresses(nickname, stats.Reachable, stats.Addresses, stats.Ranges)
|
||||
}
|
||||
}
|
||||
|
||||
return buffer.String()
|
||||
},
|
||||
"printConnectionCounts": func(conns []mesh.LocalConnectionStatus) string {
|
||||
counts := make(map[string]int)
|
||||
for _, conn := range conns {
|
||||
@@ -152,6 +224,25 @@ var dnsEntriesTemplate = defTemplate("dnsEntries", `\
|
||||
{{end}}\
|
||||
`)
|
||||
|
||||
var ipamTemplate = defTemplate("ipamTemplate", `\
|
||||
Universe: {{.IPAM.Range}} ({{.IPAM.RangeNumIPs}} IPs)
|
||||
DefaultSubnet: {{.IPAM.DefaultSubnet}}
|
||||
{{if .IPAM.Owned}}\
|
||||
Containers:
|
||||
{{range $id, $addresses := .IPAM.Owned}}\
|
||||
{{printf "%-12s" $id}}: {{$addresses}}
|
||||
{{end}}\
|
||||
{{end}}\
|
||||
Ownerships:
|
||||
{{printIPAMRanges .IPAM}}
|
||||
{{if .IPAM.PendingClaims}}\
|
||||
Claims:
|
||||
{{range .IPAM.PendingClaims}}
|
||||
{{printf "%-15v" .Ident}} {{.Address}}
|
||||
{{end}}\
|
||||
{{end}}\
|
||||
`)
|
||||
|
||||
type WeaveStatus struct {
|
||||
Version string
|
||||
Router *weave.NetworkRouterStatus `json:"Router,omitempty"`
|
||||
@@ -207,5 +298,6 @@ func HandleHTTP(muxRouter *mux.Router, version string, router *weave.NetworkRout
|
||||
defHandler("/status/connections", connectionsTemplate)
|
||||
defHandler("/status/peers", peersTemplate)
|
||||
defHandler("/status/dns", dnsEntriesTemplate)
|
||||
defHandler("/status/ipam", ipamTemplate)
|
||||
|
||||
}
|
||||
Reference in new issue
Block a user