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