mirror of
https://github.com/etcd-io/etcd.git
synced 2024-09-27 06:25:44 +00:00
Merge pull request #6170 from heyitsanthony/default-advertise-ip
use default ip for advertise URL
This commit is contained in:
commit
16b2d9ca5e
@ -24,6 +24,7 @@ import (
|
||||
"github.com/coreos/etcd/discovery"
|
||||
"github.com/coreos/etcd/etcdserver"
|
||||
"github.com/coreos/etcd/pkg/cors"
|
||||
"github.com/coreos/etcd/pkg/netutil"
|
||||
"github.com/coreos/etcd/pkg/transport"
|
||||
"github.com/coreos/etcd/pkg/types"
|
||||
"github.com/ghodss/yaml"
|
||||
@ -33,13 +34,9 @@ const (
|
||||
ClusterStateFlagNew = "new"
|
||||
ClusterStateFlagExisting = "existing"
|
||||
|
||||
DefaultName = "default"
|
||||
DefaultInitialAdvertisePeerURLs = "http://localhost:2380"
|
||||
DefaultAdvertiseClientURLs = "http://localhost:2379"
|
||||
DefaultListenPeerURLs = "http://localhost:2380"
|
||||
DefaultListenClientURLs = "http://localhost:2379"
|
||||
DefaultMaxSnapshots = 5
|
||||
DefaultMaxWALs = 5
|
||||
DefaultName = "default"
|
||||
DefaultMaxSnapshots = 5
|
||||
DefaultMaxWALs = 5
|
||||
|
||||
// maxElectionMs specifies the maximum value of election timeout.
|
||||
// More details are listed in ../Documentation/tuning.md#time-parameters.
|
||||
@ -50,8 +47,28 @@ var (
|
||||
ErrConflictBootstrapFlags = fmt.Errorf("multiple discovery or bootstrap flags are set. " +
|
||||
"Choose one of \"initial-cluster\", \"discovery\" or \"discovery-srv\"")
|
||||
ErrUnsetAdvertiseClientURLsFlag = fmt.Errorf("--advertise-client-urls is required when --listen-client-urls is set explicitly")
|
||||
|
||||
DefaultListenPeerURLs = "http://localhost:2380"
|
||||
DefaultListenClientURLs = "http://localhost:2379"
|
||||
DefaultInitialAdvertisePeerURLs = "http://localhost:2380"
|
||||
DefaultAdvertiseClientURLs = "http://localhost:2379"
|
||||
|
||||
defaultHostname string = "localhost"
|
||||
defaultHostStatus error
|
||||
)
|
||||
|
||||
func init() {
|
||||
ip, err := netutil.GetDefaultHost()
|
||||
if err != nil {
|
||||
defaultHostStatus = err
|
||||
return
|
||||
}
|
||||
// found default host, advertise on it
|
||||
DefaultInitialAdvertisePeerURLs = "http://" + ip + ":2380"
|
||||
DefaultAdvertiseClientURLs = "http://" + ip + ":2379"
|
||||
defaultHostname = ip
|
||||
}
|
||||
|
||||
// Config holds the arguments for configuring an etcd server.
|
||||
type Config struct {
|
||||
// member
|
||||
@ -317,3 +334,15 @@ func (cfg Config) InitialClusterFromName(name string) (ret string) {
|
||||
|
||||
func (cfg Config) IsNewCluster() bool { return cfg.ClusterState == ClusterStateFlagNew }
|
||||
func (cfg Config) ElectionTicks() int { return int(cfg.ElectionMs / cfg.TickMs) }
|
||||
|
||||
// IsDefaultHost returns the default hostname, if used, and the error, if any,
|
||||
// from getting the machine's default host.
|
||||
func (cfg Config) IsDefaultHost() (string, error) {
|
||||
if len(cfg.APUrls) == 1 && cfg.APUrls[0].String() == DefaultInitialAdvertisePeerURLs {
|
||||
return defaultHostname, defaultHostStatus
|
||||
}
|
||||
if len(cfg.ACUrls) == 1 && cfg.ACUrls[0].String() == DefaultAdvertiseClientURLs {
|
||||
return defaultHostname, defaultHostStatus
|
||||
}
|
||||
return "", defaultHostStatus
|
||||
}
|
||||
|
@ -60,6 +60,8 @@ func startEtcdOrProxyV2() {
|
||||
grpc.EnableTracing = false
|
||||
|
||||
cfg := newConfig()
|
||||
defaultInitialCluster := cfg.InitialCluster
|
||||
|
||||
err := cfg.parse(os.Args[1:])
|
||||
if err != nil {
|
||||
plog.Errorf("error verifying flags, %v. See 'etcd --help'.", err)
|
||||
@ -83,7 +85,9 @@ func startEtcdOrProxyV2() {
|
||||
plog.Infof("setting maximum number of CPUs to %d, total number of available CPUs is %d", GoMaxProcs, runtime.NumCPU())
|
||||
|
||||
// TODO: check whether fields are set instead of whether fields have default value
|
||||
if cfg.Name != embed.DefaultName && cfg.InitialCluster == cfg.InitialClusterFromName(embed.DefaultName) {
|
||||
defaultHost, defaultHostErr := cfg.IsDefaultHost()
|
||||
defaultHostOverride := defaultHost == "" || defaultHostErr == nil
|
||||
if (defaultHostOverride || cfg.Name != embed.DefaultName) && cfg.InitialCluster == defaultInitialCluster {
|
||||
cfg.InitialCluster = cfg.InitialClusterFromName(cfg.Name)
|
||||
}
|
||||
|
||||
@ -184,6 +188,15 @@ func startEtcdOrProxyV2() {
|
||||
|
||||
// startEtcd runs StartEtcd in addition to hooks needed for standalone etcd.
|
||||
func startEtcd(cfg *embed.Config) (<-chan struct{}, <-chan error, error) {
|
||||
defaultHost, dhErr := cfg.IsDefaultHost()
|
||||
if defaultHost != "" {
|
||||
if dhErr == nil {
|
||||
plog.Infof("advertising using detected default host %q", defaultHost)
|
||||
} else {
|
||||
plog.Noticef("failed to detect default host, advertise falling back to %q (%v)", defaultHost, dhErr)
|
||||
}
|
||||
}
|
||||
|
||||
e, err := embed.StartEtcd(cfg)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
|
28
pkg/netutil/routes.go
Normal file
28
pkg/netutil/routes.go
Normal file
@ -0,0 +1,28 @@
|
||||
// Copyright 2016 The etcd Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// +build !linux !386,!amd64
|
||||
|
||||
package netutil
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"runtime"
|
||||
)
|
||||
|
||||
// GetDefaultHost fetches the a resolvable name that corresponds
|
||||
// to the machine's default routable interface
|
||||
func GetDefaultHost() (string, error) {
|
||||
return "", fmt.Errorf("default host not supported on %s_%s", runtime.GOOS, runtime.GOARCH)
|
||||
}
|
133
pkg/netutil/routes_linux.go
Normal file
133
pkg/netutil/routes_linux.go
Normal file
@ -0,0 +1,133 @@
|
||||
// Copyright 2016 The etcd Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// +build linux
|
||||
// +build 386 amd64
|
||||
|
||||
// TODO support native endian but without using "unsafe"
|
||||
|
||||
package netutil
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"net"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
var errNoDefaultRoute = fmt.Errorf("could not find default route")
|
||||
|
||||
func GetDefaultHost() (string, error) {
|
||||
rmsg, rerr := getDefaultRoute()
|
||||
if rerr != nil {
|
||||
return "", rerr
|
||||
}
|
||||
|
||||
attrs, aerr := syscall.ParseNetlinkRouteAttr(rmsg)
|
||||
if aerr != nil {
|
||||
return "", aerr
|
||||
}
|
||||
|
||||
oif := uint32(0)
|
||||
for _, attr := range attrs {
|
||||
if attr.Attr.Type == syscall.RTA_PREFSRC {
|
||||
return net.IP(attr.Value).String(), nil
|
||||
}
|
||||
if attr.Attr.Type == syscall.RTA_OIF {
|
||||
oif = binary.LittleEndian.Uint32(attr.Value)
|
||||
}
|
||||
}
|
||||
|
||||
if oif == 0 {
|
||||
return "", errNoDefaultRoute
|
||||
}
|
||||
|
||||
// prefsrc not detected, fall back to getting address from iface
|
||||
|
||||
ifmsg, ierr := getIface(oif)
|
||||
if ierr != nil {
|
||||
return "", ierr
|
||||
}
|
||||
|
||||
attrs, aerr = syscall.ParseNetlinkRouteAttr(ifmsg)
|
||||
if aerr != nil {
|
||||
return "", aerr
|
||||
}
|
||||
|
||||
for _, attr := range attrs {
|
||||
if attr.Attr.Type == syscall.RTA_SRC {
|
||||
return net.IP(attr.Value).String(), nil
|
||||
}
|
||||
}
|
||||
|
||||
return "", errNoDefaultRoute
|
||||
}
|
||||
|
||||
func getDefaultRoute() (*syscall.NetlinkMessage, error) {
|
||||
dat, err := syscall.NetlinkRIB(syscall.RTM_GETROUTE, syscall.AF_UNSPEC)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
msgs, msgErr := syscall.ParseNetlinkMessage(dat)
|
||||
if msgErr != nil {
|
||||
return nil, msgErr
|
||||
}
|
||||
|
||||
rtmsg := syscall.RtMsg{}
|
||||
for _, m := range msgs {
|
||||
if m.Header.Type != syscall.RTM_NEWROUTE {
|
||||
continue
|
||||
}
|
||||
buf := bytes.NewBuffer(m.Data[:syscall.SizeofRtMsg])
|
||||
if rerr := binary.Read(buf, binary.LittleEndian, &rtmsg); rerr != nil {
|
||||
continue
|
||||
}
|
||||
if rtmsg.Dst_len == 0 {
|
||||
// zero-length Dst_len implies default route
|
||||
return &m, nil
|
||||
}
|
||||
}
|
||||
|
||||
return nil, errNoDefaultRoute
|
||||
}
|
||||
|
||||
func getIface(idx uint32) (*syscall.NetlinkMessage, error) {
|
||||
dat, err := syscall.NetlinkRIB(syscall.RTM_GETADDR, syscall.AF_UNSPEC)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
msgs, msgErr := syscall.ParseNetlinkMessage(dat)
|
||||
if msgErr != nil {
|
||||
return nil, msgErr
|
||||
}
|
||||
|
||||
ifaddrmsg := syscall.IfAddrmsg{}
|
||||
for _, m := range msgs {
|
||||
if m.Header.Type != syscall.RTM_NEWADDR {
|
||||
continue
|
||||
}
|
||||
buf := bytes.NewBuffer(m.Data[:syscall.SizeofIfAddrmsg])
|
||||
if rerr := binary.Read(buf, binary.LittleEndian, &ifaddrmsg); rerr != nil {
|
||||
continue
|
||||
}
|
||||
if ifaddrmsg.Index == idx {
|
||||
return &m, nil
|
||||
}
|
||||
}
|
||||
|
||||
return nil, errNoDefaultRoute
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user