[lxc-devel] [lxd/master] Fix raft_nodes/nodes ID disconnect
stgraber on Github
lxc-bot at linuxcontainers.org
Thu Jul 18 08:57:40 UTC 2019
A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 301 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20190718/75fbbccd/attachment-0001.bin>
-------------- next part --------------
From 3cce1bcd8d7fcfe87017429cb88bcf431728aedb Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Thu, 18 Jul 2019 04:37:28 -0400
Subject: [PATCH 1/2] lxd/cluster/membership: Fix new DB server id
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
This effectively reverts commit 1b52ef853533efb7e0837a1aae731f925043617b.
Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
lxd/cluster/membership.go | 19 ++++++++++++++-----
1 file changed, 14 insertions(+), 5 deletions(-)
diff --git a/lxd/cluster/membership.go b/lxd/cluster/membership.go
index 671cd4a886..8a1b186c1f 100644
--- a/lxd/cluster/membership.go
+++ b/lxd/cluster/membership.go
@@ -468,7 +468,6 @@ func Rebalance(state *state.State, gateway *Gateway) (string, []db.RaftNode, err
// Check if we have a spare node that we can turn into a database one.
address := ""
- id := int64(-1)
err = state.Cluster.Transaction(func(tx *db.ClusterTx) error {
config, err := ConfigLoad(tx)
if err != nil {
@@ -489,7 +488,6 @@ func Rebalance(state *state.State, gateway *Gateway) (string, []db.RaftNode, err
logger.Debugf(
"Found spare node %s (%s) to be promoted as database node", node.Name, node.Address)
address = node.Address
- id = node.ID
break
}
@@ -504,9 +502,20 @@ func Rebalance(state *state.State, gateway *Gateway) (string, []db.RaftNode, err
return "", currentRaftNodes, nil
}
- // Update the local raft_table adding the new member and building a new
- // list.
- updatedRaftNodes := append(currentRaftNodes, db.RaftNode{ID: id, Address: address})
+ // Figure out the next ID in the raft_nodes table
+ var updatedRaftNodes []db.RaftNode
+ err = gateway.db.Transaction(func(tx *db.NodeTx) error {
+ id, err := tx.RaftNodeAdd(address)
+ if err != nil {
+ return errors.Wrap(err, "Failed to add new raft node")
+ }
+
+ updatedRaftNodes = append(currentRaftNodes, db.RaftNode{ID: id, Address: address})
+ return nil
+ })
+ if err != nil {
+ return "", nil, err
+ }
return address, updatedRaftNodes, nil
}
From bcf52e7ef6e5c02ae4906d14db63948a701582e8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Thu, 18 Jul 2019 04:57:14 -0400
Subject: [PATCH 2/2] lxd/cluster/heartbeat: Properly handle raft_nodes/nodes
ID disconnect
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
lxd/cluster/gateway.go | 7 ++++++-
lxd/cluster/heartbeat.go | 20 +++++++++++++++-----
2 files changed, 21 insertions(+), 6 deletions(-)
diff --git a/lxd/cluster/gateway.go b/lxd/cluster/gateway.go
index 78a9264a46..f14e873582 100644
--- a/lxd/cluster/gateway.go
+++ b/lxd/cluster/gateway.go
@@ -180,8 +180,13 @@ func (g *Gateway) HandlerFuncs(nodeRefreshTask func(*APIHeartbeat)) map[string]h
nodes := make([]db.RaftNode, 0)
for _, node := range heartbeatData.Members {
if node.Raft {
+ // Needed to handle LXD 3.15
+ if node.RaftID == 0 {
+ node.RaftID = node.ID
+ }
+
nodes = append(nodes, db.RaftNode{
- ID: node.ID,
+ ID: node.RaftID,
Address: node.Address,
})
}
diff --git a/lxd/cluster/heartbeat.go b/lxd/cluster/heartbeat.go
index 45bca1d908..19219cd09c 100644
--- a/lxd/cluster/heartbeat.go
+++ b/lxd/cluster/heartbeat.go
@@ -22,6 +22,7 @@ type APIHeartbeatMember struct {
ID int64
Address string
Raft bool
+ RaftID int64
LastHeartbeat time.Time
Online bool // Calculated from offline threshold and LastHeatbeat time.
updated bool // Has node been updated during this heartbeat run. Not sent to nodes.
@@ -46,6 +47,16 @@ type APIHeartbeat struct {
FullStateList bool
}
+func (hbState *APIHeartbeat) memberByAddress(address string) (APIHeartbeatMember, bool) {
+ for _, member := range hbState.Members {
+ if member.Address == address {
+ return member, true
+ }
+ }
+
+ return APIHeartbeatMember{}, false
+}
+
// Update updates an existing APIHeartbeat struct with the raft and all node states supplied.
// If allNodes provided is an empty set then this is considered a non-full state list.
func (hbState *APIHeartbeat) Update(fullStateList bool, raftNodes []db.RaftNode, allNodes []db.NodeInfo, offlineThreshold time.Duration) {
@@ -61,16 +72,16 @@ func (hbState *APIHeartbeat) Update(fullStateList bool, raftNodes []db.RaftNode,
// Add raft nodes first with the raft flag set to true, but missing LastHeartbeat time.
for _, node := range raftNodes {
- member, exists := hbState.Members[node.ID]
+ member, exists := hbState.memberByAddress(node.Address)
if !exists {
member = APIHeartbeatMember{
- ID: node.ID,
Address: node.Address,
}
}
+ member.RaftID = node.ID
member.Raft = true
- hbState.Members[node.ID] = member
+ hbState.Members[member.ID] = member
}
// Add remaining nodes, and when if existing node is found, update status.
@@ -121,7 +132,6 @@ func (hbState *APIHeartbeat) Send(ctx context.Context, cert *shared.CertInfo, lo
logger.Debugf("Sending heartbeat to %s", address)
err := HeartbeatNode(ctx, address, cert, heartbeatData)
-
if err == nil {
hbState.Lock()
// Ensure only update nodes that exist in Members already.
@@ -281,7 +291,7 @@ func (g *Gateway) heartbeat(ctx context.Context, initialHeartbeat bool) {
for _, currentNode := range currentNodes {
existing := false
for _, node := range allNodes {
- if node.Address == currentNode.Address && node.ID == currentNode.ID {
+ if node.Address == currentNode.Address {
existing = true
break
}
More information about the lxc-devel
mailing list