github.com/marksheahan/packer@v0.10.2-0.20160613200515-1acb2d6645a0/builder/vmware/common/step_configure_vnc.go (about) 1 package common 2 3 import ( 4 "fmt" 5 "io/ioutil" 6 "log" 7 "math/rand" 8 "net" 9 "os" 10 11 "github.com/mitchellh/multistep" 12 "github.com/mitchellh/packer/packer" 13 ) 14 15 // This step configures the VM to enable the VNC server. 16 // 17 // Uses: 18 // ui packer.Ui 19 // vmx_path string 20 // 21 // Produces: 22 // vnc_port uint - The port that VNC is configured to listen on. 23 type StepConfigureVNC struct { 24 VNCBindAddress string 25 VNCPortMin uint 26 VNCPortMax uint 27 } 28 29 type VNCAddressFinder interface { 30 VNCAddress(string, uint, uint) (string, uint, error) 31 } 32 33 func (StepConfigureVNC) VNCAddress(vncBindAddress string, portMin, portMax uint) (string, uint, error) { 34 // Find an open VNC port. Note that this can still fail later on 35 // because we have to release the port at some point. But this does its 36 // best. 37 var vncPort uint 38 portRange := int(portMax - portMin) 39 for { 40 if portRange > 0 { 41 vncPort = uint(rand.Intn(portRange)) + portMin 42 } else { 43 vncPort = portMin 44 } 45 46 log.Printf("Trying port: %d", vncPort) 47 l, err := net.Listen("tcp", fmt.Sprintf("%s:%d", vncBindAddress, vncPort)) 48 if err == nil { 49 defer l.Close() 50 break 51 } 52 } 53 return vncBindAddress, vncPort, nil 54 } 55 56 func (s *StepConfigureVNC) Run(state multistep.StateBag) multistep.StepAction { 57 driver := state.Get("driver").(Driver) 58 ui := state.Get("ui").(packer.Ui) 59 vmxPath := state.Get("vmx_path").(string) 60 61 f, err := os.Open(vmxPath) 62 if err != nil { 63 err := fmt.Errorf("Error reading VMX data: %s", err) 64 state.Put("error", err) 65 ui.Error(err.Error()) 66 return multistep.ActionHalt 67 } 68 69 vmxBytes, err := ioutil.ReadAll(f) 70 if err != nil { 71 err := fmt.Errorf("Error reading VMX data: %s", err) 72 state.Put("error", err) 73 ui.Error(err.Error()) 74 return multistep.ActionHalt 75 } 76 77 var vncFinder VNCAddressFinder 78 if finder, ok := driver.(VNCAddressFinder); ok { 79 vncFinder = finder 80 } else { 81 vncFinder = s 82 } 83 log.Printf("Looking for available port between %d and %d", s.VNCPortMin, s.VNCPortMax) 84 vncBindAddress, vncPort, err := vncFinder.VNCAddress(s.VNCBindAddress, s.VNCPortMin, s.VNCPortMax) 85 if err != nil { 86 state.Put("error", err) 87 ui.Error(err.Error()) 88 return multistep.ActionHalt 89 } 90 91 log.Printf("Found available VNC port: %d", vncPort) 92 93 vmxData := ParseVMX(string(vmxBytes)) 94 vmxData["remotedisplay.vnc.enabled"] = "TRUE" 95 vmxData["remotedisplay.vnc.port"] = fmt.Sprintf("%d", vncPort) 96 vmxData["remotedisplay.vnc.ip"] = fmt.Sprintf("%s", vncBindAddress) 97 98 if err := WriteVMX(vmxPath, vmxData); err != nil { 99 err := fmt.Errorf("Error writing VMX data: %s", err) 100 state.Put("error", err) 101 ui.Error(err.Error()) 102 return multistep.ActionHalt 103 } 104 105 state.Put("vnc_port", vncPort) 106 state.Put("vnc_ip", vncBindAddress) 107 108 return multistep.ActionContinue 109 } 110 111 func (StepConfigureVNC) Cleanup(multistep.StateBag) { 112 }