etcdserver: Check the initial cluster settings after checking if the WAL exists

This commit is contained in:
Barak Michener 2014-10-22 17:31:27 -04:00
parent d6a5dc9e61
commit e42d65da12
5 changed files with 23 additions and 31 deletions

View File

@ -27,7 +27,6 @@ import (
// ServerConfig holds the configuration of etcd as taken from the command line or discovery. // ServerConfig holds the configuration of etcd as taken from the command line or discovery.
type ServerConfig struct { type ServerConfig struct {
NodeID uint64
Name string Name string
DiscoveryURL string DiscoveryURL string
ClientURLs types.URLs ClientURLs types.URLs
@ -41,7 +40,12 @@ type ServerConfig struct {
// VerifyBootstrapConfig sanity-checks the initial config and returns an error // VerifyBootstrapConfig sanity-checks the initial config and returns an error
// for things that should never happen. // for things that should never happen.
func (c *ServerConfig) VerifyBootstrapConfig() error { func (c *ServerConfig) VerifyBootstrapConfig() error {
if c.NodeID == raft.None { m := c.Cluster.FindName(c.Name)
// Make sure the cluster at least contains the local server.
if m == nil {
return fmt.Errorf("couldn't find local name %s in the initial cluster configuration", c.Name)
}
if m.ID == raft.None {
return fmt.Errorf("could not use %x as member id", raft.None) return fmt.Errorf("could not use %x as member id", raft.None)
} }
@ -49,12 +53,6 @@ func (c *ServerConfig) VerifyBootstrapConfig() error {
return fmt.Errorf("initial cluster state unset and no wal or discovery URL found") return fmt.Errorf("initial cluster state unset and no wal or discovery URL found")
} }
// Make sure the cluster at least contains the local server.
m := c.Cluster.FindID(c.NodeID)
if m == nil {
return fmt.Errorf("couldn't find local ID in cluster config")
}
// No identical IPs in the cluster peer list // No identical IPs in the cluster peer list
urlMap := make(map[string]bool) urlMap := make(map[string]bool)
for _, m := range c.Cluster.Members() { for _, m := range c.Cluster.Members() {

View File

@ -51,7 +51,7 @@ func TestBootstrapConfigVerify(t *testing.T) {
} }
cfg := ServerConfig{ cfg := ServerConfig{
NodeID: 0x7350a9cd4dc16f76, Name: "node1",
DiscoveryURL: tt.disc, DiscoveryURL: tt.disc,
Cluster: cluster, Cluster: cluster,
ClusterState: tt.clst, ClusterState: tt.clst,

View File

@ -181,8 +181,9 @@ func NewServer(cfg *ServerConfig) *EtcdServer {
if err := cfg.VerifyBootstrapConfig(); err != nil { if err := cfg.VerifyBootstrapConfig(); err != nil {
log.Fatalf("etcdserver: %v", err) log.Fatalf("etcdserver: %v", err)
} }
m := cfg.Cluster.FindName(cfg.Name)
if cfg.ShouldDiscover() { if cfg.ShouldDiscover() {
d, err := discovery.New(cfg.DiscoveryURL, cfg.NodeID, cfg.Cluster.String()) d, err := discovery.New(cfg.DiscoveryURL, m.ID, cfg.Cluster.String())
if err != nil { if err != nil {
log.Fatalf("etcdserver: cannot init discovery %v", err) log.Fatalf("etcdserver: cannot init discovery %v", err)
} }
@ -216,9 +217,9 @@ func NewServer(cfg *ServerConfig) *EtcdServer {
sstats := &stats.ServerStats{ sstats := &stats.ServerStats{
Name: cfg.Name, Name: cfg.Name,
ID: idAsHex(cfg.NodeID), ID: idAsHex(id),
} }
lstats := stats.NewLeaderStats(idAsHex(cfg.NodeID)) lstats := stats.NewLeaderStats(idAsHex(id))
s := &EtcdServer{ s := &EtcdServer{
store: st, store: st,
@ -647,8 +648,9 @@ func startNode(cfg *ServerConfig) (id, cid uint64, n raft.Node, w *wal.WAL) {
var err error var err error
// TODO: remove the discoveryURL when it becomes part of the source for // TODO: remove the discoveryURL when it becomes part of the source for
// generating nodeID. // generating nodeID.
member := cfg.Cluster.FindName(cfg.Name)
cfg.Cluster.GenID([]byte(cfg.DiscoveryURL)) cfg.Cluster.GenID([]byte(cfg.DiscoveryURL))
metadata := pbutil.MustMarshal(&pb.Metadata{NodeID: cfg.NodeID, ClusterID: cfg.Cluster.ID()}) metadata := pbutil.MustMarshal(&pb.Metadata{NodeID: member.ID, ClusterID: cfg.Cluster.ID()})
if w, err = wal.Create(cfg.WALDir(), metadata); err != nil { if w, err = wal.Create(cfg.WALDir(), metadata); err != nil {
log.Fatal(err) log.Fatal(err)
} }
@ -661,9 +663,9 @@ func startNode(cfg *ServerConfig) (id, cid uint64, n raft.Node, w *wal.WAL) {
} }
peers[i] = raft.Peer{ID: id, Context: ctx} peers[i] = raft.Peer{ID: id, Context: ctx}
} }
id, cid = cfg.NodeID, cfg.Cluster.ID() id, cid = member.ID, cfg.Cluster.ID()
log.Printf("etcdserver: start node %d in cluster %d", id, cid) log.Printf("etcdserver: start node %d in cluster %d", id, cid)
n = raft.StartNode(cfg.NodeID, peers, 10, 1) n = raft.StartNode(member.ID, peers, 10, 1)
return return
} }

View File

@ -105,7 +105,6 @@ func (c *cluster) Launch(t *testing.T) {
m.PeerListeners = []net.Listener{lns[i]} m.PeerListeners = []net.Listener{lns[i]}
cln := newLocalListener(t) cln := newLocalListener(t)
m.ClientListeners = []net.Listener{cln} m.ClientListeners = []net.Listener{cln}
m.NodeID = clusterCfg.FindName(c.name(i)).ID
m.Name = c.name(i) m.Name = c.name(i)
m.ClientURLs, err = types.NewURLs([]string{"http://" + cln.Addr().String()}) m.ClientURLs, err = types.NewURLs([]string{"http://" + cln.Addr().String()})
if err != nil { if err != nil {

23
main.go
View File

@ -141,8 +141,7 @@ func main() {
// startEtcd launches the etcd server and HTTP handlers for client/server communication. // startEtcd launches the etcd server and HTTP handlers for client/server communication.
func startEtcd() { func startEtcd() {
self, err := setupCluster() if err := setupCluster(); err != nil {
if err != nil {
log.Fatalf("etcd: setupCluster returned error %v", err) log.Fatalf("etcd: setupCluster returned error %v", err)
} }
@ -164,7 +163,6 @@ func startEtcd() {
log.Fatal(err.Error()) log.Fatal(err.Error())
} }
cfg := &etcdserver.ServerConfig{ cfg := &etcdserver.ServerConfig{
NodeID: self.ID,
Name: *name, Name: *name,
ClientURLs: acurls, ClientURLs: acurls,
DataDir: *dir, DataDir: *dir,
@ -262,37 +260,32 @@ func startProxy() {
} }
} }
// setupCluster sets cluster to a temporary value if you are using // setupCluster sets up the cluster definition for bootstrap or discovery.
// discovery, or to the static configuration for bootstrapped clusters. func setupCluster() error {
// Returns the local member on success.
func setupCluster() (*etcdserver.Member, error) {
cluster = etcdserver.NewCluster(*initialClusterName) cluster = etcdserver.NewCluster(*initialClusterName)
set := make(map[string]bool) set := make(map[string]bool)
flag.Visit(func(f *flag.Flag) { flag.Visit(func(f *flag.Flag) {
set[f.Name] = true set[f.Name] = true
}) })
if set["discovery"] && set["initial-cluster"] { if set["discovery"] && set["initial-cluster"] {
return nil, fmt.Errorf("both discovery and bootstrap-config are set") return fmt.Errorf("both discovery and bootstrap-config are set")
} }
apurls, err := pkg.URLsFromFlags(fs, "advertise-peer-urls", "addr", peerTLSInfo) apurls, err := pkg.URLsFromFlags(fs, "advertise-peer-urls", "addr", peerTLSInfo)
if err != nil { if err != nil {
return nil, err return err
} }
switch { switch {
case set["discovery"]: case set["discovery"]:
cluster = etcdserver.NewCluster(*durl) cluster = etcdserver.NewCluster(*durl)
return cluster.AddMemberFromURLs(*name, apurls) _, err := cluster.AddMemberFromURLs(*name, apurls)
return err
case set["initial-cluster"]: case set["initial-cluster"]:
fallthrough fallthrough
default: default:
// We're statically configured, and cluster has appropriately been set. // We're statically configured, and cluster has appropriately been set.
// Try to configure by indexing the static cluster by name. // Try to configure by indexing the static cluster by name.
cluster.SetMembersFromString(*initialCluster) cluster.SetMembersFromString(*initialCluster)
m := cluster.FindName(*name)
if m != nil {
return m, nil
}
return nil, fmt.Errorf("cannot find the passed name %s in --initial-cluster bootstrap list.", *name)
} }
return nil
} }