Skip to content

Commit

Permalink
Add a method to export membership info to v2 store from RaftCluster
Browse files Browse the repository at this point in the history
Signed-off-by: Geeta Gharpure <geetagh@amazon.com>
  • Loading branch information
Geeta Gharpure committed Jun 23, 2023
1 parent 3e725ac commit e29461f
Show file tree
Hide file tree
Showing 5 changed files with 66 additions and 15 deletions.
17 changes: 3 additions & 14 deletions etcdutl/etcdutl/backup_command.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@ import (
"go.etcd.io/etcd/client/pkg/v3/types"
"go.etcd.io/etcd/pkg/v3/idutil"
"go.etcd.io/etcd/pkg/v3/pbutil"
"go.etcd.io/etcd/server/v3/etcdserver"
"go.etcd.io/etcd/server/v3/etcdserver/api/membership"
"go.etcd.io/etcd/server/v3/etcdserver/api/snap"
"go.etcd.io/etcd/server/v3/etcdserver/api/v2store"
"go.etcd.io/etcd/server/v3/storage/backend"
"go.etcd.io/etcd/server/v3/storage/datadir"
"go.etcd.io/etcd/server/v3/storage/schema"
Expand Down Expand Up @@ -178,21 +178,10 @@ func saveSnap(lg *zap.Logger, destSnap, srcSnap string, desired *desiredCluster)
// mustTranslateV2store processes storeData such that they match 'desiredCluster'.
// In particular the method overrides membership information.
func mustTranslateV2store(lg *zap.Logger, storeData []byte, desired *desiredCluster) []byte {
st := v2store.New()
if err := st.Recovery(storeData); err != nil {
lg.Panic("cannot translate v2store", zap.Error(err))
}

raftCluster := membership.NewClusterFromMembers(lg, desired.clusterId, desired.members)
raftCluster.SetID(desired.nodeId, desired.clusterId)
raftCluster.SetStore(st)
raftCluster.PushMembershipToStorage()

outputData, err := st.Save()
if err != nil {
lg.Panic("cannot save v2store", zap.Error(err))
}
return outputData
d := etcdserver.GetMembershipInfoInV2Format(lg, raftCluster)
return d
}

func translateWAL(lg *zap.Logger, srcWAL string, walsnap walpb.Snapshot) (etcdserverpb.Metadata, raftpb.HardState, []raftpb.Entry) {
Expand Down
23 changes: 23 additions & 0 deletions server/etcdserver/api/membership/cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -854,3 +854,26 @@ func ValidateMaxLearnerConfig(maxLearners int, members []*Member, scaleUpLearner

return nil
}

func (c *RaftCluster) Store(store v2store.Store) {
c.Lock()
defer c.Unlock()
for _, m := range c.members {
mustSaveMemberToStore(c.lg, store, m)
if m.ClientURLs != nil {
mustUpdateMemberAttrInStore(c.lg, store, m)
}
c.lg.Info(
"snapshot storing member",
zap.String("id", m.ID.String()),
zap.Strings("peer-urls", m.PeerURLs),
zap.Bool("is-learner", m.IsLearner),
)
}
for id, _ := range c.removed {
mustDeleteMemberFromStore(c.lg, store, id)
}
if c.version != nil {
mustSaveClusterVersionToStore(c.lg, store, c.version)
}
}
27 changes: 27 additions & 0 deletions server/etcdserver/api/membership/cluster_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
"reflect"
"testing"

"github.com/stretchr/testify/assert"
"go.uber.org/zap/zaptest"

"go.etcd.io/etcd/client/pkg/v3/testutil"
Expand Down Expand Up @@ -975,3 +976,29 @@ func TestIsReadyToPromoteMember(t *testing.T) {
}
}
}

func TestClusterStore(t *testing.T) {
name := "etcd"
clientURLs := []string{"http://127.0.0.1:4001"}
tests := []struct {
mems []*Member
removed map[types.ID]bool
}{
{
[]*Member{
newTestMember(1, nil, name, clientURLs),
},
map[types.ID]bool{types.ID(2): true},
},
}
for _, tt := range tests {
c := newTestCluster(t, tt.mems)
c.removed = tt.removed

st := v2store.New("/0", "/1")
c.Store(st)
mst, rst := membersFromStore(c.lg, st)
assert.Equal(t, mst[types.ID(1)], tt.mems[0])
assert.Equal(t, rst, tt.removed)
}
}
2 changes: 1 addition & 1 deletion server/etcdserver/api/membership/storev2.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ func mustSaveMemberToStore(lg *zap.Logger, s v2store.Store, m *Member) {
}

func mustDeleteMemberFromStore(lg *zap.Logger, s v2store.Store, id types.ID) {
if _, err := s.Delete(MemberStoreKey(id), true, true); err != nil {
if _, err := s.Delete(MemberStoreKey(id), true, true); err != nil && !isKeyNotFound(err) {
lg.Panic(
"failed to delete member from store",
zap.String("path", MemberStoreKey(id)),
Expand Down
12 changes: 12 additions & 0 deletions server/etcdserver/cluster_util.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import (
"go.etcd.io/etcd/api/v3/version"
"go.etcd.io/etcd/client/pkg/v3/types"
"go.etcd.io/etcd/server/v3/etcdserver/api/membership"
"go.etcd.io/etcd/server/v3/etcdserver/api/v2store"
"go.etcd.io/etcd/server/v3/etcdserver/errors"

"github.com/coreos/go-semver/semver"
Expand Down Expand Up @@ -416,3 +417,14 @@ func convertToClusterVersion(v string) (*semver.Version, error) {
ver = &semver.Version{Major: ver.Major, Minor: ver.Minor}
return ver, nil
}

func GetMembershipInfoInV2Format(lg *zap.Logger, cl *membership.RaftCluster) []byte {
var st v2store.Store
st = v2store.New(StoreClusterPrefix, StoreKeysPrefix)
cl.Store(st)
d, err := st.SaveNoCopy()
if err != nil {
lg.Panic("failed to save v2 store", zap.Error(err))
}
return d
}

0 comments on commit e29461f

Please sign in to comment.