diff --git a/command/agent/agent.go b/command/agent/agent.go index 6f0f1e8a3..80fe9b8e7 100644 --- a/command/agent/agent.go +++ b/command/agent/agent.go @@ -7,11 +7,11 @@ import ( "net" "os" "path/filepath" - "runtime" "sync" "time" "github.com/hashicorp/nomad/client" + clientconfig "github.com/hashicorp/nomad/client/config" "github.com/hashicorp/nomad/nomad" "github.com/hashicorp/nomad/nomad/structs" ) @@ -242,26 +242,8 @@ func (a *Agent) setupClient() error { conf.Node.HTTPAddr = httpAddr // Reserve some ports for the plugins - if runtime.GOOS == "windows" { - deviceName, err := a.findLoopbackDevice() - if err != nil { - return fmt.Errorf("error finding the device name for loopback: %v", err) - } - var nr *structs.NetworkResource - for _, n := range conf.Node.Reserved.Networks { - if n.Device == deviceName { - nr = n - } - } - if nr == nil { - nr = &structs.NetworkResource{ - Device: deviceName, - ReservedPorts: make([]structs.Port, 0), - } - } - for i := conf.ClientMinPort; i <= conf.ClientMaxPort; i++ { - nr.ReservedPorts = append(nr.ReservedPorts, structs.Port{Label: fmt.Sprintf("plugin-%d", i), Value: int(i)}) - } + if err := a.reservePortsForClient(conf); err != nil { + return err } // Create the client @@ -273,26 +255,75 @@ func (a *Agent) setupClient() error { return nil } -func (a *Agent) findLoopbackDevice() (string, error) { +// reservePortsForClient reservers a range of ports for the client to use when +// it creates various plugins for log collection, executors, drivers, etc +func (a *Agent) reservePortsForClient(conf *clientconfig.Config) error { + // finding the device name for loopback + deviceName, addr, mask, err := a.findLoopbackDevice() + if err != nil { + return fmt.Errorf("error finding the device name for loopback: %v", err) + } + + // seeing if the user has already reserved some resources on this device + var nr *structs.NetworkResource + if conf.Node.Reserved == nil { + conf.Node.Reserved = &structs.Resources{} + } + for _, n := range conf.Node.Reserved.Networks { + if n.Device == deviceName { + nr = n + } + } + // If the user hasn't already created the device, we create it + if nr == nil { + nr = &structs.NetworkResource{ + Device: deviceName, + IP: addr, + CIDR: mask, + ReservedPorts: make([]structs.Port, 0), + } + } + // appending the port ranges we want to use for the client to the list of + // reserved ports for this device + for i := conf.ClientMinPort; i <= conf.ClientMaxPort; i++ { + nr.ReservedPorts = append(nr.ReservedPorts, structs.Port{Label: fmt.Sprintf("plugin-%d", i), Value: int(i)}) + } + conf.Node.Reserved.Networks = append(conf.Node.Reserved.Networks, nr) + return nil +} + +// findLoopbackDevice iterates through all the interfaces on a machine and +// returns the ip addr, mask of the loopback device +func (a *Agent) findLoopbackDevice() (string, string, string, error) { var ifcs []net.Interface var err error - var deviceName string ifcs, err = net.Interfaces() if err != nil { - return "", err + return "", "", "", err } for _, ifc := range ifcs { addrs, err := ifc.Addrs() if err != nil { - return deviceName, err + return "", "", "", err } for _, addr := range addrs { - if net.ParseIP(addr.String()).IsLoopback() { - return ifc.Name, nil + var ip net.IP + switch v := addr.(type) { + case *net.IPNet: + ip = v.IP + case *net.IPAddr: + ip = v.IP + } + if ip.IsLoopback() { + if ip.To4() == nil { + continue + } + return ifc.Name, ip.String(), addr.String(), nil } } } - return deviceName, err + + return "", "", "", fmt.Errorf("no loopback devices with IPV4 addr found") } // Leave is used gracefully exit. Clients will inform servers