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  }