Browse Source

feat(etcd): add listen host parameter

this separates out the listening IP from the advertised IP. This is
necessary so that we can hit etcd on 127.0.0.1 but also advertise the
right IP to the rest of the cluster.
Brandon Philips 12 years ago
parent
commit
351e84aece
4 changed files with 35 additions and 17 deletions
  1. 12 4
      etcd.go
  2. 2 9
      etcd_server.go
  3. 5 4
      raft_server.go
  4. 16 0
      util.go

+ 12 - 4
etcd.go

@@ -50,8 +50,10 @@ func init() {
 	flag.StringVar(&machinesFile, "CF", "", "the file contains a list of existing machines in the cluster, seperate by comma")
 	flag.StringVar(&machinesFile, "CF", "", "the file contains a list of existing machines in the cluster, seperate by comma")
 
 
 	flag.StringVar(&argInfo.Name, "n", "default-name", "the node name (required)")
 	flag.StringVar(&argInfo.Name, "n", "default-name", "the node name (required)")
-	flag.StringVar(&argInfo.EtcdURL, "c", "127.0.0.1:4001", "the hostname:port for etcd client communication")
-	flag.StringVar(&argInfo.RaftURL, "s", "127.0.0.1:7001", "the hostname:port for raft server communication")
+	flag.StringVar(&argInfo.EtcdURL, "c", "127.0.0.1:4001", "the advertised public hostname:port for etcd client communication")
+	flag.StringVar(&argInfo.RaftURL, "s", "127.0.0.1:7001", "the advertised public hostname:port for raft server communication")
+	flag.StringVar(&argInfo.EtcdListenHost, "cl", "127.0.0.1", "the listening hostname for etcd client communication")
+	flag.StringVar(&argInfo.RaftListenHost, "sl", "127.0.0.1", "the listening hostname for raft server communication")
 	flag.StringVar(&argInfo.WebURL, "w", "", "the hostname:port of web interface")
 	flag.StringVar(&argInfo.WebURL, "w", "", "the hostname:port of web interface")
 
 
 	flag.StringVar(&argInfo.RaftTLS.CAFile, "serverCAFile", "", "the path of the CAFile")
 	flag.StringVar(&argInfo.RaftTLS.CAFile, "serverCAFile", "", "the path of the CAFile")
@@ -107,6 +109,9 @@ type Info struct {
 	EtcdURL string `json:"etcdURL"`
 	EtcdURL string `json:"etcdURL"`
 	WebURL  string `json:"webURL"`
 	WebURL  string `json:"webURL"`
 
 
+	RaftListenHost string `json:"raftListenHost"`
+	EtcdListenHost string `json:"etcdListenHost"`
+
 	RaftTLS TLSInfo `json:"raftTLS"`
 	RaftTLS TLSInfo `json:"raftTLS"`
 	EtcdTLS TLSInfo `json:"etcdTLS"`
 	EtcdTLS TLSInfo `json:"etcdTLS"`
 }
 }
@@ -178,6 +183,9 @@ func main() {
 	argInfo.EtcdURL = sanitizeURL(argInfo.EtcdURL, etcdTLSConfig.Scheme)
 	argInfo.EtcdURL = sanitizeURL(argInfo.EtcdURL, etcdTLSConfig.Scheme)
 	argInfo.WebURL = sanitizeURL(argInfo.WebURL, "http")
 	argInfo.WebURL = sanitizeURL(argInfo.WebURL, "http")
 
 
+	argInfo.RaftListenHost = sanitizeListenHost(argInfo.RaftListenHost, argInfo.RaftURL)
+	argInfo.EtcdListenHost = sanitizeListenHost(argInfo.EtcdListenHost, argInfo.EtcdURL)
+
 	// Read server info from file or grab it from user.
 	// Read server info from file or grab it from user.
 	if err := os.MkdirAll(dirPath, 0744); err != nil {
 	if err := os.MkdirAll(dirPath, 0744); err != nil {
 		fatalf("Unable to create path: %s", err)
 		fatalf("Unable to create path: %s", err)
@@ -190,8 +198,8 @@ func main() {
 	snapConf = newSnapshotConf()
 	snapConf = newSnapshotConf()
 
 
 	// Create etcd and raft server
 	// Create etcd and raft server
-	e = newEtcdServer(info.Name, info.EtcdURL, &etcdTLSConfig, &info.EtcdTLS)
-	r = newRaftServer(info.Name, info.RaftURL, &raftTLSConfig, &info.RaftTLS)
+	e = newEtcdServer(info.Name, info.EtcdURL, info.EtcdListenHost, &etcdTLSConfig, &info.EtcdTLS)
+	r = newRaftServer(info.Name, info.RaftURL, info.RaftListenHost, &raftTLSConfig, &info.RaftTLS)
 
 
 	startWebInterface()
 	startWebInterface()
 	r.ListenAndServe()
 	r.ListenAndServe()

+ 2 - 9
etcd_server.go

@@ -2,7 +2,6 @@ package main
 
 
 import (
 import (
 	"net/http"
 	"net/http"
-	"net/url"
 )
 )
 
 
 type etcdServer struct {
 type etcdServer struct {
@@ -15,18 +14,12 @@ type etcdServer struct {
 
 
 var e *etcdServer
 var e *etcdServer
 
 
-func newEtcdServer(name string, urlStr string, tlsConf *TLSConfig, tlsInfo *TLSInfo) *etcdServer {
-	u, err := url.Parse(urlStr)
-
-	if err != nil {
-		fatalf("invalid url '%s': %s", e.url, err)
-	}
-
+func newEtcdServer(name string, urlStr string, listenHost string, tlsConf *TLSConfig, tlsInfo *TLSInfo) *etcdServer {
 	return &etcdServer{
 	return &etcdServer{
 		Server: http.Server{
 		Server: http.Server{
 			Handler:   NewEtcdMuxer(),
 			Handler:   NewEtcdMuxer(),
 			TLSConfig: &tlsConf.Server,
 			TLSConfig: &tlsConf.Server,
-			Addr:      u.Host,
+			Addr:      listenHost,
 		},
 		},
 		name:    name,
 		name:    name,
 		url:     urlStr,
 		url:     urlStr,

+ 5 - 4
raft_server.go

@@ -20,13 +20,14 @@ type raftServer struct {
 	joinIndex uint64
 	joinIndex uint64
 	name      string
 	name      string
 	url       string
 	url       string
+	listenHost string
 	tlsConf   *TLSConfig
 	tlsConf   *TLSConfig
 	tlsInfo   *TLSInfo
 	tlsInfo   *TLSInfo
 }
 }
 
 
 var r *raftServer
 var r *raftServer
 
 
-func newRaftServer(name string, url string, tlsConf *TLSConfig, tlsInfo *TLSInfo) *raftServer {
+func newRaftServer(name string, url string, listenHost string, tlsConf *TLSConfig, tlsInfo *TLSInfo) *raftServer {
 
 
 	// Create transporter for raft
 	// Create transporter for raft
 	raftTransporter := newTransporter(tlsConf.Scheme, tlsConf.Client)
 	raftTransporter := newTransporter(tlsConf.Scheme, tlsConf.Client)
@@ -41,6 +42,7 @@ func newRaftServer(name string, url string, tlsConf *TLSConfig, tlsInfo *TLSInfo
 		version: raftVersion,
 		version: raftVersion,
 		name:    name,
 		name:    name,
 		url:     url,
 		url:     url,
+		listenHost: listenHost,
 		tlsConf: tlsConf,
 		tlsConf: tlsConf,
 		tlsInfo: tlsInfo,
 		tlsInfo: tlsInfo,
 	}
 	}
@@ -134,15 +136,14 @@ func startAsFollower() {
 
 
 // Start to listen and response raft command
 // Start to listen and response raft command
 func (r *raftServer) startTransport(scheme string, tlsConf tls.Config) {
 func (r *raftServer) startTransport(scheme string, tlsConf tls.Config) {
-	u, _ := url.Parse(r.url)
-	infof("raft server [%s:%s]", r.name, u)
+	infof("raft server [%s:%s]", r.name, r.listenHost)
 
 
 	raftMux := http.NewServeMux()
 	raftMux := http.NewServeMux()
 
 
 	server := &http.Server{
 	server := &http.Server{
 		Handler:   raftMux,
 		Handler:   raftMux,
 		TLSConfig: &tlsConf,
 		TLSConfig: &tlsConf,
-		Addr:      u.Host,
+		Addr:      r.listenHost,
 	}
 	}
 
 
 	// internal commands
 	// internal commands

+ 16 - 0
util.go

@@ -106,6 +106,22 @@ func sanitizeURL(host string, defaultScheme string) string {
 	return p.String()
 	return p.String()
 }
 }
 
 
+// sanitizeListenHost cleans up the ListenHost parameter and appends a port
+// if necessary based on the advertised port.
+func sanitizeListenHost(listen string, advertised string) string {
+	aurl, err := url.Parse(advertised)
+	if err != nil {
+		fatal(err)
+	}
+
+	_, aport, err := net.SplitHostPort(aurl.Host)
+	if err != nil {
+		fatal(err)
+	}
+
+	return net.JoinHostPort(listen, aport)
+}
+
 func check(err error) {
 func check(err error) {
 	if err != nil {
 	if err != nil {
 		fatal(err)
 		fatal(err)