etcdserver: refactor ValidateClusterAndAssignIDs

This commit is contained in:
Xiang Li 2014-11-17 14:08:45 -08:00
parent a817ca705b
commit 0541f0afa0
3 changed files with 38 additions and 37 deletions

View File

@ -226,33 +226,6 @@ func (c *Cluster) String() string {
return strings.Join(sl, ",") return strings.Join(sl, ",")
} }
// ValidateAndAssignIDs validates the given members by matching their PeerURLs
// with the existing members in the cluster. If the validation succeeds, it
// assigns the IDs from the given members to the existing members in the
// cluster. If the validation fails, an error will be returned.
func (c *Cluster) ValidateAndAssignIDs(membs []*Member) error {
if len(c.members) != len(membs) {
return fmt.Errorf("member count is unequal")
}
omembs := make([]*Member, 0)
for _, m := range c.members {
omembs = append(omembs, m)
}
sort.Sort(SortableMemberSliceByPeerURLs(omembs))
sort.Sort(SortableMemberSliceByPeerURLs(membs))
for i := range omembs {
if !reflect.DeepEqual(omembs[i].PeerURLs, membs[i].PeerURLs) {
return fmt.Errorf("unmatched member while checking PeerURLs")
}
omembs[i].ID = membs[i].ID
}
c.members = make(map[types.ID]*Member)
for _, m := range omembs {
c.members[m.ID] = m
}
return nil
}
func (c *Cluster) genID() { func (c *Cluster) genID() {
mIDs := c.MemberIDs() mIDs := c.MemberIDs()
b := make([]byte, 8*len(mIDs)) b := make([]byte, 8*len(mIDs))
@ -442,6 +415,32 @@ func membersFromStore(st store.Store) (map[types.ID]*Member, map[types.ID]bool)
return members, removed return members, removed
} }
// ValidateClusterAndAssignIDs validates the local cluster by matching the PeerURLs
// with the existing cluster. If the validation succeeds, it assigns the IDs
// from the existing cluster to the local cluster.
// If the validation fails, an error will be returned.
func ValidateClusterAndAssignIDs(local *Cluster, existing *Cluster) error {
ems := existing.Members()
lms := local.Members()
if len(ems) != len(lms) {
return fmt.Errorf("member count is unequal")
}
sort.Sort(SortableMemberSliceByPeerURLs(ems))
sort.Sort(SortableMemberSliceByPeerURLs(lms))
for i := range ems {
if !reflect.DeepEqual(ems[i].PeerURLs, lms[i].PeerURLs) {
return fmt.Errorf("unmatched member while checking PeerURLs")
}
lms[i].ID = ems[i].ID
}
local.members = make(map[types.ID]*Member)
for _, m := range lms {
local.members[m.ID] = m
}
return nil
}
func isKeyNotFound(err error) bool { func isKeyNotFound(err error) bool {
e, ok := err.(*etcdErr.Error) e, ok := err.(*etcdErr.Error)
return ok && e.ErrorCode == etcdErr.EcodeKeyNotFound return ok && e.ErrorCode == etcdErr.EcodeKeyNotFound

View File

@ -317,8 +317,9 @@ func TestClusterValidateAndAssignIDsBad(t *testing.T) {
}, },
} }
for i, tt := range tests { for i, tt := range tests {
cl := newTestCluster(tt.clmembs) ecl := newTestCluster(tt.clmembs)
if err := cl.ValidateAndAssignIDs(tt.membs); err == nil { lcl := newTestCluster(tt.membs)
if err := ValidateClusterAndAssignIDs(lcl, ecl); err == nil {
t.Errorf("#%d: unexpected update success", i) t.Errorf("#%d: unexpected update success", i)
} }
} }
@ -343,12 +344,13 @@ func TestClusterValidateAndAssignIDs(t *testing.T) {
}, },
} }
for i, tt := range tests { for i, tt := range tests {
cl := newTestCluster(tt.clmembs) lcl := newTestCluster(tt.clmembs)
if err := cl.ValidateAndAssignIDs(tt.membs); err != nil { ecl := newTestCluster(tt.membs)
if err := ValidateClusterAndAssignIDs(lcl, ecl); err != nil {
t.Errorf("#%d: unexpect update error: %v", i, err) t.Errorf("#%d: unexpect update error: %v", i, err)
} }
if !reflect.DeepEqual(cl.MemberIDs(), tt.wids) { if !reflect.DeepEqual(lcl.MemberIDs(), tt.wids) {
t.Errorf("#%d: ids = %v, want %v", i, cl.MemberIDs(), tt.wids) t.Errorf("#%d: ids = %v, want %v", i, lcl.MemberIDs(), tt.wids)
} }
} }
} }

View File

@ -203,14 +203,14 @@ func NewServer(cfg *ServerConfig) (*EtcdServer, error) {
switch { switch {
case !haveWAL && !cfg.NewCluster: case !haveWAL && !cfg.NewCluster:
us := getOtherPeerURLs(cfg.Cluster, cfg.Name) us := getOtherPeerURLs(cfg.Cluster, cfg.Name)
cl, err := GetClusterFromPeers(us) existingCluster, err := GetClusterFromPeers(us)
if err != nil { if err != nil {
return nil, fmt.Errorf("cannot fetch cluster info from peer urls: %v", err) return nil, fmt.Errorf("cannot fetch cluster info from peer urls: %v", err)
} }
if err := cfg.Cluster.ValidateAndAssignIDs(cl.Members()); err != nil { if err := ValidateClusterAndAssignIDs(cfg.Cluster, existingCluster); err != nil {
return nil, fmt.Errorf("error validating IDs from cluster %s: %v", cl, err) return nil, fmt.Errorf("error validating peerURLs %s: %v", existingCluster, err)
} }
cfg.Cluster.SetID(cl.id) cfg.Cluster.SetID(existingCluster.id)
cfg.Cluster.SetStore(st) cfg.Cluster.SetStore(st)
cfg.Print() cfg.Print()
id, n, w = startNode(cfg, nil) id, n, w = startNode(cfg, nil)