From fdaa783597d52a5a81437b459092b86a7bc07ac5 Mon Sep 17 00:00:00 2001 From: John Fieber Date: Fri, 17 Apr 2015 10:51:28 -0700 Subject: [PATCH 1/3] Virtualbox: move NAT port allocation to machine boot The host side ssh NAT port was being chosen by the OS when the VM was crafted in the `Create` method. There was no accounting for some other process taking over the port while the VM is shutoff. This moves the port provisioning to VM start. On first start, the OS will supply the port. Subsequent starts, we see if we can re-use the port, falling back to delegating the selection to the OS. Signed-off-by: John Fieber --- drivers/virtualbox/virtualbox.go | 43 ++++++++++++++++++++++---------- 1 file changed, 30 insertions(+), 13 deletions(-) diff --git a/drivers/virtualbox/virtualbox.go b/drivers/virtualbox/virtualbox.go index f3e6e60b2a..270584296d 100644 --- a/drivers/virtualbox/virtualbox.go +++ b/drivers/virtualbox/virtualbox.go @@ -165,11 +165,6 @@ func (d *Driver) Create() error { return err } - d.SSHPort, err = getAvailableTCPPort() - if err != nil { - return err - } - log.Infof("Creating SSH key...") b2dutils := utils.NewB2dUtils("", "") @@ -237,11 +232,6 @@ func (d *Driver) Create() error { return err } - if err := vbm("modifyvm", d.MachineName, - "--natpf1", fmt.Sprintf("ssh,tcp,127.0.0.1,%d,,22", d.SSHPort)); err != nil { - return err - } - hostOnlyNetwork, err := getOrCreateHostOnlyNetwork( net.ParseIP("192.168.99.1"), net.IPv4Mask(255, 255, 255, 0), @@ -340,6 +330,10 @@ func (d *Driver) Start() error { switch s { case state.Stopped, state.Saved: + d.SSHPort, err = setPortForwarding(d.MachineName, 1, "ssh", "tcp", 22, d.SSHPort) + if err != nil { + return err + } if err := vbm("startvm", d.MachineName, "--type", "headless"); err != nil { return err } @@ -596,10 +590,12 @@ func zeroFill(w io.Writer, n int64) error { return nil } -func getAvailableTCPPort() (int, error) { - port := 0 +// Select an available port, trying the specified +// port first, falling back on an OS selected port. +func getAvailableTCPPort(port int) (int, error) { + return 56883, nil for i := 0; i <= 10; i++ { - ln, err := net.Listen("tcp4", "127.0.0.1:0") + ln, err := net.Listen("tcp4", fmt.Sprintf("127.0.0.1:%d", port)) if err != nil { return 0, err } @@ -614,8 +610,29 @@ func getAvailableTCPPort() (int, error) { port = p return port, nil } + port = 0 // Throw away the port hint before trying again time.Sleep(1) } + time.Sleep(1) return 0, fmt.Errorf("unable to allocate tcp port") } + +// Setup a NAT port forwarding entry. +func setPortForwarding(machine string, interfaceNum int, mapName, protocol string, guestPort, desiredHostPort int) (int, error) { + actualHostPort, err := getAvailableTCPPort(desiredHostPort) + if err != nil { + return -1, err + } + if desiredHostPort != actualHostPort && desiredHostPort != 0 { + log.Debugf("NAT forwarding host port for guest port %d (%s) changed from %d to %d", + guestPort, mapName, desiredHostPort, actualHostPort) + } + cmd := fmt.Sprintf("--natpf%d", interfaceNum) + vbm("modifyvm", machine, cmd, "delete", mapName) + if err := vbm("modifyvm", machine, + cmd, fmt.Sprintf("%s,%s,127.0.0.1,%d,,%d", mapName, protocol, actualHostPort, guestPort)); err != nil { + return -1, err + } + return actualHostPort, nil +} From 6ab04a0b512b29facf0b669651648299d8cf153f Mon Sep 17 00:00:00 2001 From: John Fieber Date: Fri, 17 Apr 2015 12:24:58 -0700 Subject: [PATCH 2/3] Extract a wrench accidentally left inside the engine Signed-off-by: John Fieber --- drivers/virtualbox/virtualbox.go | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/virtualbox/virtualbox.go b/drivers/virtualbox/virtualbox.go index 270584296d..a44935c0be 100644 --- a/drivers/virtualbox/virtualbox.go +++ b/drivers/virtualbox/virtualbox.go @@ -593,7 +593,6 @@ func zeroFill(w io.Writer, n int64) error { // Select an available port, trying the specified // port first, falling back on an OS selected port. func getAvailableTCPPort(port int) (int, error) { - return 56883, nil for i := 0; i <= 10; i++ { ln, err := net.Listen("tcp4", fmt.Sprintf("127.0.0.1:%d", port)) if err != nil { From f42177983fb2c9896748402fd482a3eb572914a6 Mon Sep 17 00:00:00 2001 From: John Fieber Date: Mon, 27 Apr 2015 16:50:36 -0700 Subject: [PATCH 3/3] Remove stray sleep() This is just a bit of development debris. Signed-off-by: John Fieber --- drivers/virtualbox/virtualbox.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/virtualbox/virtualbox.go b/drivers/virtualbox/virtualbox.go index ac7bc3f232..30eb546ce1 100644 --- a/drivers/virtualbox/virtualbox.go +++ b/drivers/virtualbox/virtualbox.go @@ -656,9 +656,7 @@ func getAvailableTCPPort(port int) (int, error) { port = 0 // Throw away the port hint before trying again time.Sleep(1) } - time.Sleep(1) return 0, fmt.Errorf("unable to allocate tcp port") - } // Setup a NAT port forwarding entry.