etcd.go 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. package main
  2. import (
  3. "crypto/tls"
  4. "flag"
  5. "github.com/coreos/etcd/store"
  6. "github.com/coreos/go-raft"
  7. "io/ioutil"
  8. "os"
  9. "strings"
  10. "time"
  11. )
  12. //------------------------------------------------------------------------------
  13. //
  14. // Initialization
  15. //
  16. //------------------------------------------------------------------------------
  17. var (
  18. verbose bool
  19. veryVerbose bool
  20. machines string
  21. machinesFile string
  22. cluster []string
  23. argInfo Info
  24. dirPath string
  25. force bool
  26. maxSize int
  27. snapshot bool
  28. retryTimes int
  29. maxClusterSize int
  30. cpuprofile string
  31. )
  32. func init() {
  33. flag.BoolVar(&verbose, "v", false, "verbose logging")
  34. flag.BoolVar(&veryVerbose, "vv", false, "very verbose logging")
  35. flag.StringVar(&machines, "C", "", "the ip address and port of a existing machines in the cluster, sepearate by comma")
  36. flag.StringVar(&machinesFile, "CF", "", "the file contains a list of existing machines in the cluster, seperate by comma")
  37. flag.StringVar(&argInfo.Name, "n", "default-name", "the node name (required)")
  38. flag.StringVar(&argInfo.EtcdURL, "c", "127.0.0.1:4001", "the advertised public hostname:port for etcd client communication")
  39. flag.StringVar(&argInfo.RaftURL, "s", "127.0.0.1:7001", "the advertised public hostname:port for raft server communication")
  40. flag.StringVar(&argInfo.EtcdListenHost, "cl", "", "the listening hostname for etcd client communication (defaults to advertised ip)")
  41. flag.StringVar(&argInfo.RaftListenHost, "sl", "", "the listening hostname for raft server communication (defaults to advertised ip)")
  42. flag.StringVar(&argInfo.WebURL, "w", "", "the hostname:port of web interface")
  43. flag.StringVar(&argInfo.RaftTLS.CAFile, "serverCAFile", "", "the path of the CAFile")
  44. flag.StringVar(&argInfo.RaftTLS.CertFile, "serverCert", "", "the cert file of the server")
  45. flag.StringVar(&argInfo.RaftTLS.KeyFile, "serverKey", "", "the key file of the server")
  46. flag.StringVar(&argInfo.EtcdTLS.CAFile, "clientCAFile", "", "the path of the client CAFile")
  47. flag.StringVar(&argInfo.EtcdTLS.CertFile, "clientCert", "", "the cert file of the client")
  48. flag.StringVar(&argInfo.EtcdTLS.KeyFile, "clientKey", "", "the key file of the client")
  49. flag.StringVar(&dirPath, "d", ".", "the directory to store log and snapshot")
  50. flag.BoolVar(&force, "f", false, "force new node configuration if existing is found (WARNING: data loss!)")
  51. flag.BoolVar(&snapshot, "snapshot", false, "open or close snapshot")
  52. flag.IntVar(&maxSize, "m", 1024, "the max size of result buffer")
  53. flag.IntVar(&retryTimes, "r", 3, "the max retry attempts when trying to join a cluster")
  54. flag.IntVar(&maxClusterSize, "maxsize", 9, "the max size of the cluster")
  55. flag.StringVar(&cpuprofile, "cpuprofile", "", "write cpu profile to file")
  56. }
  57. const (
  58. ElectionTimeout = 200 * time.Millisecond
  59. HeartbeatTimeout = 50 * time.Millisecond
  60. // Timeout for internal raft http connection
  61. // The original timeout for http is 45 seconds
  62. // which is too long for our usage.
  63. HTTPTimeout = 10 * time.Second
  64. RetryInterval = 10
  65. )
  66. //------------------------------------------------------------------------------
  67. //
  68. // Typedefs
  69. //
  70. //------------------------------------------------------------------------------
  71. type TLSInfo struct {
  72. CertFile string `json:"CertFile"`
  73. KeyFile string `json:"KeyFile"`
  74. CAFile string `json:"CAFile"`
  75. }
  76. type Info struct {
  77. Name string `json:"name"`
  78. RaftURL string `json:"raftURL"`
  79. EtcdURL string `json:"etcdURL"`
  80. WebURL string `json:"webURL"`
  81. RaftListenHost string `json:"raftListenHost"`
  82. EtcdListenHost string `json:"etcdListenHost"`
  83. RaftTLS TLSInfo `json:"raftTLS"`
  84. EtcdTLS TLSInfo `json:"etcdTLS"`
  85. }
  86. type TLSConfig struct {
  87. Scheme string
  88. Server tls.Config
  89. Client tls.Config
  90. }
  91. //------------------------------------------------------------------------------
  92. //
  93. // Variables
  94. //
  95. //------------------------------------------------------------------------------
  96. var etcdStore *store.Store
  97. //------------------------------------------------------------------------------
  98. //
  99. // Functions
  100. //
  101. //------------------------------------------------------------------------------
  102. //--------------------------------------
  103. // Main
  104. //--------------------------------------
  105. func main() {
  106. flag.Parse()
  107. if cpuprofile != "" {
  108. runCPUProfile()
  109. }
  110. if veryVerbose {
  111. verbose = true
  112. raft.SetLogLevel(raft.Debug)
  113. }
  114. if machines != "" {
  115. cluster = strings.Split(machines, ",")
  116. } else if machinesFile != "" {
  117. b, err := ioutil.ReadFile(machinesFile)
  118. if err != nil {
  119. fatalf("Unable to read the given machines file: %s", err)
  120. }
  121. cluster = strings.Split(string(b), ",")
  122. }
  123. // Check TLS arguments
  124. raftTLSConfig, ok := tlsConfigFromInfo(argInfo.RaftTLS)
  125. if !ok {
  126. fatal("Please specify cert and key file or cert and key file and CAFile or none of the three")
  127. }
  128. etcdTLSConfig, ok := tlsConfigFromInfo(argInfo.EtcdTLS)
  129. if !ok {
  130. fatal("Please specify cert and key file or cert and key file and CAFile or none of the three")
  131. }
  132. argInfo.Name = strings.TrimSpace(argInfo.Name)
  133. if argInfo.Name == "" {
  134. fatal("ERROR: server name required. e.g. '-n=server_name'")
  135. }
  136. // Check host name arguments
  137. argInfo.RaftURL = sanitizeURL(argInfo.RaftURL, raftTLSConfig.Scheme)
  138. argInfo.EtcdURL = sanitizeURL(argInfo.EtcdURL, etcdTLSConfig.Scheme)
  139. argInfo.WebURL = sanitizeURL(argInfo.WebURL, "http")
  140. argInfo.RaftListenHost = sanitizeListenHost(argInfo.RaftListenHost, argInfo.RaftURL)
  141. argInfo.EtcdListenHost = sanitizeListenHost(argInfo.EtcdListenHost, argInfo.EtcdURL)
  142. // Read server info from file or grab it from user.
  143. if err := os.MkdirAll(dirPath, 0744); err != nil {
  144. fatalf("Unable to create path: %s", err)
  145. }
  146. info := getInfo(dirPath)
  147. // Create etcd key-value store
  148. etcdStore = store.CreateStore(maxSize)
  149. snapConf = newSnapshotConf()
  150. // Create etcd and raft server
  151. e = newEtcdServer(info.Name, info.EtcdURL, info.EtcdListenHost, &etcdTLSConfig, &info.EtcdTLS)
  152. r = newRaftServer(info.Name, info.RaftURL, info.RaftListenHost, &raftTLSConfig, &info.RaftTLS)
  153. startWebInterface()
  154. r.ListenAndServe()
  155. e.ListenAndServe()
  156. }