github.com/macb/etcd@v0.3.1-0.20140227003422-a60481c6b1a0/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  }