package vmware import ( "fmt" "github.com/mitchellh/multistep" "github.com/mitchellh/packer/packer" "io/ioutil" "log" "os" "path/filepath" ) type vmxTemplateData struct { Name string GuestOS string DiskName string ISOPath string } // This step creates the VMX file for the VM. // // Uses: // config *config // iso_path string // ui packer.Ui // // Produces: // vmx_path string - The path to the VMX file. type stepCreateVMX struct{} func (stepCreateVMX) Run(state multistep.StateBag) multistep.StepAction { config := state.Get("config").(*config) isoPath := state.Get("iso_path").(string) ui := state.Get("ui").(packer.Ui) ui.Say("Building and writing VMX file") tplData := &vmxTemplateData{ Name: config.VMName, GuestOS: config.GuestOSType, DiskName: config.DiskName, ISOPath: isoPath, } vmxTemplate := DefaultVMXTemplate if config.VMXTemplatePath != "" { f, err := os.Open(config.VMXTemplatePath) if err != nil { err := fmt.Errorf("Error reading VMX template: %s", err) state.Put("error", err) ui.Error(err.Error()) return multistep.ActionHalt } defer f.Close() rawBytes, err := ioutil.ReadAll(f) if err != nil { err := fmt.Errorf("Error reading VMX template: %s", err) state.Put("error", err) ui.Error(err.Error()) return multistep.ActionHalt } vmxTemplate = string(rawBytes) } vmxContents, err := config.tpl.Process(vmxTemplate, tplData) if err != nil { err := fmt.Errorf("Error procesing VMX template: %s", err) state.Put("error", err) ui.Error(err.Error()) return multistep.ActionHalt } vmxData := ParseVMX(vmxContents) if config.VMXData != nil { log.Println("Setting custom VMX data...") for k, v := range config.VMXData { log.Printf("Setting VMX: '%s' = '%s'", k, v) vmxData[k] = v } } if floppyPathRaw, ok := state.GetOk("floppy_path"); ok { log.Println("Floppy path present, setting in VMX") vmxData["floppy0.present"] = "TRUE" vmxData["floppy0.fileType"] = "file" vmxData["floppy0.fileName"] = floppyPathRaw.(string) } // Set this so that no dialogs ever appear from Packer. vmxData["msg.autoAnswer"] = "true" vmxPath := filepath.Join(config.OutputDir, config.VMName+".vmx") if err := WriteVMX(vmxPath, vmxData); err != nil { err := fmt.Errorf("Error creating VMX file: %s", err) state.Put("error", err) ui.Error(err.Error()) return multistep.ActionHalt } state.Put("vmx_path", vmxPath) return multistep.ActionContinue } func (stepCreateVMX) Cleanup(multistep.StateBag) { } // This is the default VMX template used if no other template is given. // This is hardcoded here. If you wish to use a custom template please // do so by specifying in the builder configuration. const DefaultVMXTemplate = ` .encoding = "UTF-8" bios.bootOrder = "hdd,CDROM" checkpoint.vmState = "" cleanShutdown = "TRUE" config.version = "8" displayName = "{{ .Name }}" ehci.pciSlotNumber = "34" ehci.present = "TRUE" ethernet0.addressType = "generated" ethernet0.bsdName = "en0" ethernet0.connectionType = "nat" ethernet0.displayName = "Ethernet" ethernet0.linkStatePropagation.enable = "FALSE" ethernet0.pciSlotNumber = "33" ethernet0.present = "TRUE" ethernet0.virtualDev = "e1000" ethernet0.wakeOnPcktRcv = "FALSE" extendedConfigFile = "{{ .Name }}.vmxf" floppy0.present = "FALSE" guestOS = "{{ .GuestOS }}" gui.fullScreenAtPowerOn = "FALSE" gui.viewModeAtPowerOn = "windowed" hgfs.linkRootShare = "TRUE" hgfs.mapRootShare = "TRUE" ide1:0.present = "TRUE" ide1:0.fileName = "{{ .ISOPath }}" ide1:0.deviceType = "cdrom-image" isolation.tools.hgfs.disable = "FALSE" memsize = "512" nvram = "{{ .Name }}.nvram" pciBridge0.pciSlotNumber = "17" pciBridge0.present = "TRUE" pciBridge4.functions = "8" pciBridge4.pciSlotNumber = "21" pciBridge4.present = "TRUE" pciBridge4.virtualDev = "pcieRootPort" pciBridge5.functions = "8" pciBridge5.pciSlotNumber = "22" pciBridge5.present = "TRUE" pciBridge5.virtualDev = "pcieRootPort" pciBridge6.functions = "8" pciBridge6.pciSlotNumber = "23" pciBridge6.present = "TRUE" pciBridge6.virtualDev = "pcieRootPort" pciBridge7.functions = "8" pciBridge7.pciSlotNumber = "24" pciBridge7.present = "TRUE" pciBridge7.virtualDev = "pcieRootPort" powerType.powerOff = "soft" powerType.powerOn = "soft" powerType.reset = "soft" powerType.suspend = "soft" proxyApps.publishToHost = "FALSE" replay.filename = "" replay.supported = "FALSE" scsi0.pciSlotNumber = "16" scsi0.present = "TRUE" scsi0.virtualDev = "lsilogic" scsi0:0.fileName = "{{ .DiskName }}.vmdk" scsi0:0.present = "TRUE" scsi0:0.redo = "" sound.startConnected = "FALSE" tools.syncTime = "TRUE" tools.upgrade.policy = "upgradeAtPowerCycle" usb.pciSlotNumber = "32" usb.present = "FALSE" virtualHW.productCompatibility = "hosted" virtualHW.version = "9" vmci0.id = "1861462627" vmci0.pciSlotNumber = "35" vmci0.present = "TRUE" vmotion.checkpointFBSize = "65536000" `