mirror of
https://github.com/kemko/nomad.git
synced 2026-01-08 19:35:41 +03:00
Merge pull request #189 from apognu/dev/net-fingerprint
Fingerprint: config parameter for interface and native method for IP address
This commit is contained in:
@@ -31,6 +31,9 @@ type Config struct {
|
||||
// Region is the clients region
|
||||
Region string
|
||||
|
||||
// Network interface to be used in network fingerprinting
|
||||
NetworkInterface string
|
||||
|
||||
// Servers is a list of known server addresses. These are as "host:port"
|
||||
Servers []string
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
package fingerprint
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
@@ -38,10 +39,14 @@ func (f *NetworkFingerprint) Fingerprint(cfg *config.Config, node *structs.Node)
|
||||
if "darwin" == runtime.GOOS {
|
||||
defaultDevice = "en0"
|
||||
}
|
||||
// User-defined override for the default interface
|
||||
if cfg.NetworkInterface != "" {
|
||||
defaultDevice = cfg.NetworkInterface
|
||||
}
|
||||
|
||||
newNetwork.Device = defaultDevice
|
||||
|
||||
if ip := f.ifConfig(defaultDevice); ip != "" {
|
||||
if ip := f.ipAddress(defaultDevice); ip != "" {
|
||||
node.Attributes["network.ip-address"] = ip
|
||||
newNetwork.IP = ip
|
||||
newNetwork.CIDR = newNetwork.IP + "/32"
|
||||
@@ -129,6 +134,56 @@ func (f *NetworkFingerprint) linkSpeedEthtool(path, device string) int {
|
||||
return mbs
|
||||
}
|
||||
|
||||
// ipAddress returns the first IPv4 address on the configured default interface
|
||||
// Tries Golang native functions and falls back onto ifconfig
|
||||
func (f *NetworkFingerprint) ipAddress(device string) string {
|
||||
if ip, err := f.nativeIpAddress(device); err == nil {
|
||||
return ip
|
||||
}
|
||||
|
||||
return f.ifConfig(device)
|
||||
}
|
||||
|
||||
func (f *NetworkFingerprint) nativeIpAddress(device string) (string, error) {
|
||||
// Find IP address on configured interface
|
||||
var ip string
|
||||
ifaces, err := net.Interfaces()
|
||||
if err != nil {
|
||||
return "", errors.New("could not retrieve interface list")
|
||||
}
|
||||
|
||||
// TODO: should we handle IPv6 here? How do we determine precedence?
|
||||
for _, i := range ifaces {
|
||||
if i.Name != device {
|
||||
continue
|
||||
}
|
||||
|
||||
addrs, err := i.Addrs()
|
||||
if err != nil {
|
||||
return "", errors.New("could not retrieve interface IP addresses")
|
||||
}
|
||||
|
||||
for _, a := range addrs {
|
||||
switch v := a.(type) {
|
||||
case *net.IPNet:
|
||||
if v.IP.To4() != nil {
|
||||
ip = v.IP.String()
|
||||
}
|
||||
case *net.IPAddr:
|
||||
if v.IP.To4() != nil {
|
||||
ip = v.IP.String()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if net.ParseIP(ip) == nil {
|
||||
return "", errors.New(fmt.Sprintf("could not parse IP address `%s`", ip))
|
||||
}
|
||||
|
||||
return ip, nil
|
||||
}
|
||||
|
||||
// ifConfig returns the IP Address for this node according to ifConfig, for the
|
||||
// specified device.
|
||||
func (f *NetworkFingerprint) ifConfig(device string) string {
|
||||
|
||||
@@ -192,6 +192,9 @@ func (a *Agent) setupClient() error {
|
||||
conf.AllocDir = a.config.Client.AllocDir
|
||||
}
|
||||
conf.Servers = a.config.Client.Servers
|
||||
if a.config.Client.NetworkInterface != "" {
|
||||
conf.NetworkInterface = a.config.Client.NetworkInterface
|
||||
}
|
||||
|
||||
// Setup the node
|
||||
conf.Node = new(structs.Node)
|
||||
|
||||
@@ -139,6 +139,9 @@ type ClientConfig struct {
|
||||
|
||||
// Metadata associated with the node
|
||||
Meta map[string]string `hcl:"meta"`
|
||||
|
||||
// Interface to use for network fingerprinting
|
||||
NetworkInterface string `hcl:"network_interface"`
|
||||
}
|
||||
|
||||
// ServerConfig is configuration specific to the server mode
|
||||
@@ -384,6 +387,9 @@ func (a *ClientConfig) Merge(b *ClientConfig) *ClientConfig {
|
||||
if b.NodeClass != "" {
|
||||
result.NodeClass = b.NodeClass
|
||||
}
|
||||
if b.NetworkInterface != "" {
|
||||
result.NetworkInterface = b.NetworkInterface
|
||||
}
|
||||
|
||||
// Add the servers
|
||||
result.Servers = append(result.Servers, b.Servers...)
|
||||
|
||||
@@ -84,7 +84,7 @@ nodes, unless otherwise specified:
|
||||
TCP and UDP should be routable between the server nodes on this port.
|
||||
Defaults to `4648`. Only used on server nodes.
|
||||
|
||||
* <a id="addresses">`addresses`</a>: Controls the bind address for individual
|
||||
* <a id="addresses">`addresses`</a>: Controls the bind address for individual
|
||||
network services. Any values configured in this block take precedence over the
|
||||
default [bind_addr](#bind_addr). The value is a map of IP addresses and
|
||||
supports the following keys:
|
||||
@@ -154,7 +154,7 @@ configured on client nodes.
|
||||
* `enabled`: A boolean indicating if server mode should be enabled for the
|
||||
local agent. All other server options depend on this value being set.
|
||||
Defaults to `false`.
|
||||
* <a id="bootstrap_expect">`bootstrap_expect`</a>: This is an integer
|
||||
* <a id="bootstrap_expect">`bootstrap_expect`</a>: This is an integer
|
||||
representing the number of server nodes to wait for before bootstrapping. It
|
||||
is most common to use the odd-numbered integers `3` or `5` for this value,
|
||||
depending on the cluster size. A value of `1` does not provide any fault
|
||||
@@ -205,8 +205,10 @@ configured on server nodes.
|
||||
* <a id="node_class">`node_class`</a>: A string used to logically group client
|
||||
nodes by class. This can be used during job placement as a filter. This
|
||||
option is not required and has no default.
|
||||
* <a id="meta">`meta`</a>: This is a key/value mapping of metadata pairs. This
|
||||
* <a id="meta">`meta`</a>: This is a key/value mapping of metadata pairs. This
|
||||
is a free-form map and can contain any string values.
|
||||
* `network_interface`: This is a string to force network fingerprinting to use
|
||||
a specific network interface
|
||||
|
||||
## Atlas Options
|
||||
|
||||
|
||||
Reference in New Issue
Block a user