mirror of
https://github.com/etcd-io/etcd.git
synced 2024-09-27 06:25:44 +00:00
Merge pull request #11725 from YoyinZyc/downgrade-api
[Etcd Downgrade] Store downgrade info to backend
This commit is contained in:
commit
0908a8bd10
@ -59,6 +59,16 @@ type RaftCluster struct {
|
|||||||
// removed contains the ids of removed members in the cluster.
|
// removed contains the ids of removed members in the cluster.
|
||||||
// removed id cannot be reused.
|
// removed id cannot be reused.
|
||||||
removed map[types.ID]bool
|
removed map[types.ID]bool
|
||||||
|
|
||||||
|
downgradeInfo *DowngradeInfo
|
||||||
|
}
|
||||||
|
|
||||||
|
type DowngradeInfo struct {
|
||||||
|
// TargetVersion is the target downgrade version, if the cluster is not under downgrading,
|
||||||
|
// the targetVersion will be an empty string
|
||||||
|
TargetVersion string `json:"target-version"`
|
||||||
|
// Enabled indicates whether the cluster is enabled to downgrade
|
||||||
|
Enabled bool `json:"enabled"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// ConfigChangeContext represents a context for confChange.
|
// ConfigChangeContext represents a context for confChange.
|
||||||
@ -106,6 +116,7 @@ func NewCluster(lg *zap.Logger, token string) *RaftCluster {
|
|||||||
token: token,
|
token: token,
|
||||||
members: make(map[types.ID]*Member),
|
members: make(map[types.ID]*Member),
|
||||||
removed: make(map[types.ID]bool),
|
removed: make(map[types.ID]bool),
|
||||||
|
downgradeInfo: &DowngradeInfo{Enabled: false},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -691,6 +702,39 @@ func clusterVersionFromBackend(lg *zap.Logger, be backend.Backend) *semver.Versi
|
|||||||
return semver.Must(semver.NewVersion(string(vals[0])))
|
return semver.Must(semver.NewVersion(string(vals[0])))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func downgradeInfoFromBackend(lg *zap.Logger, be backend.Backend) *DowngradeInfo {
|
||||||
|
dkey := backendDowngradeKey()
|
||||||
|
tx := be.ReadTx()
|
||||||
|
tx.Lock()
|
||||||
|
defer tx.Unlock()
|
||||||
|
keys, vals := tx.UnsafeRange(clusterBucketName, dkey, nil, 0)
|
||||||
|
if len(keys) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(keys) != 1 {
|
||||||
|
lg.Panic(
|
||||||
|
"unexpected number of keys when getting cluster version from backend",
|
||||||
|
zap.Int("number-of-key", len(keys)),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
var d DowngradeInfo
|
||||||
|
if err := json.Unmarshal(vals[0], &d); err != nil {
|
||||||
|
lg.Panic("failed to unmarshal downgrade information", zap.Error(err))
|
||||||
|
}
|
||||||
|
|
||||||
|
// verify the downgrade info from backend
|
||||||
|
if d.Enabled {
|
||||||
|
if _, err := semver.NewVersion(d.TargetVersion); err != nil {
|
||||||
|
lg.Panic(
|
||||||
|
"unexpected version format of the downgrade target version from backend",
|
||||||
|
zap.String("target-version", d.TargetVersion),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return &d
|
||||||
|
}
|
||||||
|
|
||||||
// ValidateClusterAndAssignIDs validates the local cluster by matching the PeerURLs
|
// ValidateClusterAndAssignIDs validates the local cluster by matching the PeerURLs
|
||||||
// with the existing cluster. If the validation succeeds, it assigns the IDs
|
// with the existing cluster. If the validation succeeds, it assigns the IDs
|
||||||
// from the existing cluster to the local cluster.
|
// from the existing cluster to the local cluster.
|
||||||
@ -752,6 +796,36 @@ func (c *RaftCluster) IsLocalMemberLearner() bool {
|
|||||||
return localMember.IsLearner
|
return localMember.IsLearner
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DowngradeInfo returns the downgrade status of the cluster
|
||||||
|
func (c *RaftCluster) DowngradeInfo() *DowngradeInfo {
|
||||||
|
c.Lock()
|
||||||
|
defer c.Unlock()
|
||||||
|
if c.downgradeInfo == nil {
|
||||||
|
return &DowngradeInfo{Enabled: false}
|
||||||
|
}
|
||||||
|
d := &DowngradeInfo{Enabled: c.downgradeInfo.Enabled, TargetVersion: c.downgradeInfo.TargetVersion}
|
||||||
|
return d
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *RaftCluster) SetDowngradeInfo(d *DowngradeInfo) {
|
||||||
|
c.Lock()
|
||||||
|
defer c.Unlock()
|
||||||
|
|
||||||
|
if c.be != nil {
|
||||||
|
mustSaveDowngradeToBackend(c.lg, c.be, d)
|
||||||
|
}
|
||||||
|
|
||||||
|
c.downgradeInfo = d
|
||||||
|
|
||||||
|
if d.Enabled {
|
||||||
|
c.lg.Info(
|
||||||
|
"The server is ready to downgrade",
|
||||||
|
zap.String("target-version", d.TargetVersion),
|
||||||
|
zap.String("server-version", version.Version),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// IsMemberExist returns if the member with the given id exists in cluster.
|
// IsMemberExist returns if the member with the given id exists in cluster.
|
||||||
func (c *RaftCluster) IsMemberExist(id types.ID) bool {
|
func (c *RaftCluster) IsMemberExist(id types.ID) bool {
|
||||||
c.Lock()
|
c.Lock()
|
||||||
|
@ -53,8 +53,8 @@ func mustSaveMemberToBackend(lg *zap.Logger, be backend.Backend, m *Member) {
|
|||||||
|
|
||||||
tx := be.BatchTx()
|
tx := be.BatchTx()
|
||||||
tx.Lock()
|
tx.Lock()
|
||||||
|
defer tx.Unlock()
|
||||||
tx.UnsafePut(membersBucketName, mkey, mvalue)
|
tx.UnsafePut(membersBucketName, mkey, mvalue)
|
||||||
tx.Unlock()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func mustDeleteMemberFromBackend(be backend.Backend, id types.ID) {
|
func mustDeleteMemberFromBackend(be backend.Backend, id types.ID) {
|
||||||
@ -62,9 +62,9 @@ func mustDeleteMemberFromBackend(be backend.Backend, id types.ID) {
|
|||||||
|
|
||||||
tx := be.BatchTx()
|
tx := be.BatchTx()
|
||||||
tx.Lock()
|
tx.Lock()
|
||||||
|
defer tx.Unlock()
|
||||||
tx.UnsafeDelete(membersBucketName, mkey)
|
tx.UnsafeDelete(membersBucketName, mkey)
|
||||||
tx.UnsafePut(membersRemovedBucketName, mkey, []byte("removed"))
|
tx.UnsafePut(membersRemovedBucketName, mkey, []byte("removed"))
|
||||||
tx.Unlock()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func mustSaveClusterVersionToBackend(be backend.Backend, ver *semver.Version) {
|
func mustSaveClusterVersionToBackend(be backend.Backend, ver *semver.Version) {
|
||||||
@ -76,6 +76,18 @@ func mustSaveClusterVersionToBackend(be backend.Backend, ver *semver.Version) {
|
|||||||
tx.UnsafePut(clusterBucketName, ckey, []byte(ver.String()))
|
tx.UnsafePut(clusterBucketName, ckey, []byte(ver.String()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func mustSaveDowngradeToBackend(lg *zap.Logger, be backend.Backend, downgrade *DowngradeInfo) {
|
||||||
|
dkey := backendDowngradeKey()
|
||||||
|
dvalue, err := json.Marshal(downgrade)
|
||||||
|
if err != nil {
|
||||||
|
lg.Panic("failed to marshal downgrade information", zap.Error(err))
|
||||||
|
}
|
||||||
|
tx := be.BatchTx()
|
||||||
|
tx.Lock()
|
||||||
|
defer tx.Unlock()
|
||||||
|
tx.UnsafePut(clusterBucketName, dkey, dvalue)
|
||||||
|
}
|
||||||
|
|
||||||
func mustSaveMemberToStore(lg *zap.Logger, s v2store.Store, m *Member) {
|
func mustSaveMemberToStore(lg *zap.Logger, s v2store.Store, m *Member) {
|
||||||
b, err := json.Marshal(m.RaftAttributes)
|
b, err := json.Marshal(m.RaftAttributes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -184,6 +196,10 @@ func backendClusterVersionKey() []byte {
|
|||||||
return []byte("clusterVersion")
|
return []byte("clusterVersion")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func backendDowngradeKey() []byte {
|
||||||
|
return []byte("downgrade")
|
||||||
|
}
|
||||||
|
|
||||||
func mustCreateBackendBuckets(be backend.Backend) {
|
func mustCreateBackendBuckets(be backend.Backend) {
|
||||||
tx := be.BatchTx()
|
tx := be.BatchTx()
|
||||||
tx.Lock()
|
tx.Lock()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user