lxd/cluster/membership.go
func Accept(state *state.State, gateway *Gateway, name, address string, schema, api int) ([]db.RaftNode, error) {
	// Check parameters
	if name == "" {
		return nil, fmt.Errorf("node name must not be empty")
	}
	if address == "" {
		return nil, fmt.Errorf("node address must not be empty")
	}

	// Insert the new node into the nodes table.
	err := state.Cluster.Transaction(func(tx *db.ClusterTx) error {
		// Check that the node can be accepted with these parameters.
		err := membershipCheckClusterStateForAccept(tx, name, address, schema, api)
		if err != nil {
			return err
		}
		// Add the new node
		id, err := tx.NodeAdd(name, address)
		if err != nil {
			return errors.Wrap(err, "failed to insert new node")
		}

		// Mark the node as pending, so it will be skipped when
		// performing heartbeats or sending cluster
		// notifications.
		err = tx.NodePending(id, true)
		if err != nil {
			return errors.Wrap(err, "failed to mark new node as pending")
		}

		return nil
	})
	if err != nil {
		return nil, err
	}

	// Possibly insert the new node into the raft_nodes table (if we have
	// less than 3 database nodes).
	nodes, err := gateway.currentRaftNodes()
	if err != nil {
		return nil, errors.Wrap(err, "failed to get raft nodes from the log")
	}
	if len(nodes) < membershipMaxRaftNodes {
		err = state.Node.Transaction(func(tx *db.NodeTx) error {
			id, err := tx.RaftNodeAdd(address)
			if err != nil {
				return err
			}
			nodes = append(nodes, db.RaftNode{ID: id, Address: address})
			return nil
		})
		if err != nil {
			return nil, errors.Wrap(err, "failed to insert new node into raft_nodes")
		}
	}

	return nodes, nil
}
func Accept(state *state.State, gateway *Gateway, name, address string, schema, api int) ([]db.RaftNode, error) {
	// Check parameters
	if name == "" {
		return nil, fmt.Errorf("node name must not be empty")
	}
	if address == "" {
		return nil, fmt.Errorf("node address must not be empty")
	}

	// Insert the new node into the nodes table.
	err := state.Cluster.Transaction(func(tx *db.ClusterTx) error {
		// Check that the node can be accepted with these parameters.
		err := membershipCheckClusterStateForAccept(tx, name, address, schema, api)
		if err != nil {
			return err
		}
		// Add the new node
		id, err := tx.NodeAdd(name, address)
		if err != nil {
			return errors.Wrap(err, "failed to insert new node")
		}

		// Mark the node as pending, so it will be skipped when
		// performing heartbeats or sending cluster
		// notifications.
		err = tx.NodePending(id, true)
		if err != nil {
			return errors.Wrap(err, "failed to mark new node as pending")
		}

		return nil
	})
	if err != nil {
		return nil, err
	}

	// Possibly insert the new node into the raft_nodes table (if we have
	// less than 3 database nodes).
	nodes, err := gateway.currentRaftNodes()
	if err != nil {
		return nil, errors.Wrap(err, "failed to get raft nodes from the log")
	}
	if len(nodes) < membershipMaxRaftNodes {
		err = state.Node.Transaction(func(tx *db.NodeTx) error {
			id, err := tx.RaftNodeAdd(address)
			if err != nil {
				return err
			}
			nodes = append(nodes, db.RaftNode{ID: id, Address: address})
			return nil
		})
		if err != nil {
			return nil, errors.Wrap(err, "failed to insert new node into raft_nodes")
		}
	}

	return nodes, nil
}
// Accept a new node and add it to the cluster.
//
// This instance must already be clustered.
//
// Return an updated list raft database nodes (possibly including the newly
// accepted node).