@@ -24,6 +24,7 @@ import (
2424 "net/http"
2525 "os"
2626 "path"
27+ "reflect"
2728 "regexp"
2829 "strconv"
2930 "strings"
@@ -67,6 +68,7 @@ import (
6768 "go.etcd.io/etcd/server/v3/lease/leasehttp"
6869 "go.etcd.io/etcd/server/v3/mvcc"
6970 "go.etcd.io/etcd/server/v3/mvcc/backend"
71+ "go.etcd.io/etcd/server/v3/verify"
7072 "go.etcd.io/etcd/server/v3/wal"
7173)
7274
@@ -2449,9 +2451,51 @@ func (s *EtcdServer) applyConfChange(cc raftpb.ConfChange, confState *raftpb.Con
24492451 s .r .transport .UpdatePeer (m .ID , m .PeerURLs )
24502452 }
24512453 }
2454+
2455+ s .verifyV3StoreInSyncWithV2Store (shouldApplyV3 )
2456+
24522457 return false , nil
24532458}
24542459
2460+ func (s * EtcdServer ) verifyV3StoreInSyncWithV2Store (shouldApplyV3 membership.ShouldApplyV3 ) {
2461+ if ! verify .VerifyEnabled () {
2462+ return
2463+ }
2464+
2465+ // If shouldApplyV3 == false, then it means v2store hasn't caught up with v3store.
2466+ if ! shouldApplyV3 {
2467+ return
2468+ }
2469+
2470+ // clean up the Attributes, and we only care about the RaftAttributes
2471+ cleanAttributesFunc := func (members map [types.ID ]* membership.Member ) map [types.ID ]* membership.Member {
2472+ processedMembers := make (map [types.ID ]* membership.Member )
2473+ for id , m := range members {
2474+ clonedMember := m .Clone ()
2475+ clonedMember .Attributes = membership.Attributes {}
2476+ processedMembers [id ] = clonedMember
2477+ }
2478+
2479+ return processedMembers
2480+ }
2481+
2482+ v2Members , _ := s .cluster .MembersFromStore ()
2483+ v3Members , _ := s .cluster .MembersFromBackend ()
2484+
2485+ processedV2Members := cleanAttributesFunc (v2Members )
2486+ processedV3Members := cleanAttributesFunc (v3Members )
2487+
2488+ if match := reflect .DeepEqual (processedV2Members , processedV3Members ); ! match {
2489+ v2Data , v2Err := json .Marshal (processedV2Members )
2490+ v3Data , v3Err := json .Marshal (processedV3Members )
2491+
2492+ if v2Err != nil || v3Err != nil {
2493+ panic ("members in v2store doesn't match v3store" )
2494+ }
2495+ panic (fmt .Sprintf ("members in v2store doesn't match v3store, v2store: %s, v3store: %s" , string (v2Data ), string (v3Data )))
2496+ }
2497+ }
2498+
24552499// TODO: non-blocking snapshot
24562500func (s * EtcdServer ) snapshot (snapi uint64 , confState raftpb.ConfState ) {
24572501 clone := s .v2store .Clone ()
0 commit comments