Merge pull request #1736 from xiang90/verify

etcdserver: refactor ValidateClusterAndAssignIDs
release-2.0
Xiang Li 2014-11-17 14:34:59 -08:00
commit e04e4632b3
3 changed files with 38 additions and 37 deletions

View File

@ -226,33 +226,6 @@ func (c *Cluster) String() string {
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() {
mIDs := c.MemberIDs()
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
}
// 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 {
e, ok := err.(*etcdErr.Error)
return ok && e.ErrorCode == etcdErr.EcodeKeyNotFound

View File

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

View File

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