mirror of
https://github.com/etcd-io/etcd.git
synced 2024-09-27 06:25:44 +00:00
Allow updateClusterVersion when downgrading from 3.5.
Signed-off-by: Siyuan Zhang <sizhang@google.com>
This commit is contained in:
parent
6093ab9033
commit
0d62c99777
@ -789,6 +789,15 @@ func ValidateClusterAndAssignIDs(lg *zap.Logger, local *RaftCluster, existing *R
|
||||
return nil
|
||||
}
|
||||
|
||||
// isValidDowngrade verifies whether the cluster can be downgraded from verFrom to verTo
|
||||
func isValidDowngrade(verFrom *semver.Version, verTo *semver.Version) bool {
|
||||
allowedDowngradeVersion := semver.Version{
|
||||
Major: verFrom.Major,
|
||||
Minor: verFrom.Minor - 1,
|
||||
}
|
||||
return verTo.Equal(allowedDowngradeVersion)
|
||||
}
|
||||
|
||||
func mustDetectDowngrade(lg *zap.Logger, cv *semver.Version, nextClusterVersionCompatible bool) {
|
||||
err := detectDowngrade(cv, nextClusterVersionCompatible)
|
||||
if err != nil {
|
||||
@ -825,6 +834,22 @@ func detectDowngrade(cv *semver.Version, nextClusterVersionCompatible bool) erro
|
||||
return nil
|
||||
}
|
||||
|
||||
// IsValidClusterVersionChange checks the two scenario when version is valid to change:
|
||||
// 1. Downgrade: cluster version is 1 minor version higher than local version,
|
||||
// cluster version should change.
|
||||
// 2. Cluster start: when not all members version are available, cluster version
|
||||
// is set to MinVersion(3.0), when all members are at higher version, cluster version
|
||||
// is lower than minimal server version, cluster version should change
|
||||
func IsValidClusterVersionChange(verFrom *semver.Version, verTo *semver.Version, nextClusterVersionCompatible bool) bool {
|
||||
verFrom = &semver.Version{Major: verFrom.Major, Minor: verFrom.Minor}
|
||||
verTo = &semver.Version{Major: verTo.Major, Minor: verTo.Minor}
|
||||
|
||||
if (nextClusterVersionCompatible && isValidDowngrade(verFrom, verTo)) || (verFrom.Major == verTo.Major && verFrom.LessThan(*verTo)) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// IsLocalMemberLearner returns if the local member is raft learner
|
||||
func (c *RaftCluster) IsLocalMemberLearner() bool {
|
||||
c.Lock()
|
||||
|
@ -22,6 +22,7 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/coreos/go-semver/semver"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"go.etcd.io/etcd/etcdserver/api/v2store"
|
||||
"go.etcd.io/etcd/pkg/mock/mockstore"
|
||||
"go.etcd.io/etcd/pkg/testutil"
|
||||
@ -948,6 +949,83 @@ func TestIsReadyToPromoteMember(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestIsVersionChangable(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
verFrom string
|
||||
verTo string
|
||||
nextClusterVersionCompatible bool
|
||||
expectedResult bool
|
||||
}{
|
||||
{
|
||||
name: "When local version is one minor lower than cluster version in downgrade mode",
|
||||
verFrom: "3.5.0",
|
||||
verTo: "3.4.0",
|
||||
nextClusterVersionCompatible: true,
|
||||
expectedResult: true,
|
||||
},
|
||||
{
|
||||
name: "When local version is one minor lower than cluster version not in downgrade mode",
|
||||
verFrom: "3.5.0",
|
||||
verTo: "3.4.0",
|
||||
expectedResult: false,
|
||||
},
|
||||
{
|
||||
name: "When local version is one minor and one patch lower than cluster version in downgrade mode",
|
||||
verFrom: "3.5.2",
|
||||
verTo: "3.4.1",
|
||||
nextClusterVersionCompatible: true,
|
||||
expectedResult: true,
|
||||
},
|
||||
{
|
||||
name: "When local version is one minor higher than cluster version",
|
||||
verFrom: "3.3.0",
|
||||
verTo: "3.4.0",
|
||||
expectedResult: true,
|
||||
},
|
||||
{
|
||||
name: "When local version is two minor higher than cluster version",
|
||||
verFrom: "3.2.0",
|
||||
verTo: "3.4.0",
|
||||
expectedResult: true,
|
||||
},
|
||||
{
|
||||
name: "When local version is one major higher than cluster version",
|
||||
verFrom: "2.4.0",
|
||||
verTo: "3.4.0",
|
||||
expectedResult: false,
|
||||
},
|
||||
{
|
||||
name: "When local version is equal to cluster version",
|
||||
verFrom: "3.4.0",
|
||||
verTo: "3.4.0",
|
||||
expectedResult: false,
|
||||
},
|
||||
{
|
||||
name: "When local version is one patch higher than cluster version",
|
||||
verFrom: "3.4.0",
|
||||
verTo: "3.4.1",
|
||||
expectedResult: false,
|
||||
},
|
||||
{
|
||||
name: "When local version is two minor lower than cluster version",
|
||||
verFrom: "3.6.0",
|
||||
verTo: "3.4.0",
|
||||
nextClusterVersionCompatible: true,
|
||||
expectedResult: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
verFrom := semver.Must(semver.NewVersion(tt.verFrom))
|
||||
verTo := semver.Must(semver.NewVersion(tt.verTo))
|
||||
ret := IsValidClusterVersionChange(verFrom, verTo, tt.nextClusterVersionCompatible)
|
||||
assert.Equal(t, tt.expectedResult, ret)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestDetectDowngrade(t *testing.T) {
|
||||
tests := []struct {
|
||||
clusterVersion string
|
||||
|
@ -2636,8 +2636,8 @@ func (s *EtcdServer) monitorVersions() {
|
||||
}
|
||||
|
||||
// update cluster version only if the decided version is greater than
|
||||
// the current cluster version
|
||||
if v != nil && s.cluster.Version().LessThan(*v) {
|
||||
// the current cluster version or it is a valid downgrade
|
||||
if v != nil && membership.IsValidClusterVersionChange(s.cluster.Version(), v, s.Config().NextClusterVersionCompatible) {
|
||||
s.goAttach(func() { s.updateClusterVersion(v.String()) })
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user