@@ -31,9 +31,13 @@ import (
3131	"github.com/coreos/go-semver/semver" 
3232	"go.uber.org/zap" 
3333
34+ 	"go.etcd.io/etcd/api/v3/version" 
3435	"go.etcd.io/etcd/client/pkg/v3/fileutil" 
3536	"go.etcd.io/etcd/pkg/v3/expect" 
3637	"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" 
3741	"go.etcd.io/etcd/tests/v3/framework/config" 
3842)
3943
@@ -60,6 +64,8 @@ type EtcdProcess interface {
6064	LazyFS () * LazyFS 
6165	Logs () LogsExpect 
6266	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 
6369}
6470
6571type  LogsExpect  interface  {
@@ -253,6 +259,34 @@ func (ep *EtcdServerProcess) Close() error {
253259	return  nil 
254260}
255261
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+ 
256290func  (ep  * EtcdServerProcess ) waitReady (ctx  context.Context ) error  {
257291	defer  close (ep .donec )
258292	return  WaitReadyExpectProc (ctx , ep .proc , EtcdServerReadyLines )
0 commit comments