Commit 64bfc7c8 authored by Hussein Galal's avatar Hussein Galal Committed by Brad Davidson

Allow for multiple etcd snapshot restoration (#2307)

* add reset tmp file Signed-off-by: 's avatargalal-hussein <hussein.galal.ahmed.11@gmail.com> * go imports Signed-off-by: 's avatargalal-hussein <hussein.galal.ahmed.11@gmail.com> * fix multiple lines string Signed-off-by: 's avatargalal-hussein <hussein.galal.ahmed.11@gmail.com> * fix typo Signed-off-by: 's avatargalal-hussein <hussein.galal.ahmed.11@gmail.com> * use resetFile function Signed-off-by: 's avatargalal-hussein <hussein.galal.ahmed.11@gmail.com>
parent 4a3f0e49
...@@ -5,11 +5,16 @@ package cluster ...@@ -5,11 +5,16 @@ package cluster
import ( import (
"context" "context"
"fmt"
"net/http" "net/http"
"os"
"strings" "strings"
"time" "time"
"github.com/rancher/k3s/pkg/etcd"
"github.com/rancher/k3s/pkg/cluster/managed" "github.com/rancher/k3s/pkg/cluster/managed"
"github.com/rancher/k3s/pkg/version"
"github.com/rancher/kine/pkg/endpoint" "github.com/rancher/kine/pkg/endpoint"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
) )
...@@ -47,13 +52,23 @@ func (c *Cluster) testClusterDB(ctx context.Context) (<-chan struct{}, error) { ...@@ -47,13 +52,23 @@ func (c *Cluster) testClusterDB(ctx context.Context) (<-chan struct{}, error) {
// start starts the database, unless a cluster reset has been requested, in which case // start starts the database, unless a cluster reset has been requested, in which case
// it does that instead. // it does that instead.
func (c *Cluster) start(ctx context.Context) error { func (c *Cluster) start(ctx context.Context) error {
resetFile := etcd.ResetFile(c.config)
if c.managedDB == nil { if c.managedDB == nil {
return nil return nil
} }
if c.config.ClusterReset { if c.config.ClusterReset {
if _, err := os.Stat(resetFile); err != nil {
if !os.IsNotExist(err) {
return err
}
} else {
return fmt.Errorf("cluster-reset was successfully performed, please remove the cluster-reset flag and start %s normally, if you need to perform another cluster reset, you must first manually delete the %s file", version.Program, resetFile)
}
return c.managedDB.Reset(ctx, c.clientAccessInfo) return c.managedDB.Reset(ctx, c.clientAccessInfo)
} }
// removing the reset file and ignore error if the file doesnt exist
os.Remove(resetFile)
return c.managedDB.Start(ctx, c.clientAccessInfo) return c.managedDB.Start(ctx, c.clientAccessInfo)
} }
......
...@@ -120,6 +120,11 @@ func nameFile(config *config.Control) string { ...@@ -120,6 +120,11 @@ func nameFile(config *config.Control) string {
return filepath.Join(etcdDBDir(config), "name") return filepath.Join(etcdDBDir(config), "name")
} }
// ResetFile returns the path to etcdDBDir/reset-flag
func ResetFile(config *config.Control) string {
return filepath.Join(config.DataDir, "db", "reset-flag")
}
// IsInitialized checks to see if a WAL directory exists. If so, we assume that etcd // IsInitialized checks to see if a WAL directory exists. If so, we assume that etcd
// has already been brought up at least once. // has already been brought up at least once.
func (e *ETCD) IsInitialized(ctx context.Context, config *config.Control) (bool, error) { func (e *ETCD) IsInitialized(ctx context.Context, config *config.Control) (bool, error) {
...@@ -171,7 +176,10 @@ func (e *ETCD) Reset(ctx context.Context, clientAccessInfo *clientaccess.Info) e ...@@ -171,7 +176,10 @@ func (e *ETCD) Reset(ctx context.Context, clientAccessInfo *clientaccess.Info) e
if err := e.setName(true); err != nil { if err := e.setName(true); err != nil {
return err return err
} }
// touch a file to avoid multiple resets
if err := ioutil.WriteFile(ResetFile(e.config), []byte{}, 0600); err != nil {
return err
}
return e.newCluster(ctx, true) return e.newCluster(ctx, true)
} }
...@@ -632,34 +640,28 @@ func (e *ETCD) setSnapshotFunction(ctx context.Context) { ...@@ -632,34 +640,28 @@ func (e *ETCD) setSnapshotFunction(ctx context.Context) {
// completion. // completion.
func (e *ETCD) Restore(ctx context.Context) error { func (e *ETCD) Restore(ctx context.Context) error {
// check the old etcd data dir // check the old etcd data dir
oldDataDir := etcdDBDir(e.config) + "-old" oldDataDir := etcdDBDir(e.config) + "-old-" + strconv.Itoa(int(time.Now().Unix()))
if s, err := os.Stat(oldDataDir); err == nil && s.IsDir() { if e.config.ClusterResetRestorePath == "" {
logrus.Infof("Etcd already restored from a snapshot. Restart without --snapshot-restore-path flag. Backup and delete ${datadir}/server/db on each peer etcd server and rejoin the nodes") return errors.New("no etcd restore path was specified")
os.Exit(0) }
} else if os.IsNotExist(err) { // make sure snapshot exists before restoration
if e.config.ClusterResetRestorePath == "" { if _, err := os.Stat(e.config.ClusterResetRestorePath); err != nil {
return errors.New("no etcd restore path was specified") return err
} }
// make sure snapshot exists before restoration // move the data directory to a temp path
if _, err := os.Stat(e.config.ClusterResetRestorePath); err != nil { if err := os.Rename(etcdDBDir(e.config), oldDataDir); err != nil {
return err return err
} }
// move the data directory to a temp path logrus.Infof("Pre-restore etcd database moved to %s", oldDataDir)
if err := os.Rename(etcdDBDir(e.config), oldDataDir); err != nil { sManager := snapshot.NewV3(nil)
return err if err := sManager.Restore(snapshot.RestoreConfig{
} SnapshotPath: e.config.ClusterResetRestorePath,
sManager := snapshot.NewV3(nil) Name: e.name,
if err := sManager.Restore(snapshot.RestoreConfig{ OutputDataDir: etcdDBDir(e.config),
SnapshotPath: e.config.ClusterResetRestorePath, OutputWALDir: walDir(e.config),
Name: e.name, PeerURLs: []string{e.peerURL()},
OutputDataDir: etcdDBDir(e.config), InitialCluster: e.name + "=" + e.peerURL(),
OutputWALDir: walDir(e.config), }); err != nil {
PeerURLs: []string{e.peerURL()},
InitialCluster: e.name + "=" + e.peerURL(),
}); err != nil {
return err
}
} else {
return err return err
} }
return nil return nil
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment