The following pull request was submitted through Github. It can be accessed and reviewed at: https://github.com/lxc/lxd/pull/6481
This e-mail was sent by the LXC bot, direct replies will not reach the author unless they happen to be subscribed to this list. === Description (from pull-request) === Draft Pull for #6230
From fe8327b767fdb391f082ae1883e2e5f6d9f11581 Mon Sep 17 00:00:00 2001 From: Rizwan Ahmad Lubis <rizwan.lu...@gmail.com> Date: Sun, 3 Nov 2019 00:29:02 -0500 Subject: [PATCH 1/2] Issue #6230 --- lxd/api_cluster.go | 26 ++++++++++++++++++++++++-- lxd/cluster/membership.go | 32 ++++++++++++++++++++++++++------ lxd/main_init_interactive.go | 2 +- 3 files changed, 51 insertions(+), 9 deletions(-) diff --git a/lxd/api_cluster.go b/lxd/api_cluster.go index ea2c2d3aa1..96ab18d5fb 100644 --- a/lxd/api_cluster.go +++ b/lxd/api_cluster.go @@ -608,6 +608,12 @@ func clusterPutJoin(d *Daemon, req api.ClusterPut) response.Response { // Add the cluster flag from the agent version.UserAgentFeatures([]string{"cluster"}) + logger.Infof("Making cluster rebalance call.") + err = clusterRebalance(client) + if err != nil { + logger.Errorf("Failed cluster rebalance call: %v", err) + } + return nil } @@ -820,6 +826,14 @@ func clusterAcceptMember( return info, nil } +func clusterRebalance(client lxd.InstanceServer) error { + _, _, err := client.RawQuery("POST", "/internal/cluster/rebalance", nil, "") + if err != nil { + return errors.Wrap(err, "Failed cluster rebalance request") + } + return nil +} + func clusterNodesGet(d *Daemon, r *http.Request) response.Response { recursion := util.IsRecursionRequest(r) @@ -1075,7 +1089,7 @@ func internalClusterPostRebalance(d *Daemon, r *http.Request) response.Response return response.InternalError(err) } if localAddress != leader { - logger.Debugf("Redirect cluster rebalance request to %s", leader) + logger.Infof("Redirect cluster rebalance request to %s", leader) url := &url.URL{ Scheme: "https", Path: "/internal/cluster/rebalance", @@ -1084,7 +1098,7 @@ func internalClusterPostRebalance(d *Daemon, r *http.Request) response.Response return response.SyncResponseRedirect(url.String()) } - logger.Debugf("Rebalance cluster") + logger.Infof("Handling rebalance cluster request") // Check if we have a spare node to promote. address, nodes, err := cluster.Rebalance(d.State(), d.gateway) @@ -1094,6 +1108,7 @@ func internalClusterPostRebalance(d *Daemon, r *http.Request) response.Response if address == "" { // If no node could be found to promote, notify all nodes about current set of DB nodes + logger.Infof("No address found to promote") var offlineThreshold time.Duration err := d.cluster.Transaction(func(tx *db.ClusterTx) error { var err error @@ -1128,6 +1143,8 @@ func internalClusterPostRebalance(d *Daemon, r *http.Request) response.Response return response.SyncResponse(true, nil) } + logger.Infof("Promoting address %s. New raft node list: %v", address, nodes) + // Tell the node to promote itself. post := &internalClusterPostPromoteRequest{} for _, node := range nodes { @@ -1144,14 +1161,18 @@ func internalClusterPostRebalance(d *Daemon, r *http.Request) response.Response } _, _, err = client.RawQuery("POST", "/internal/cluster/promote", post, "") if err != nil { + logger.Errorf("Promote request failed: %v", err) return response.SmartError(err) } + logger.Infof("Promote request succeeded") return response.SyncResponse(true, nil) } // Used to promote the local non-database node to be a database one. func internalClusterPostPromote(d *Daemon, r *http.Request) response.Response { + logger.Infof("Handling promote request") + req := internalClusterPostPromoteRequest{} // Parse the request @@ -1162,6 +1183,7 @@ func internalClusterPostPromote(d *Daemon, r *http.Request) response.Response { // Sanity checks if len(req.RaftNodes) == 0 { + logger.Errorf("No raft nodes provided") return response.BadRequest(fmt.Errorf("No raft members provided")) } diff --git a/lxd/cluster/membership.go b/lxd/cluster/membership.go index b8b4456c1f..d5865650d0 100644 --- a/lxd/cluster/membership.go +++ b/lxd/cluster/membership.go @@ -82,6 +82,8 @@ func Bootstrap(state *state.State, gateway *Gateway, name string) error { } // Update our role list. + fmt.Println("Testing that I am running from edited source.\n") + err = tx.NodeAddRole(1, db.ClusterRoleDatabase) if err != nil { return errors.Wrapf(err, "Failed to add database role for the node") @@ -198,8 +200,10 @@ func Accept(state *state.State, gateway *Gateway, name, address string, schema, if err != nil { return nil, errors.Wrap(err, "Failed to get raft nodes from the log") } - - if len(nodes) < membershipMaxRaftNodes { + count, err := Count(state) + if count != 2 && len(nodes) < membershipMaxRaftNodes { +// return nil, fmt.Errorf("%v", nodes) +// if false { err = state.Node.Transaction(func(tx *db.NodeTx) error { id, err := tx.RaftNodeAdd(address) if err != nil { @@ -482,8 +486,9 @@ func Rebalance(state *state.State, gateway *Gateway) (string, []db.RaftNode, err if err != nil { return "", nil, errors.Wrap(err, "failed to get current raft nodes") } - if len(currentRaftNodes) >= membershipMaxRaftNodes { - // We're already at full capacity. + logger.Infof("List of current raft nodes: %v", currentRaftNodes) + if len(currentRaftNodes) >= membershipMaxRaftNodes || len(currentRaftNodes) == 1 { + // We're already at full capacity or would have a two-member cluster. return "", nil, nil } @@ -506,12 +511,14 @@ func Rebalance(state *state.State, gateway *Gateway) (string, []db.RaftNode, err // Find a node that is not part of the raft cluster yet. for _, node := range nodes { if shared.StringInSlice(node.Address, currentRaftAddresses) { + logger.Infof("node %s (%s) is already a database node", node.Name, node.Address) continue // This is already a database node } if node.IsOffline(config.OfflineThreshold()) { + logger.Infof("node %s (%s) is offline", node.Name, node.Address) continue // This node is offline } - logger.Debugf( + logger.Infof( "Found spare node %s (%s) to be promoted as database node", node.Name, node.Address) address = node.Address break @@ -531,6 +538,7 @@ func Rebalance(state *state.State, gateway *Gateway) (string, []db.RaftNode, err // Figure out the next ID in the raft_nodes table var updatedRaftNodes []db.RaftNode err = gateway.db.Transaction(func(tx *db.NodeTx) error { + logger.Infof("Calling raft node add.") id, err := tx.RaftNodeAdd(address) if err != nil { return errors.Wrap(err, "Failed to add new raft node") @@ -549,7 +557,7 @@ func Rebalance(state *state.State, gateway *Gateway) (string, []db.RaftNode, err // Promote makes a LXD node which is not a database node, become part of the // raft cluster. func Promote(state *state.State, gateway *Gateway, nodes []db.RaftNode) error { - logger.Info("Promote node to database node") + logger.Info("Promote this node to database node") // Sanity check that this is not already a database node if gateway.IsDatabaseNode() { @@ -597,6 +605,7 @@ func Promote(state *state.State, gateway *Gateway, nodes []db.RaftNode) error { // includes ourselves). This will make the gateway start a raft node // when restarted. err = state.Node.Transaction(func(tx *db.NodeTx) error { + logger.Infof("Replacing raft node list") err = tx.RaftNodesReplace(nodes) if err != nil { return errors.Wrap(err, "failed to set raft nodes") @@ -642,6 +651,7 @@ func Promote(state *state.State, gateway *Gateway, nodes []db.RaftNode) error { return errors.Wrap(err, "Failed to connect to cluster leader") } defer client.Close() + logger.Info("Found leader successfully. Adding gateway info.") err = client.Add(ctx, gateway.raft.info) if err != nil { @@ -650,8 +660,18 @@ func Promote(state *state.State, gateway *Gateway, nodes []db.RaftNode) error { // Unlock regular access to our cluster database and add the database role. err = state.Cluster.ExitExclusive(func(tx *db.ClusterTx) error { + logger.Info("Getting node list.") + nodeInfo, err := tx.Nodes() + if err != nil { + logger.Errorf("Failed to get node list: %v", err) + return errors.Wrapf(err, "Failed to get node list") + } + logger.Info("Test %d. Got node list: %+v", 0, nodeInfo) + + logger.Info("Adding database role to this node") err = tx.NodeAddRole(id, db.ClusterRoleDatabase) if err != nil { + logger.Errorf("Failed to add database role: %v", err) return errors.Wrapf(err, "Failed to add database role for the node") } return err diff --git a/lxd/main_init_interactive.go b/lxd/main_init_interactive.go index f3947ed526..b998b18c82 100644 --- a/lxd/main_init_interactive.go +++ b/lxd/main_init_interactive.go @@ -99,7 +99,7 @@ func (c *cmdInit) RunInteractive(cmd *cobra.Command, args []string, d lxd.Instan } func (c *cmdInit) askClustering(config *cmdInitData, d lxd.InstanceServer) error { - if cli.AskBool("Would you like to use LXD clustering? (yes/no) [default=no]: ", "no") { + if cli.AskBool("Would you like to use LXD clustering? TEST (yes/no) [default=no]: ", "no") { config.Cluster = &initDataCluster{} config.Cluster.Enabled = true From 7e94399a6c668ae6104e76210c61417794230c0a Mon Sep 17 00:00:00 2001 From: Rizwan Ahmad Lubis <rizwan.lu...@gmail.com> Date: Wed, 20 Nov 2019 14:51:32 -0600 Subject: [PATCH 2/2] clean up --- lxd/cluster/membership.go | 4 ---- lxd/main_init_interactive.go | 2 +- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/lxd/cluster/membership.go b/lxd/cluster/membership.go index d5865650d0..beaee295e4 100644 --- a/lxd/cluster/membership.go +++ b/lxd/cluster/membership.go @@ -82,8 +82,6 @@ func Bootstrap(state *state.State, gateway *Gateway, name string) error { } // Update our role list. - fmt.Println("Testing that I am running from edited source.\n") - err = tx.NodeAddRole(1, db.ClusterRoleDatabase) if err != nil { return errors.Wrapf(err, "Failed to add database role for the node") @@ -202,8 +200,6 @@ func Accept(state *state.State, gateway *Gateway, name, address string, schema, } count, err := Count(state) if count != 2 && len(nodes) < membershipMaxRaftNodes { -// return nil, fmt.Errorf("%v", nodes) -// if false { err = state.Node.Transaction(func(tx *db.NodeTx) error { id, err := tx.RaftNodeAdd(address) if err != nil { diff --git a/lxd/main_init_interactive.go b/lxd/main_init_interactive.go index b998b18c82..f3947ed526 100644 --- a/lxd/main_init_interactive.go +++ b/lxd/main_init_interactive.go @@ -99,7 +99,7 @@ func (c *cmdInit) RunInteractive(cmd *cobra.Command, args []string, d lxd.Instan } func (c *cmdInit) askClustering(config *cmdInitData, d lxd.InstanceServer) error { - if cli.AskBool("Would you like to use LXD clustering? TEST (yes/no) [default=no]: ", "no") { + if cli.AskBool("Would you like to use LXD clustering? (yes/no) [default=no]: ", "no") { config.Cluster = &initDataCluster{} config.Cluster.Enabled = true
_______________________________________________ lxc-devel mailing list lxc-devel@lists.linuxcontainers.org http://lists.linuxcontainers.org/listinfo/lxc-devel