From 0847986d4afbdf8d0e8569915b817a3fe90f0ec5 Mon Sep 17 00:00:00 2001 From: Xiang Li Date: Tue, 17 Mar 2015 14:43:20 -0700 Subject: [PATCH] etcdmain: identify data dir type --- etcdmain/etcd.go | 65 ++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 55 insertions(+), 10 deletions(-) diff --git a/etcdmain/etcd.go b/etcdmain/etcd.go index 904c456f3..1f8459e48 100644 --- a/etcdmain/etcd.go +++ b/etcdmain/etcd.go @@ -31,6 +31,7 @@ import ( "github.com/coreos/etcd/etcdserver" "github.com/coreos/etcd/etcdserver/etcdhttp" "github.com/coreos/etcd/pkg/cors" + "github.com/coreos/etcd/pkg/fileutil" "github.com/coreos/etcd/pkg/osutil" "github.com/coreos/etcd/pkg/transport" "github.com/coreos/etcd/pkg/types" @@ -38,11 +39,19 @@ import ( "github.com/coreos/etcd/rafthttp" ) +type dirType string + const ( // the owner can make/remove files inside the directory privateDirMode = 0700 ) +var ( + dirMember = dirType("member") + dirProxy = dirType("proxy") + dirEmpty = dirType("empty") +) + func Main() { cfg := NewConfig() err := cfg.Parse(os.Args[1:]) @@ -53,7 +62,17 @@ func Main() { var stopped <-chan struct{} - shouldProxy := cfg.isProxy() + if cfg.dir == "" { + cfg.dir = fmt.Sprintf("%v.etcd", cfg.name) + log.Printf("etcd: no data-dir provided, using default data-dir ./%s", cfg.dir) + } + + which := identifyDataDirOrDie(cfg.dir) + if which != dirEmpty { + log.Printf("etcd: already initialized as %v before, starting as etcd %v...", which, which) + } + + shouldProxy := cfg.isProxy() || which == dirProxy if !shouldProxy { stopped, err = startEtcd(cfg) if err == discovery.ErrFullCluster && cfg.shouldFallbackToProxy() { @@ -87,11 +106,6 @@ func startEtcd(cfg *config) (<-chan struct{}, error) { return nil, fmt.Errorf("error setting up initial cluster: %v", err) } - if cfg.dir == "" { - cfg.dir = fmt.Sprintf("%v.etcd", cfg.name) - log.Printf("no data-dir provided, using default data-dir ./%s", cfg.dir) - } - pt, err := transport.NewTimeoutTransport(cfg.peerTLSInfo, rafthttp.ConnReadTimeout, rafthttp.ConnWriteTimeout) if err != nil { return nil, err @@ -218,10 +232,6 @@ func startProxy(cfg *config) error { return err } - if cfg.dir == "" { - cfg.dir = fmt.Sprintf("%v.etcd", cfg.name) - log.Printf("no proxy data-dir provided, using default proxy data-dir ./%s", cfg.dir) - } cfg.dir = path.Join(cfg.dir, "proxy") err = os.MkdirAll(cfg.dir, 0700) if err != nil { @@ -340,3 +350,38 @@ func genClusterString(name string, urls types.URLs) string { } return strings.Join(addrs, ",") } + +// identifyDataDirOrDie returns the type of the data dir. +// Dies if the datadir is invalid. +func identifyDataDirOrDie(dir string) dirType { + names, err := fileutil.ReadDir(dir) + if err != nil { + if os.IsNotExist(err) { + return dirEmpty + } + log.Fatalf("etcd: error listing data dir: %s", dir) + } + + var m, p bool + for _, name := range names { + switch dirType(name) { + case dirMember: + m = true + case dirProxy: + p = true + default: + log.Printf("etcd: found invalid file/dir %s under data dir %s (Ignore this if you are upgrading etcd)", name, dir) + } + } + + if m && p { + log.Fatal("etcd: invalid datadir. Both member and proxy directories exist.") + } + if m { + return dirMember + } + if p { + return dirProxy + } + return dirEmpty +}