diff --git a/builder/xenserver/find_port.go b/builder/xenserver/find_port.go new file mode 100644 index 0000000..a6a8492 --- /dev/null +++ b/builder/xenserver/find_port.go @@ -0,0 +1,25 @@ +package xenserver + +import ( + "fmt" + "log" + "net" +) + +// FindPort finds and starts listening on a port in the range [portMin, portMax] +// returns the listener and the port number on success, or nil, 0 on failure +func FindPort(portMin uint, portMax uint) (net.Listener, uint) { + log.Printf("Looking for an available port between %d and %d", portMin, portMax) + + for port := portMin; port <= portMax; port++ { + log.Printf("Trying port: %d", port) + l, err := net.Listen("tcp", fmt.Sprintf(":%d", port)) + if err == nil { + return l, port + } else { + log.Printf("Port %d unavailable: %s", port, err.Error()) + } + } + + return nil, 0 +} diff --git a/builder/xenserver/step_forward_port_over_ssh.go b/builder/xenserver/step_forward_port_over_ssh.go index a41c670..4c407c8 100644 --- a/builder/xenserver/step_forward_port_over_ssh.go +++ b/builder/xenserver/step_forward_port_over_ssh.go @@ -4,8 +4,6 @@ import ( "fmt" "github.com/mitchellh/multistep" "github.com/mitchellh/packer/packer" - "log" - "net" ) type stepForwardPortOverSSH struct { @@ -25,32 +23,15 @@ func (self *stepForwardPortOverSSH) Run(state multistep.StateBag) multistep.Step // Find a free local port: - log.Printf("Looking for an available port between %d and %d", - self.HostPortMin, - self.HostPortMax) + l, sshHostPort := FindPort(self.HostPortMin, self.HostPortMax) - var sshHostPort uint - var foundPort bool - - foundPort = false - - for i := self.HostPortMin; i < self.HostPortMax; i++ { - sshHostPort = i - log.Printf("Trying port: %d", sshHostPort) - l, err := net.Listen("tcp", fmt.Sprintf("127.0.0.1:%d", sshHostPort)) - if err == nil { - l.Close() - foundPort = true - break - } - - } - - if !foundPort { - ui.Error("Error: unable to find free host port. Try providing a larger range") + if l == nil || sshHostPort == 0 { + ui.Error("Error: unable to find free host port. Try providing a larger range [host_port_min, host_port_max]") return multistep.ActionHalt } + l.Close() + ui.Say(fmt.Sprintf("Creating a local port forward over SSH on local port %d", sshHostPort)) remotePort, _ := self.RemotePort(state) diff --git a/builder/xenserver/step_http_server.go b/builder/xenserver/step_http_server.go index 538a729..f233f6e 100644 --- a/builder/xenserver/step_http_server.go +++ b/builder/xenserver/step_http_server.go @@ -6,8 +6,6 @@ import ( "fmt" "github.com/mitchellh/multistep" "github.com/mitchellh/packer/packer" - "log" - "math/rand" "net" "net/http" ) @@ -36,32 +34,18 @@ func (s *stepHTTPServer) Run(state multistep.StateBag) multistep.StepAction { return multistep.ActionContinue } - // Find an available TCP port for our HTTP server - var httpAddr string - portRange := int(config.HTTPPortMax - config.HTTPPortMin) - for { - var err error - var offset uint = 0 + s.l, httpPort = FindPort(config.HTTPPortMin, config.HTTPPortMax) - if portRange > 0 { - // Intn will panic if portRange == 0, so we do a check. - offset = uint(rand.Intn(portRange)) - } - - httpPort = offset + config.HTTPPortMin - httpAddr = fmt.Sprintf(":%d", httpPort) - log.Printf("Trying port: %d", httpPort) - s.l, err = net.Listen("tcp", httpAddr) - if err == nil { - break - } + if s.l == nil || httpPort == 0 { + ui.Error("Error: unable to find free HTTP server port. Try providing a larger range [http_port_min, http_port_max]") + return multistep.ActionHalt } ui.Say(fmt.Sprintf("Starting HTTP server on port %d", httpPort)) // Start the HTTP server and run it in the background fileServer := http.FileServer(http.Dir(config.HTTPDir)) - server := &http.Server{Addr: httpAddr, Handler: fileServer} + server := &http.Server{Addr: fmt.Sprintf(":%d", httpPort), Handler: fileServer} go server.Serve(s.l) // Save the address into the state so it can be accessed in the future