step_create_vmx.go 4.7 KB
Newer Older
1 2 3 4 5 6
package vmware

import (
	"fmt"
	"github.com/mitchellh/multistep"
	"github.com/mitchellh/packer/packer"
7
	"io/ioutil"
8
	"log"
9
	"os"
10 11 12 13 14 15 16
	"path/filepath"
)

type vmxTemplateData struct {
	Name     string
	GuestOS  string
	DiskName string
17
	ISOPath  string
18 19
}

20 21 22 23
// This step creates the VMX file for the VM.
//
// Uses:
//   config *config
24
//   iso_path string
25 26 27
//   ui     packer.Ui
//
// Produces:
28
//   vmx_path string - The path to the VMX file.
29 30
type stepCreateVMX struct{}

31 32 33 34
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)
35

36
	ui.Say("Building and writing VMX file")
37 38

	tplData := &vmxTemplateData{
39 40 41 42
		Name:     config.VMName,
		GuestOS:  config.GuestOSType,
		DiskName: config.DiskName,
		ISOPath:  isoPath,
43 44
	}

45 46 47 48 49
	vmxTemplate := DefaultVMXTemplate
	if config.VMXTemplatePath != "" {
		f, err := os.Open(config.VMXTemplatePath)
		if err != nil {
			err := fmt.Errorf("Error reading VMX template: %s", err)
50
			state.Put("error", err)
51 52 53 54
			ui.Error(err.Error())
			return multistep.ActionHalt
		}
		defer f.Close()
55

56 57 58
		rawBytes, err := ioutil.ReadAll(f)
		if err != nil {
			err := fmt.Errorf("Error reading VMX template: %s", err)
59
			state.Put("error", err)
60 61 62 63 64 65 66 67 68 69
			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)
70
		state.Put("error", err)
71 72 73 74 75
		ui.Error(err.Error())
		return multistep.ActionHalt
	}

	vmxData := ParseVMX(vmxContents)
76 77 78 79 80 81 82 83
	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
		}
	}

84
	if floppyPathRaw, ok := state.GetOk("floppy_path"); ok {
85 86 87 88 89 90
		log.Println("Floppy path present, setting in VMX")
		vmxData["floppy0.present"] = "TRUE"
		vmxData["floppy0.fileType"] = "file"
		vmxData["floppy0.fileName"] = floppyPathRaw.(string)
	}

91 92
	vmxPath := filepath.Join(config.OutputDir, config.VMName+".vmx")
	if err := WriteVMX(vmxPath, vmxData); err != nil {
93
		err := fmt.Errorf("Error creating VMX file: %s", err)
94
		state.Put("error", err)
95
		ui.Error(err.Error())
96 97
		return multistep.ActionHalt
	}
98

99
	state.Put("vmx_path", vmxPath)
100

101 102 103
	return multistep.ActionContinue
}

104
func (stepCreateVMX) Cleanup(multistep.StateBag) {
105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134
}

// 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"
135 136 137
ide1:0.present = "TRUE"
ide1:0.fileName = "{{ .ISOPath }}"
ide1:0.deviceType = "cdrom-image"
138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183
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"
`