github.com/ian-lewis-cs/etcd@v0.3.1-0.20140223024957-4c17dc343197/etcd.go (about) 1 /* 2 Copyright 2013 CoreOS Inc. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package main 18 19 import ( 20 "fmt" 21 "net" 22 "net/http" 23 "os" 24 "path/filepath" 25 "runtime" 26 "time" 27 28 "github.com/coreos/etcd/third_party/github.com/coreos/raft" 29 30 "github.com/coreos/etcd/config" 31 ehttp "github.com/coreos/etcd/http" 32 "github.com/coreos/etcd/log" 33 "github.com/coreos/etcd/metrics" 34 "github.com/coreos/etcd/server" 35 "github.com/coreos/etcd/store" 36 ) 37 38 func main() { 39 // Load configuration. 40 var config = config.New() 41 if err := config.Load(os.Args[1:]); err != nil { 42 fmt.Println(server.Usage() + "\n") 43 fmt.Println(err.Error() + "\n") 44 os.Exit(1) 45 } else if config.ShowVersion { 46 fmt.Println("etcd version", server.ReleaseVersion) 47 os.Exit(0) 48 } else if config.ShowHelp { 49 fmt.Println(server.Usage() + "\n") 50 os.Exit(0) 51 } 52 53 // Enable options. 54 if config.VeryVeryVerbose { 55 log.Verbose = true 56 raft.SetLogLevel(raft.Trace) 57 } else if config.VeryVerbose { 58 log.Verbose = true 59 raft.SetLogLevel(raft.Debug) 60 } else if config.Verbose { 61 log.Verbose = true 62 } 63 if config.CPUProfileFile != "" { 64 profile(config.CPUProfileFile) 65 } 66 67 if config.DataDir == "" { 68 log.Fatal("The data dir was not set and could not be guessed from machine name") 69 } 70 71 // Create data directory if it doesn't already exist. 72 if err := os.MkdirAll(config.DataDir, 0744); err != nil { 73 log.Fatalf("Unable to create path: %s", err) 74 } 75 76 // Warn people if they have an info file 77 info := filepath.Join(config.DataDir, "info") 78 if _, err := os.Stat(info); err == nil { 79 log.Warnf("All cached configuration is now ignored. The file %s can be removed.", info) 80 } 81 82 var mbName string 83 if config.Trace() { 84 mbName = config.MetricsBucketName() 85 runtime.SetBlockProfileRate(1) 86 } 87 88 mb := metrics.NewBucket(mbName) 89 90 if config.GraphiteHost != "" { 91 err := mb.Publish(config.GraphiteHost) 92 if err != nil { 93 panic(err) 94 } 95 } 96 97 // Retrieve CORS configuration 98 corsInfo, err := ehttp.NewCORSInfo(config.CorsOrigins) 99 if err != nil { 100 log.Fatal("CORS:", err) 101 } 102 103 // Create etcd key-value store and registry. 104 store := store.New() 105 registry := server.NewRegistry(store) 106 107 // Create stats objects 108 followersStats := server.NewRaftFollowersStats(config.Name) 109 serverStats := server.NewRaftServerStats(config.Name) 110 111 // Calculate all of our timeouts 112 heartbeatInterval := time.Duration(config.Peer.HeartbeatInterval) * time.Millisecond 113 electionTimeout := time.Duration(config.Peer.ElectionTimeout) * time.Millisecond 114 dialTimeout := (3 * heartbeatInterval) + electionTimeout 115 responseHeaderTimeout := (3 * heartbeatInterval) + electionTimeout 116 117 // Create peer server 118 psConfig := server.PeerServerConfig{ 119 Name: config.Name, 120 Scheme: config.PeerTLSInfo().Scheme(), 121 URL: config.Peer.Addr, 122 SnapshotCount: config.SnapshotCount, 123 MaxClusterSize: config.MaxClusterSize, 124 RetryTimes: config.MaxRetryAttempts, 125 RetryInterval: config.RetryInterval, 126 } 127 ps := server.NewPeerServer(psConfig, registry, store, &mb, followersStats, serverStats) 128 129 var psListener net.Listener 130 if psConfig.Scheme == "https" { 131 peerServerTLSConfig, err := config.PeerTLSInfo().ServerConfig() 132 if err != nil { 133 log.Fatal("peer server TLS error: ", err) 134 } 135 136 psListener, err = server.NewTLSListener(config.Peer.BindAddr, peerServerTLSConfig) 137 if err != nil { 138 log.Fatal("Failed to create peer listener: ", err) 139 } 140 } else { 141 psListener, err = server.NewListener(config.Peer.BindAddr) 142 if err != nil { 143 log.Fatal("Failed to create peer listener: ", err) 144 } 145 } 146 147 // Create raft transporter and server 148 raftTransporter := server.NewTransporter(followersStats, serverStats, registry, heartbeatInterval, dialTimeout, responseHeaderTimeout) 149 if psConfig.Scheme == "https" { 150 raftClientTLSConfig, err := config.PeerTLSInfo().ClientConfig() 151 if err != nil { 152 log.Fatal("raft client TLS error: ", err) 153 } 154 raftTransporter.SetTLSConfig(*raftClientTLSConfig) 155 } 156 raftServer, err := raft.NewServer(config.Name, config.DataDir, raftTransporter, store, ps, "") 157 if err != nil { 158 log.Fatal(err) 159 } 160 raftServer.SetElectionTimeout(electionTimeout) 161 raftServer.SetHeartbeatInterval(heartbeatInterval) 162 ps.SetRaftServer(raftServer) 163 164 // Create etcd server 165 s := server.New(config.Name, config.Addr, ps, registry, store, &mb) 166 167 if config.Trace() { 168 s.EnableTracing() 169 } 170 171 var sListener net.Listener 172 if config.EtcdTLSInfo().Scheme() == "https" { 173 etcdServerTLSConfig, err := config.EtcdTLSInfo().ServerConfig() 174 if err != nil { 175 log.Fatal("etcd TLS error: ", err) 176 } 177 178 sListener, err = server.NewTLSListener(config.BindAddr, etcdServerTLSConfig) 179 if err != nil { 180 log.Fatal("Failed to create TLS etcd listener: ", err) 181 } 182 } else { 183 sListener, err = server.NewListener(config.BindAddr) 184 if err != nil { 185 log.Fatal("Failed to create etcd listener: ", err) 186 } 187 } 188 189 ps.SetServer(s) 190 ps.Start(config.Snapshot, config.Discovery, config.Peers) 191 192 go func() { 193 log.Infof("peer server [name %s, listen on %s, advertised url %s]", ps.Config.Name, psListener.Addr(), ps.Config.URL) 194 sHTTP := &ehttp.CORSHandler{ps.HTTPHandler(), corsInfo} 195 log.Fatal(http.Serve(psListener, sHTTP)) 196 }() 197 198 log.Infof("etcd server [name %s, listen on %s, advertised url %s]", s.Name, sListener.Addr(), s.URL()) 199 sHTTP := &ehttp.CORSHandler{s.HTTPHandler(), corsInfo} 200 log.Fatal(http.Serve(sListener, sHTTP)) 201 }