Show some IPAM status at /status/ipam

This commit is contained in:
Alvaro Saurin authored and Bryan Boreham committed 2015-11-26 17:23:47 +00:00
1 parent f2d7a28258
commit 34e7996f2f
3 files changed
+132 -3

No files matched your search

+20
View File
@@ -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) {
+17
View File
@@ -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
View File
@@ -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)
}