@@ -31,9 +31,13 @@ import (
31
31
"github.com/coreos/go-semver/semver"
32
32
"go.uber.org/zap"
33
33
34
+ "go.etcd.io/etcd/api/v3/version"
34
35
"go.etcd.io/etcd/client/pkg/v3/fileutil"
35
36
"go.etcd.io/etcd/pkg/v3/expect"
36
37
"go.etcd.io/etcd/pkg/v3/proxy"
38
+ "go.etcd.io/etcd/server/v3/storage/backend"
39
+ "go.etcd.io/etcd/server/v3/storage/datadir"
40
+ "go.etcd.io/etcd/server/v3/storage/schema"
37
41
"go.etcd.io/etcd/tests/v3/framework/config"
38
42
)
39
43
@@ -60,6 +64,8 @@ type EtcdProcess interface {
60
64
LazyFS () * LazyFS
61
65
Logs () LogsExpect
62
66
Kill () error
67
+ // VerifySchemaVersion verifies the db file schema version is compatible with the binary after the process is closed.
68
+ VerifySchemaVersion (lg * zap.Logger ) error
63
69
}
64
70
65
71
type LogsExpect interface {
@@ -253,6 +259,34 @@ func (ep *EtcdServerProcess) Close() error {
253
259
return nil
254
260
}
255
261
262
+ func (ep * EtcdServerProcess ) VerifySchemaVersion (lg * zap.Logger ) error {
263
+ dbPath := datadir .ToBackendFileName (ep .cfg .DataDirPath )
264
+ be := backend .NewDefaultBackend (lg , dbPath )
265
+ defer be .Close ()
266
+ ver , err := schema .UnsafeDetectSchemaVersion (lg , be .BatchTx ())
267
+ if err != nil {
268
+ return err
269
+ }
270
+ maxStorageVersion := version .V3_6
271
+ if ep .cfg .ExecPath == BinPath .EtcdLastRelease {
272
+ maxStorageVersion = version .V3_5
273
+ }
274
+ // in a mix version cluster, the storage version would be set to the cluster version,
275
+ // which could be lower than the server version by 1 minor version.
276
+ if ! ver .LessThan (maxStorageVersion ) && ! ver .Equal (maxStorageVersion ) {
277
+ return fmt .Errorf ("expect backend schema version to be <= %s, but got %s" , maxStorageVersion .String (), ver .String ())
278
+ }
279
+ // check new fields introduced in V3_6 do not exist in V3_5 data file.
280
+ // V3_6 contains all the fields in V3_5, so no need to check for V3_6 servers.
281
+ if maxStorageVersion == version .V3_5 {
282
+ _ , vs := be .BatchTx ().UnsafeRange (schema .Meta , schema .MetaStorageVersionName , nil , 1 )
283
+ if len (vs ) != 0 {
284
+ return fmt .Errorf ("expect storageVersion not exist in the meta bucket, but got %s" , string (vs [0 ]))
285
+ }
286
+ }
287
+ return nil
288
+ }
289
+
256
290
func (ep * EtcdServerProcess ) waitReady (ctx context.Context ) error {
257
291
defer close (ep .donec )
258
292
return WaitReadyExpectProc (ctx , ep .proc , EtcdServerReadyLines )
0 commit comments