builder/vmware: Randomize HTTP port to avoid collisions
This commit is contained in:
parent
56108f2b16
commit
85ab8621d4
|
@ -26,6 +26,8 @@ type config struct {
|
|||
VMName string `mapstructure:"vm_name"`
|
||||
OutputDir string `mapstructure:"output_directory"`
|
||||
HTTPDir string `mapstructure:"http_directory"`
|
||||
HTTPPortMin uint `mapstructure:"http_port_min"`
|
||||
HTTPPortMax uint `mapstructure:"http_port_max"`
|
||||
BootCommand []string `mapstructure:"boot_command"`
|
||||
BootWait time.Duration
|
||||
ShutdownCommand string `mapstructure:"shutdown_command"`
|
||||
|
@ -55,6 +57,14 @@ func (b *Builder) Prepare(raw interface{}) (err error) {
|
|||
b.config.VMName = "packer"
|
||||
}
|
||||
|
||||
if b.config.HTTPPortMin == 0 {
|
||||
b.config.HTTPPortMin = 8000
|
||||
}
|
||||
|
||||
if b.config.HTTPPortMax == 0 {
|
||||
b.config.HTTPPortMax = 9000
|
||||
}
|
||||
|
||||
if b.config.VNCPortMin == 0 {
|
||||
b.config.VNCPortMin = 5900
|
||||
}
|
||||
|
@ -70,6 +80,10 @@ func (b *Builder) Prepare(raw interface{}) (err error) {
|
|||
// Accumulate any errors
|
||||
errs := make([]error, 0)
|
||||
|
||||
if b.config.HTTPPortMin > b.config.HTTPPortMax {
|
||||
errs = append(errs, errors.New("http_port_min must be less than http_port_max"))
|
||||
}
|
||||
|
||||
if b.config.ISOUrl == "" {
|
||||
errs = append(errs, errors.New("An iso_url must be specified."))
|
||||
}
|
||||
|
|
|
@ -65,6 +65,34 @@ func TestBuilderPrepare_Defaults(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestBuilderPrepare_HTTPPort(t *testing.T) {
|
||||
var b Builder
|
||||
config := testConfig()
|
||||
|
||||
// Bad
|
||||
config["http_port_min"] = 1000
|
||||
config["http_port_max"] = 500
|
||||
err := b.Prepare(config)
|
||||
if err == nil {
|
||||
t.Fatal("should have error")
|
||||
}
|
||||
|
||||
// Bad
|
||||
config["http_port_min"] = -500
|
||||
err = b.Prepare(config)
|
||||
if err == nil {
|
||||
t.Fatal("should have error")
|
||||
}
|
||||
|
||||
// Good
|
||||
config["http_port_min"] = 500
|
||||
config["http_port_max"] = 1000
|
||||
err = b.Prepare(config)
|
||||
if err != nil {
|
||||
t.Fatalf("should not have error: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuilderPrepare_ISOUrl(t *testing.T) {
|
||||
var b Builder
|
||||
config := testConfig()
|
||||
|
|
|
@ -4,6 +4,8 @@ import (
|
|||
"fmt"
|
||||
"github.com/mitchellh/multistep"
|
||||
"github.com/mitchellh/packer/packer"
|
||||
"log"
|
||||
"math/rand"
|
||||
"net"
|
||||
"net/http"
|
||||
)
|
||||
|
@ -25,27 +27,32 @@ func (s *stepHTTPServer) Run(state map[string]interface{}) multistep.StepAction
|
|||
config := state["config"].(*config)
|
||||
ui := state["ui"].(packer.Ui)
|
||||
|
||||
httpPort := 0
|
||||
if config.HTTPDir != "" {
|
||||
httpPort = 8080
|
||||
httpAddr := fmt.Sprintf(":%d", httpPort)
|
||||
|
||||
ui.Say(fmt.Sprintf("Starting HTTP server on port %d", httpPort))
|
||||
|
||||
// Start the TCP listener
|
||||
var err error
|
||||
s.l, err = net.Listen("tcp", httpAddr)
|
||||
if err != nil {
|
||||
ui.Error(fmt.Sprintf("Error starting HTTP server: %s", err))
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
|
||||
// Start the HTTP server and run it in the background
|
||||
fileServer := http.FileServer(http.Dir(config.HTTPDir))
|
||||
server := &http.Server{Addr: httpAddr, Handler: fileServer}
|
||||
go server.Serve(s.l)
|
||||
var httpPort uint = 0
|
||||
if config.HTTPDir == "" {
|
||||
state["http_port"] = httpPort
|
||||
}
|
||||
|
||||
// Find an available TCP port for our HTTP server
|
||||
var httpAddr string
|
||||
portRange := int(config.HTTPPortMax - config.HTTPPortMin)
|
||||
for {
|
||||
var err error
|
||||
httpPort = uint(rand.Intn(portRange)) + config.HTTPPortMin
|
||||
httpAddr = fmt.Sprintf(":%d", httpPort)
|
||||
log.Printf("Trying port: %d", httpPort)
|
||||
s.l, err = net.Listen("tcp", httpAddr)
|
||||
if err == nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
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}
|
||||
go server.Serve(s.l)
|
||||
|
||||
// Save the address into the state so it can be accessed in the future
|
||||
state["http_port"] = httpPort
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@ const KeyLeftShift uint32 = 0xFFE1
|
|||
|
||||
type bootCommandTemplateData struct {
|
||||
HTTPIP string
|
||||
HTTPPort int
|
||||
HTTPPort uint
|
||||
Name string
|
||||
}
|
||||
|
||||
|
@ -37,7 +37,7 @@ type stepTypeBootCommand struct{}
|
|||
|
||||
func (s *stepTypeBootCommand) Run(state map[string]interface{}) multistep.StepAction {
|
||||
config := state["config"].(*config)
|
||||
httpPort := state["http_port"].(int)
|
||||
httpPort := state["http_port"].(uint)
|
||||
ui := state["ui"].(packer.Ui)
|
||||
vncPort := state["vnc_port"].(uint)
|
||||
|
||||
|
|
Loading…
Reference in New Issue