github.com/sneal/packer@v0.5.2/builder/virtualbox/common/step_forward_ssh.go (about)

     1  package common
     2  
     3  import (
     4  	"fmt"
     5  	"github.com/mitchellh/multistep"
     6  	"github.com/mitchellh/packer/packer"
     7  	"log"
     8  	"math/rand"
     9  	"net"
    10  )
    11  
    12  // This step adds a NAT port forwarding definition so that SSH is available
    13  // on the guest machine.
    14  //
    15  // Uses:
    16  //   driver Driver
    17  //   ui packer.Ui
    18  //   vmName string
    19  //
    20  // Produces:
    21  type StepForwardSSH struct {
    22  	GuestPort   uint
    23  	HostPortMin uint
    24  	HostPortMax uint
    25  }
    26  
    27  func (s *StepForwardSSH) Run(state multistep.StateBag) multistep.StepAction {
    28  	driver := state.Get("driver").(Driver)
    29  	ui := state.Get("ui").(packer.Ui)
    30  	vmName := state.Get("vmName").(string)
    31  
    32  	log.Printf("Looking for available SSH port between %d and %d",
    33  		s.HostPortMin, s.HostPortMax)
    34  	var sshHostPort uint
    35  	var offset uint = 0
    36  
    37  	portRange := int(s.HostPortMax - s.HostPortMin)
    38  	if portRange > 0 {
    39  		// Have to check if > 0 to avoid a panic
    40  		offset = uint(rand.Intn(portRange))
    41  	}
    42  
    43  	for {
    44  		sshHostPort = offset + s.HostPortMin
    45  		log.Printf("Trying port: %d", sshHostPort)
    46  		l, err := net.Listen("tcp", fmt.Sprintf("127.0.0.1:%d", sshHostPort))
    47  		if err == nil {
    48  			defer l.Close()
    49  			break
    50  		}
    51  	}
    52  
    53  	// Create a forwarded port mapping to the VM
    54  	ui.Say(fmt.Sprintf("Creating forwarded port mapping for SSH (host port %d)", sshHostPort))
    55  	command := []string{
    56  		"modifyvm", vmName,
    57  		"--natpf1",
    58  		fmt.Sprintf("packerssh,tcp,127.0.0.1,%d,,%d", sshHostPort, s.GuestPort),
    59  	}
    60  	if err := driver.VBoxManage(command...); err != nil {
    61  		err := fmt.Errorf("Error creating port forwarding rule: %s", err)
    62  		state.Put("error", err)
    63  		ui.Error(err.Error())
    64  		return multistep.ActionHalt
    65  	}
    66  
    67  	// Save the port we're using so that future steps can use it
    68  	state.Put("sshHostPort", sshHostPort)
    69  
    70  	return multistep.ActionContinue
    71  }
    72  
    73  func (s *StepForwardSSH) Cleanup(state multistep.StateBag) {}