diff --git a/etcdserver/api/capability.go b/etcdserver/api/capability.go index 8b13f474295..9a8e280c13e 100644 --- a/etcdserver/api/capability.go +++ b/etcdserver/api/capability.go @@ -41,6 +41,8 @@ var ( "3.2.0": {AuthCapability: true, V3rpcCapability: true}, "3.3.0": {AuthCapability: true, V3rpcCapability: true}, "3.4.0": {AuthCapability: true, V3rpcCapability: true}, + //TODO: use EnableCapability and flag to control this dynamically + "3.5.0": {AuthCapability: true, V3rpcCapability: true}, } enableMapMu sync.RWMutex diff --git a/etcdserver/api/membership/cluster.go b/etcdserver/api/membership/cluster.go index ae1a5608005..0d0277d3046 100644 --- a/etcdserver/api/membership/cluster.go +++ b/etcdserver/api/membership/cluster.go @@ -248,7 +248,8 @@ func (c *RaftCluster) Recover(onSet func(*zap.Logger, *semver.Version)) { c.members, c.removed = membersFromStore(c.lg, c.v2store) c.version = clusterVersionFromStore(c.lg, c.v2store) - mustDetectDowngrade(c.lg, c.version) + // TODO: add flag to control this check + //mustDetectDowngrade(c.lg, c.version) onSet(c.lg, c.version) for _, m := range c.members { @@ -567,7 +568,8 @@ func (c *RaftCluster) SetVersion(ver *semver.Version, onSet func(*zap.Logger, *s } oldVer := c.version c.version = ver - mustDetectDowngrade(c.lg, c.version) + // TODO: add flag to control this check + //mustDetectDowngrade(c.lg, c.version) if c.v2store != nil { mustSaveClusterVersionToStore(c.v2store, ver) } diff --git a/mvcc/kvstore.go b/mvcc/kvstore.go index d688dcd1cfa..ab92605aca2 100644 --- a/mvcc/kvstore.go +++ b/mvcc/kvstore.go @@ -43,6 +43,10 @@ var ( scheduledCompactKeyName = []byte("scheduledCompactRev") finishedCompactKeyName = []byte("finishedCompactRev") + // 3.5 meta keys that have to be deleted for downgrade + confStateKeyName = []byte("confState") + termKeyName = []byte("term") + ErrCompacted = errors.New("mvcc: required revision has been compacted") ErrFutureRev = errors.New("mvcc: required revision is a future revision") ErrCanceled = errors.New("mvcc: watcher is canceled") @@ -148,6 +152,8 @@ func NewStore(lg *zap.Logger, b backend.Backend, le lease.Lessor, ig ConsistentI tx.Lock() tx.UnsafeCreateBucket(keyBucketName) tx.UnsafeCreateBucket(metaBucketName) + // TODO: add flag to control this + downgradeMetaBucket(tx) tx.Unlock() s.b.ForceCommit() @@ -379,6 +385,9 @@ func (s *store) restore() error { tx := s.b.BatchTx() tx.Lock() + // TODO: add flag to control this + downgradeMetaBucket(tx) + _, finishedCompactBytes := tx.UnsafeRange(metaBucketName, finishedCompactKeyName, nil, 0) if len(finishedCompactBytes) != 0 { s.revMu.Lock() @@ -637,3 +646,9 @@ func appendMarkTombstone(lg *zap.Logger, b []byte) []byte { func isTombstone(b []byte) bool { return len(b) == markedRevBytesLen && b[markBytePosition] == markTombstone } + +// downgradeMetaBucket delete 3.5 specific keys to make backend fully compatible with 3.4 +func downgradeMetaBucket(tx backend.BatchTx) { + tx.UnsafeDelete(metaBucketName, confStateKeyName) + tx.UnsafeDelete(metaBucketName, termKeyName) +} diff --git a/mvcc/kvstore_test.go b/mvcc/kvstore_test.go index 672878fa60c..0a763287746 100644 --- a/mvcc/kvstore_test.go +++ b/mvcc/kvstore_test.go @@ -397,6 +397,8 @@ func TestStoreRestore(t *testing.T) { t.Errorf("current rev = %v, want 5", s.currentRev) } wact := []testutil.Action{ + {Name: "delete", Params: []interface{}{metaBucketName, confStateKeyName}}, + {Name: "delete", Params: []interface{}{metaBucketName, termKeyName}}, {Name: "range", Params: []interface{}{metaBucketName, finishedCompactKeyName, []byte(nil), int64(0)}}, {Name: "range", Params: []interface{}{metaBucketName, scheduledCompactKeyName, []byte(nil), int64(0)}}, {Name: "range", Params: []interface{}{keyBucketName, newTestRevBytes(revision{1, 0}), newTestRevBytes(revision{math.MaxInt64, math.MaxInt64}), int64(restoreChunkKeys)}},