github.phpd.cn/hashicorp/packer@v1.3.2/builder/virtualbox/common/step_forward_ssh.go (about) 1 package common 2 3 import ( 4 "context" 5 "fmt" 6 "log" 7 "math/rand" 8 "net" 9 10 "github.com/hashicorp/packer/helper/communicator" 11 "github.com/hashicorp/packer/helper/multistep" 12 "github.com/hashicorp/packer/packer" 13 ) 14 15 // This step adds a NAT port forwarding definition so that SSH is available 16 // on the guest machine. 17 // 18 // Uses: 19 // driver Driver 20 // ui packer.Ui 21 // vmName string 22 // 23 // Produces: 24 type StepForwardSSH struct { 25 CommConfig *communicator.Config 26 HostPortMin uint 27 HostPortMax uint 28 SkipNatMapping bool 29 } 30 31 func (s *StepForwardSSH) Run(_ context.Context, state multistep.StateBag) multistep.StepAction { 32 driver := state.Get("driver").(Driver) 33 ui := state.Get("ui").(packer.Ui) 34 vmName := state.Get("vmName").(string) 35 36 if s.CommConfig.Type == "none" { 37 log.Printf("Not using a communicator, skipping setting up port forwarding...") 38 state.Put("sshHostPort", 0) 39 return multistep.ActionContinue 40 } 41 42 guestPort := s.CommConfig.Port() 43 sshHostPort := guestPort 44 if !s.SkipNatMapping { 45 log.Printf("Looking for available communicator (SSH, WinRM, etc) port between %d and %d", 46 s.HostPortMin, s.HostPortMax) 47 48 portRange := int(s.HostPortMax - s.HostPortMin + 1) 49 offset := rand.Intn(portRange) 50 51 for { 52 sshHostPort = offset + int(s.HostPortMin) 53 log.Printf("Trying port: %d", sshHostPort) 54 l, err := net.Listen("tcp", fmt.Sprintf("127.0.0.1:%d", sshHostPort)) 55 if err == nil { 56 defer l.Close() 57 break 58 } 59 offset++ 60 if offset == portRange { 61 offset = 0 62 } 63 } 64 65 // Create a forwarded port mapping to the VM 66 ui.Say(fmt.Sprintf("Creating forwarded port mapping for communicator (SSH, WinRM, etc) (host port %d)", sshHostPort)) 67 command := []string{ 68 "modifyvm", vmName, 69 "--natpf1", 70 fmt.Sprintf("packercomm,tcp,127.0.0.1,%d,,%d", sshHostPort, guestPort), 71 } 72 if err := driver.VBoxManage(command...); err != nil { 73 err := fmt.Errorf("Error creating port forwarding rule: %s", err) 74 state.Put("error", err) 75 ui.Error(err.Error()) 76 return multistep.ActionHalt 77 } 78 } 79 80 // Save the port we're using so that future steps can use it 81 state.Put("sshHostPort", sshHostPort) 82 83 return multistep.ActionContinue 84 } 85 86 func (s *StepForwardSSH) Cleanup(state multistep.StateBag) {}