etcdserver: autodetect v0.4 WALs and upgrade them to v0.5 automatically

This commit is contained in:
Barak Michener 2014-11-18 13:43:20 -05:00
parent aca195f3ad
commit 78ea3335bf
2 changed files with 74 additions and 5 deletions

View File

@ -36,6 +36,7 @@ import (
"github.com/coreos/etcd/etcdserver/etcdhttp/httptypes" "github.com/coreos/etcd/etcdserver/etcdhttp/httptypes"
pb "github.com/coreos/etcd/etcdserver/etcdserverpb" pb "github.com/coreos/etcd/etcdserver/etcdserverpb"
"github.com/coreos/etcd/etcdserver/stats" "github.com/coreos/etcd/etcdserver/stats"
"github.com/coreos/etcd/migrate"
"github.com/coreos/etcd/pkg/pbutil" "github.com/coreos/etcd/pkg/pbutil"
"github.com/coreos/etcd/pkg/types" "github.com/coreos/etcd/pkg/types"
"github.com/coreos/etcd/pkg/wait" "github.com/coreos/etcd/pkg/wait"
@ -190,18 +191,39 @@ type EtcdServer struct {
raftLead uint64 raftLead uint64
} }
// UpgradeWAL converts an older version of the EtcdServer data to the newest version.
// It must ensure that, after upgrading, the most recent version is present.
func UpgradeWAL(cfg *ServerConfig, ver wal.WalVersion) {
if ver == wal.WALv0_4 {
err := migrate.Migrate4To5(cfg.DataDir, cfg.Name)
if err != nil {
log.Fatalf("Failed migrating data-dir: %v", err)
}
}
}
// NewServer creates a new EtcdServer from the supplied configuration. The // NewServer creates a new EtcdServer from the supplied configuration. The
// configuration is considered static for the lifetime of the EtcdServer. // configuration is considered static for the lifetime of the EtcdServer.
func NewServer(cfg *ServerConfig) (*EtcdServer, error) { func NewServer(cfg *ServerConfig) (*EtcdServer, error) {
if err := os.MkdirAll(cfg.SnapDir(), privateDirMode); err != nil {
return nil, fmt.Errorf("cannot create snapshot directory: %v", err)
}
ss := snap.New(cfg.SnapDir())
st := store.New() st := store.New()
var w *wal.WAL var w *wal.WAL
var n raft.Node var n raft.Node
var id types.ID var id types.ID
haveWAL := wal.Exist(cfg.WALDir()) walVersion := wal.DetectVersion(cfg.DataDir)
if walVersion == wal.UnknownWAL {
return nil, fmt.Errorf("unknown wal version in data dir %s", cfg.DataDir)
}
haveWAL := walVersion != wal.NoWAL
if haveWAL && walVersion != wal.WALv0_5 {
UpgradeWAL(cfg, walVersion)
}
if err := os.MkdirAll(cfg.SnapDir(), privateDirMode); err != nil {
return nil, fmt.Errorf("cannot create snapshot directory: %v", err)
}
ss := snap.New(cfg.SnapDir())
switch { switch {
case !haveWAL && !cfg.NewCluster: case !haveWAL && !cfg.NewCluster:
us := getOtherPeerURLs(cfg.Cluster, cfg.Name) us := getOtherPeerURLs(cfg.Cluster, cfg.Name)

View File

@ -20,8 +20,55 @@ import (
"fmt" "fmt"
"log" "log"
"os" "os"
"path"
) )
type StringSlice []string
func containsStrings(source, target []string) bool {
for _, t := range target {
ok := false
for _, s := range source {
if t == s {
ok = true
}
}
if !ok {
return false
}
}
return true
}
// WalVersion is an enum for versions of etcd logs.
type WalVersion string
const (
UnknownWAL WalVersion = "Unknown WAL"
NoWAL WalVersion = "No WAL"
WALv0_4 WalVersion = "0.4.x"
WALv0_5 WalVersion = "0.5.x"
)
func DetectVersion(dirpath string) WalVersion {
names, err := readDir(dirpath)
if err != nil || len(names) == 0 {
return NoWAL
}
if containsStrings(names, []string{"snap", "wal"}) {
// .../wal cannot be empty to exist.
if Exist(path.Join(dirpath, "wal")) {
return WALv0_5
}
return NoWAL
}
if containsStrings(names, []string{"snapshot", "conf", "log"}) {
return WALv0_4
}
return UnknownWAL
}
func Exist(dirpath string) bool { func Exist(dirpath string) bool {
names, err := readDir(dirpath) names, err := readDir(dirpath)
if err != nil { if err != nil {