Skip to content
This repository has been archived by the owner on Jun 20, 2024. It is now read-only.

Commit

Permalink
Show some IPAM stats with weave status ipam
Browse files Browse the repository at this point in the history
  • Loading branch information
inercia committed Nov 19, 2015
1 parent 989f4e5 commit 63d50b6
Show file tree
Hide file tree
Showing 3 changed files with 123 additions and 2 deletions.
20 changes: 20 additions & 0 deletions ipam/ring/ring.go
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
17 changes: 17 additions & 0 deletions ipam/status.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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)}
Expand Down
88 changes: 86 additions & 2 deletions prog/weaver/http.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package main

import (
"bytes"
"encoding/json"
"fmt"
"net/http"
Expand All @@ -26,6 +27,76 @@ var rootTemplate = template.New("root").Funcs(map[string]interface{}{
}
return count
},
"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 {
Expand Down Expand Up @@ -147,8 +218,21 @@ var dnsEntriesTemplate = defTemplate("dnsEntries", `\
`)

var ipamTemplate = defTemplate("ipamTemplate", `\
{{range .IPAM.Entries}}\
{{printf "%-21v" .Token}} {{printf "%-11v" .Peer}} {{.Version}}
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}}\
`)

Expand Down

0 comments on commit 63d50b6

Please sign in to comment.