From 7c4dbbf7da124754b4512b327aabce9cc8cc0e5d Mon Sep 17 00:00:00 2001 From: Diptanu Choudhury Date: Fri, 12 Feb 2016 13:21:56 -0800 Subject: [PATCH 1/2] Reserving ports for client in every platform --- command/agent/agent.go | 73 ++++++++++++++++++++++++++---------------- 1 file changed, 46 insertions(+), 27 deletions(-) diff --git a/command/agent/agent.go b/command/agent/agent.go index 6f0f1e8a3..a6c6b0516 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,63 @@ func (a *Agent) setupClient() error { return nil } -func (a *Agent) findLoopbackDevice() (string, error) { +func (a *Agent) reservePortsForClient(conf *clientconfig.Config) error { + deviceName, addr, mask, err := a.findLoopbackDevice() + if err != nil { + return fmt.Errorf("error finding the device name for loopback: %v", err) + } + 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 nr == nil { + nr = &structs.NetworkResource{ + Device: deviceName, + IP: addr, + CIDR: mask, + 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)}) + } + conf.Node.Reserved.Networks = append(conf.Node.Reserved.Networks, nr) + return nil +} + +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 deviceName, "", "", 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() { + return ifc.Name, ip.String(), addr.String(), nil } } } - return deviceName, err + + return deviceName, "", "", err } // Leave is used gracefully exit. Clients will inform servers From 9b31a6583c6591750a017b6b271c9c812a20ff2d Mon Sep 17 00:00:00 2001 From: Diptanu Choudhury Date: Fri, 12 Feb 2016 14:25:32 -0800 Subject: [PATCH 2/2] Adding comments --- command/agent/agent.go | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/command/agent/agent.go b/command/agent/agent.go index a6c6b0516..80fe9b8e7 100644 --- a/command/agent/agent.go +++ b/command/agent/agent.go @@ -255,11 +255,16 @@ func (a *Agent) setupClient() error { return nil } +// 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{} @@ -269,6 +274,7 @@ func (a *Agent) reservePortsForClient(conf *clientconfig.Config) error { nr = n } } + // If the user hasn't already created the device, we create it if nr == nil { nr = &structs.NetworkResource{ Device: deviceName, @@ -277,6 +283,8 @@ func (a *Agent) reservePortsForClient(conf *clientconfig.Config) error { 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)}) } @@ -284,10 +292,11 @@ func (a *Agent) reservePortsForClient(conf *clientconfig.Config) error { 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 @@ -295,7 +304,7 @@ func (a *Agent) findLoopbackDevice() (string, string, string, error) { for _, ifc := range ifcs { addrs, err := ifc.Addrs() if err != nil { - return deviceName, "", "", err + return "", "", "", err } for _, addr := range addrs { var ip net.IP @@ -306,12 +315,15 @@ func (a *Agent) findLoopbackDevice() (string, string, string, error) { 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