From 0c59de40e7b9c2b526c71ea8f581d65cdc0ae8cc Mon Sep 17 00:00:00 2001 From: Bryan Boreham Date: Wed, 6 Apr 2016 16:41:17 +0100 Subject: [PATCH 1/3] Refactor Paxos status call to remove type assertion --- ipam/allocator.go | 2 +- ipam/paxos/participant.go | 5 +++++ ipam/paxos/paxos.go | 7 ++++--- ipam/status.go | 6 ++++-- 4 files changed, 14 insertions(+), 6 deletions(-) diff --git a/ipam/allocator.go b/ipam/allocator.go index 0159f0d2..93c81f21 100644 --- a/ipam/allocator.go +++ b/ipam/allocator.go @@ -767,7 +767,7 @@ func (alloc *Allocator) update(sender mesh.PeerName, msg []byte) error { // (if we did so on periodic gossip we would force consensus unnecessarily) // * If we are an elector (to avoid a broadcast storm of ring request messages) default: - if _, ok := alloc.paxos.(*paxos.Node); ok && sender != mesh.UnknownPeerName { + if alloc.paxos.IsElector() && sender != mesh.UnknownPeerName { alloc.establishRing() } } diff --git a/ipam/paxos/participant.go b/ipam/paxos/participant.go index 32162018..b15b8733 100644 --- a/ipam/paxos/participant.go +++ b/ipam/paxos/participant.go @@ -7,6 +7,7 @@ type Participant interface { Propose() Think() bool Consensus() (bool, AcceptedValue) + IsElector() bool } type Observer struct { @@ -37,3 +38,7 @@ func (observer *Observer) Think() bool { func (observer *Observer) Consensus() (bool, AcceptedValue) { return false, AcceptedValue{} } + +func (observer *Observer) IsElector() bool { + return false +} diff --git a/ipam/paxos/paxos.go b/ipam/paxos/paxos.go index 3a956269..6d157060 100644 --- a/ipam/paxos/paxos.go +++ b/ipam/paxos/paxos.go @@ -257,14 +257,15 @@ func (node *Node) Consensus() (bool, AcceptedValue) { return false, AcceptedValue{} } +func (node *Node) IsElector() bool { + return true +} + type Status struct { KnownNodes int Quorum uint } func NewStatus(node *Node) *Status { - if node == nil { - return nil - } return &Status{len(node.knows), node.quorum} } diff --git a/ipam/status.go b/ipam/status.go index f98f303d..c826b9b1 100644 --- a/ipam/status.go +++ b/ipam/status.go @@ -37,8 +37,10 @@ func NewStatus(allocator *Allocator, defaultSubnet address.CIDR) *Status { var paxosStatus *paxos.Status if allocator.awaitingConsensus && allocator.paxos != nil { - if node, ok := allocator.paxos.(*paxos.Node); ok { - paxosStatus = paxos.NewStatus(node) + if allocator.paxos.IsElector() { + if node, ok := allocator.paxos.(*paxos.Node); ok { + paxosStatus = paxos.NewStatus(node) + } } } From c12a52d20ee1d35b53d350e3ca01bae9a7e42c49 Mon Sep 17 00:00:00 2001 From: Bryan Boreham Date: Wed, 6 Apr 2016 16:45:24 +0100 Subject: [PATCH 2/3] Better log and status messages for Paxos observer --- ipam/allocator.go | 4 +++- ipam/paxos/paxos.go | 3 ++- ipam/status.go | 2 ++ prog/weaver/http.go | 4 ++++ 4 files changed, 11 insertions(+), 2 deletions(-) diff --git a/ipam/allocator.go b/ipam/allocator.go index 93c81f21..20c78bd5 100644 --- a/ipam/allocator.go +++ b/ipam/allocator.go @@ -887,8 +887,10 @@ func (alloc *Allocator) loadPersistedData() { if len(alloc.seed) != 0 { alloc.infof("Initialising with supplied IPAM seed") alloc.createRing(alloc.seed) - } else { + } else if alloc.paxos.IsElector() { alloc.infof("Initialising via deferred consensus") + } else { + alloc.infof("Initialising as observer - awaiting IPAM data from another peer") } } diff --git a/ipam/paxos/paxos.go b/ipam/paxos/paxos.go index 6d157060..fe10775b 100644 --- a/ipam/paxos/paxos.go +++ b/ipam/paxos/paxos.go @@ -262,10 +262,11 @@ func (node *Node) IsElector() bool { } type Status struct { + Elector bool KnownNodes int Quorum uint } func NewStatus(node *Node) *Status { - return &Status{len(node.knows), node.quorum} + return &Status{true, len(node.knows), node.quorum} } diff --git a/ipam/status.go b/ipam/status.go index c826b9b1..a65de527 100644 --- a/ipam/status.go +++ b/ipam/status.go @@ -41,6 +41,8 @@ func NewStatus(allocator *Allocator, defaultSubnet address.CIDR) *Status { if node, ok := allocator.paxos.(*paxos.Node); ok { paxosStatus = paxos.NewStatus(node) } + } else { + paxosStatus = &paxos.Status{Elector: false} } } diff --git a/prog/weaver/http.go b/prog/weaver/http.go index 57945539..cf9254ac 100644 --- a/prog/weaver/http.go +++ b/prog/weaver/http.go @@ -166,7 +166,11 @@ var statusTemplate = defTemplate("status", `\ Status: ready {{end}}\ {{else if .IPAM.Paxos}}\ +{{if .IPAM.Paxos.Elector}}\ Status: awaiting consensus (quorum: {{.IPAM.Paxos.Quorum}}, known: {{.IPAM.Paxos.KnownNodes}}) +{{else}}\ + Status: awaiting consensus (observer) +{{end}}\ {{else}}\ Status: idle {{end}}\ From aad5b4dd7e7a66c2fba16e0d3a8143ed3a380c41 Mon Sep 17 00:00:00 2001 From: Bryan Boreham Date: Thu, 7 Apr 2016 13:16:15 +0100 Subject: [PATCH 3/3] Document observer status --- site/ipam/troubleshooting-ipam.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/site/ipam/troubleshooting-ipam.md b/site/ipam/troubleshooting-ipam.md index c8f8e194..cde24b8d 100644 --- a/site/ipam/troubleshooting-ipam.md +++ b/site/ipam/troubleshooting-ipam.md @@ -31,7 +31,9 @@ the total allocation range and default subnet. Columns are as follows: * 'awaiting consensus' - an attempt to achieve consensus is ongoing, triggered by an allocation or claim request; allocations will block. This state persists until a quorum of - peers are able to communicate amongst themselves successfully + peers are able to communicate amongst themselves successfully. + The Status may also show '(observer)' instead of the quorum size, + if this peer has been started with the `--observer` option. * 'ready' - consensus achieved; allocations proceed normally * 'waiting for IP range grant from peers' - peer has exhausted its agreed portion of the range and is waiting to be granted some