github.com/rothwerx/packer@v0.9.0/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 VNCPortMin uint 25 VNCPortMax uint 26 } 27 28 type VNCAddressFinder interface { 29 VNCAddress(uint, uint) (string, uint, error) 30 } 31 32 func (StepConfigureVNC) VNCAddress(portMin, portMax uint) (string, uint, error) { 33 // Find an open VNC port. Note that this can still fail later on 34 // because we have to release the port at some point. But this does its 35 // best. 36 var vncPort uint 37 portRange := int(portMax - portMin) 38 for { 39 if portRange > 0 { 40 vncPort = uint(rand.Intn(portRange)) + portMin 41 } else { 42 vncPort = portMin 43 } 44 45 log.Printf("Trying port: %d", vncPort) 46 l, err := net.Listen("tcp", fmt.Sprintf(":%d", vncPort)) 47 if err == nil { 48 defer l.Close() 49 break 50 } 51 } 52 return "127.0.0.1", vncPort, nil 53 } 54 55 func (s *StepConfigureVNC) Run(state multistep.StateBag) multistep.StepAction { 56 driver := state.Get("driver").(Driver) 57 ui := state.Get("ui").(packer.Ui) 58 vmxPath := state.Get("vmx_path").(string) 59 60 f, err := os.Open(vmxPath) 61 if err != nil { 62 err := fmt.Errorf("Error reading VMX data: %s", err) 63 state.Put("error", err) 64 ui.Error(err.Error()) 65 return multistep.ActionHalt 66 } 67 68 vmxBytes, err := ioutil.ReadAll(f) 69 if err != nil { 70 err := fmt.Errorf("Error reading VMX data: %s", err) 71 state.Put("error", err) 72 ui.Error(err.Error()) 73 return multistep.ActionHalt 74 } 75 76 var vncFinder VNCAddressFinder 77 if finder, ok := driver.(VNCAddressFinder); ok { 78 vncFinder = finder 79 } else { 80 vncFinder = s 81 } 82 log.Printf("Looking for available port between %d and %d", s.VNCPortMin, s.VNCPortMax) 83 vncIp, vncPort, err := vncFinder.VNCAddress(s.VNCPortMin, s.VNCPortMax) 84 if err != nil { 85 state.Put("error", err) 86 ui.Error(err.Error()) 87 return multistep.ActionHalt 88 } 89 90 log.Printf("Found available VNC port: %d", vncPort) 91 92 vmxData := ParseVMX(string(vmxBytes)) 93 vmxData["remotedisplay.vnc.enabled"] = "TRUE" 94 vmxData["remotedisplay.vnc.port"] = fmt.Sprintf("%d", vncPort) 95 96 if err := WriteVMX(vmxPath, vmxData); err != nil { 97 err := fmt.Errorf("Error writing VMX data: %s", err) 98 state.Put("error", err) 99 ui.Error(err.Error()) 100 return multistep.ActionHalt 101 } 102 103 state.Put("vnc_port", vncPort) 104 state.Put("vnc_ip", vncIp) 105 106 return multistep.ActionContinue 107 } 108 109 func (StepConfigureVNC) Cleanup(multistep.StateBag) { 110 }