github.com/qorio/etcd@v0.1.2-0.20131003183127-5cc585af9618/etcd.go (about) 1 package main 2 3 import ( 4 "crypto/tls" 5 "flag" 6 "fmt" 7 "io/ioutil" 8 "net/url" 9 "os" 10 "strings" 11 "time" 12 13 "github.com/coreos/etcd/store" 14 "github.com/coreos/go-raft" 15 ) 16 17 //------------------------------------------------------------------------------ 18 // 19 // Initialization 20 // 21 //------------------------------------------------------------------------------ 22 23 var ( 24 verbose bool 25 veryVerbose bool 26 27 machines string 28 machinesFile string 29 30 cluster []string 31 32 argInfo Info 33 dirPath string 34 35 force bool 36 37 maxSize int 38 39 snapshot bool 40 41 retryTimes int 42 43 maxClusterSize int 44 45 cpuprofile string 46 47 cors string 48 corsList map[string]bool 49 ) 50 51 func init() { 52 flag.BoolVar(&verbose, "v", false, "verbose logging") 53 flag.BoolVar(&veryVerbose, "vv", false, "very verbose logging") 54 55 flag.StringVar(&machines, "C", "", "the ip address and port of a existing machines in the cluster, sepearate by comma") 56 flag.StringVar(&machinesFile, "CF", "", "the file contains a list of existing machines in the cluster, seperate by comma") 57 58 flag.StringVar(&argInfo.Name, "n", "default-name", "the node name (required)") 59 flag.StringVar(&argInfo.EtcdURL, "c", "127.0.0.1:4001", "the advertised public hostname:port for etcd client communication") 60 flag.StringVar(&argInfo.RaftURL, "s", "127.0.0.1:7001", "the advertised public hostname:port for raft server communication") 61 flag.StringVar(&argInfo.EtcdListenHost, "cl", "", "the listening hostname for etcd client communication (defaults to advertised ip)") 62 flag.StringVar(&argInfo.RaftListenHost, "sl", "", "the listening hostname for raft server communication (defaults to advertised ip)") 63 flag.StringVar(&argInfo.WebURL, "w", "", "the hostname:port of web interface") 64 65 flag.StringVar(&argInfo.RaftTLS.CAFile, "serverCAFile", "", "the path of the CAFile") 66 flag.StringVar(&argInfo.RaftTLS.CertFile, "serverCert", "", "the cert file of the server") 67 flag.StringVar(&argInfo.RaftTLS.KeyFile, "serverKey", "", "the key file of the server") 68 69 flag.StringVar(&argInfo.EtcdTLS.CAFile, "clientCAFile", "", "the path of the client CAFile") 70 flag.StringVar(&argInfo.EtcdTLS.CertFile, "clientCert", "", "the cert file of the client") 71 flag.StringVar(&argInfo.EtcdTLS.KeyFile, "clientKey", "", "the key file of the client") 72 73 flag.StringVar(&dirPath, "d", ".", "the directory to store log and snapshot") 74 75 flag.BoolVar(&force, "f", false, "force new node configuration if existing is found (WARNING: data loss!)") 76 77 flag.BoolVar(&snapshot, "snapshot", false, "open or close snapshot") 78 79 flag.IntVar(&maxSize, "m", 1024, "the max size of result buffer") 80 81 flag.IntVar(&retryTimes, "r", 3, "the max retry attempts when trying to join a cluster") 82 83 flag.IntVar(&maxClusterSize, "maxsize", 9, "the max size of the cluster") 84 85 flag.StringVar(&cpuprofile, "cpuprofile", "", "write cpu profile to file") 86 87 flag.StringVar(&cors, "cors", "", "whitelist origins for cross-origin resource sharing (e.g. '*' or 'http://localhost:8001,etc')") 88 } 89 90 const ( 91 ElectionTimeout = 200 * time.Millisecond 92 HeartbeatTimeout = 50 * time.Millisecond 93 RetryInterval = 10 94 ) 95 96 //------------------------------------------------------------------------------ 97 // 98 // Typedefs 99 // 100 //------------------------------------------------------------------------------ 101 102 type TLSInfo struct { 103 CertFile string `json:"CertFile"` 104 KeyFile string `json:"KeyFile"` 105 CAFile string `json:"CAFile"` 106 } 107 108 type Info struct { 109 Name string `json:"name"` 110 111 RaftURL string `json:"raftURL"` 112 EtcdURL string `json:"etcdURL"` 113 WebURL string `json:"webURL"` 114 115 RaftListenHost string `json:"raftListenHost"` 116 EtcdListenHost string `json:"etcdListenHost"` 117 118 RaftTLS TLSInfo `json:"raftTLS"` 119 EtcdTLS TLSInfo `json:"etcdTLS"` 120 } 121 122 type TLSConfig struct { 123 Scheme string 124 Server tls.Config 125 Client tls.Config 126 } 127 128 //------------------------------------------------------------------------------ 129 // 130 // Variables 131 // 132 //------------------------------------------------------------------------------ 133 134 var etcdStore *store.Store 135 136 //------------------------------------------------------------------------------ 137 // 138 // Functions 139 // 140 //------------------------------------------------------------------------------ 141 142 //-------------------------------------- 143 // Main 144 //-------------------------------------- 145 146 func main() { 147 flag.Parse() 148 149 if cpuprofile != "" { 150 runCPUProfile() 151 } 152 153 if veryVerbose { 154 verbose = true 155 raft.SetLogLevel(raft.Debug) 156 } 157 158 parseCorsFlag() 159 160 if machines != "" { 161 cluster = strings.Split(machines, ",") 162 } else if machinesFile != "" { 163 b, err := ioutil.ReadFile(machinesFile) 164 if err != nil { 165 fatalf("Unable to read the given machines file: %s", err) 166 } 167 cluster = strings.Split(string(b), ",") 168 } 169 170 // Check TLS arguments 171 raftTLSConfig, ok := tlsConfigFromInfo(argInfo.RaftTLS) 172 if !ok { 173 fatal("Please specify cert and key file or cert and key file and CAFile or none of the three") 174 } 175 176 etcdTLSConfig, ok := tlsConfigFromInfo(argInfo.EtcdTLS) 177 if !ok { 178 fatal("Please specify cert and key file or cert and key file and CAFile or none of the three") 179 } 180 181 argInfo.Name = strings.TrimSpace(argInfo.Name) 182 if argInfo.Name == "" { 183 fatal("ERROR: server name required. e.g. '-n=server_name'") 184 } 185 186 // Check host name arguments 187 argInfo.RaftURL = sanitizeURL(argInfo.RaftURL, raftTLSConfig.Scheme) 188 argInfo.EtcdURL = sanitizeURL(argInfo.EtcdURL, etcdTLSConfig.Scheme) 189 argInfo.WebURL = sanitizeURL(argInfo.WebURL, "http") 190 191 argInfo.RaftListenHost = sanitizeListenHost(argInfo.RaftListenHost, argInfo.RaftURL) 192 argInfo.EtcdListenHost = sanitizeListenHost(argInfo.EtcdListenHost, argInfo.EtcdURL) 193 194 // Read server info from file or grab it from user. 195 if err := os.MkdirAll(dirPath, 0744); err != nil { 196 fatalf("Unable to create path: %s", err) 197 } 198 199 info := getInfo(dirPath) 200 201 // Create etcd key-value store 202 etcdStore = store.CreateStore(maxSize) 203 snapConf = newSnapshotConf() 204 205 // Create etcd and raft server 206 e = newEtcdServer(info.Name, info.EtcdURL, info.EtcdListenHost, &etcdTLSConfig, &info.EtcdTLS) 207 r = newRaftServer(info.Name, info.RaftURL, info.RaftListenHost, &raftTLSConfig, &info.RaftTLS) 208 209 startWebInterface() 210 r.ListenAndServe() 211 e.ListenAndServe() 212 213 } 214 215 // parseCorsFlag gathers up the cors whitelist and puts it into the corsList. 216 func parseCorsFlag() { 217 if cors != "" { 218 corsList = make(map[string]bool) 219 list := strings.Split(cors, ",") 220 for _, v := range list { 221 fmt.Println(v) 222 if v != "*" { 223 _, err := url.Parse(v) 224 if err != nil { 225 panic(fmt.Sprintf("bad cors url: %s", err)) 226 } 227 } 228 corsList[v] = true 229 } 230 } 231 }