func applyConf(cc raftpb.ConfChange, cl *membership.RaftCluster) { if err := cl.ValidateConfigurationChange(cc); err != nil { return } switch cc.Type { case raftpb.ConfChangeAddNode: m := new(membership.Member) if err := json.Unmarshal(cc.Context, m); err != nil { panic(err) } cl.AddMember(m) case raftpb.ConfChangeRemoveNode: cl.RemoveMember(types.ID(cc.NodeID)) case raftpb.ConfChangeUpdateNode: m := new(membership.Member) if err := json.Unmarshal(cc.Context, m); err != nil { panic(err) } cl.UpdateRaftAttributes(m.ID, m.RaftAttributes) } }
// makeWAL creates a WAL for the initial cluster func makeWALAndSnap(waldir, snapdir string, cl *membership.RaftCluster) { if err := fileutil.CreateDirAll(waldir); err != nil { ExitWithError(ExitIO, err) } // add members again to persist them to the store we create. st := store.New(etcdserver.StoreClusterPrefix, etcdserver.StoreKeysPrefix) cl.SetStore(st) for _, m := range cl.Members() { cl.AddMember(m) } m := cl.MemberByName(restoreName) md := &etcdserverpb.Metadata{NodeID: uint64(m.ID), ClusterID: uint64(cl.ID())} metadata, merr := md.Marshal() if merr != nil { ExitWithError(ExitInvalidInput, merr) } w, walerr := wal.Create(waldir, metadata) if walerr != nil { ExitWithError(ExitIO, walerr) } defer w.Close() peers := make([]raft.Peer, len(cl.MemberIDs())) for i, id := range cl.MemberIDs() { ctx, err := json.Marshal((*cl).Member(id)) if err != nil { ExitWithError(ExitInvalidInput, err) } peers[i] = raft.Peer{ID: uint64(id), Context: ctx} } ents := make([]raftpb.Entry, len(peers)) nodeIDs := make([]uint64, len(peers)) for i, p := range peers { nodeIDs[i] = p.ID cc := raftpb.ConfChange{ Type: raftpb.ConfChangeAddNode, NodeID: p.ID, Context: p.Context} d, err := cc.Marshal() if err != nil { ExitWithError(ExitInvalidInput, err) } e := raftpb.Entry{ Type: raftpb.EntryConfChange, Term: 1, Index: uint64(i + 1), Data: d, } ents[i] = e } commit, term := uint64(len(ents)), uint64(1) if err := w.Save(raftpb.HardState{ Term: term, Vote: peers[0].ID, Commit: commit}, ents); err != nil { ExitWithError(ExitIO, err) } b, berr := st.Save() if berr != nil { ExitWithError(ExitError, berr) } raftSnap := raftpb.Snapshot{ Data: b, Metadata: raftpb.SnapshotMetadata{ Index: commit, Term: term, ConfState: raftpb.ConfState{ Nodes: nodeIDs, }, }, } snapshotter := snap.New(snapdir) if err := snapshotter.SaveSnap(raftSnap); err != nil { panic(err) } if err := w.SaveSnapshot(walpb.Snapshot{Index: commit, Term: term}); err != nil { ExitWithError(ExitIO, err) } }