From 4e73c85e226f45a56154567d47ed3859e5d53f2a Mon Sep 17 00:00:00 2001 From: Ali Rizvi-Santiago Date: Fri, 16 Nov 2018 22:20:00 -0600 Subject: [PATCH 1/7] Re-sorted, grouped, and commented the options in the template VMX for the VMWare builder to keep things organized. --- builder/vmware/iso/step_create_vmx.go | 122 +++++++++++++++----------- 1 file changed, 70 insertions(+), 52 deletions(-) diff --git a/builder/vmware/iso/step_create_vmx.go b/builder/vmware/iso/step_create_vmx.go index 44d6d5e86..0255896d9 100644 --- a/builder/vmware/iso/step_create_vmx.go +++ b/builder/vmware/iso/step_create_vmx.go @@ -650,49 +650,50 @@ func (s *stepCreateVMX) Cleanup(multistep.StateBag) { // do so by specifying in the builder configuration. const DefaultVMXTemplate = ` .encoding = "UTF-8" + +displayName = "{{ .Name }}" + +// Hardware +memsize = "512" + +config.version = "8" +virtualHW.productCompatibility = "hosted" +virtualHW.version = "{{ .Version }}" + +// Bootup +nvram = "{{ .Name }}.nvram" + +floppy0.present = "FALSE" bios.bootOrder = "hdd,cdrom" bios.hddOrder = "{{ .HDD_BootOrder }}" -checkpoint.vmState = "" -cleanShutdown = "TRUE" -config.version = "8" -displayName = "{{ .Name }}" -ehci.pciSlotNumber = "34" -ehci.present = "TRUE" -ethernet0.addressType = "generated" -ethernet0.bsdName = "en0" -ethernet0.connectionType = "{{ .Network_Type }}" -ethernet0.vnet = "{{ .Network_Device }}" -ethernet0.displayName = "Ethernet" -ethernet0.linkStatePropagation.enable = "FALSE" -ethernet0.pciSlotNumber = "33" -ethernet0.present = "TRUE" -ethernet0.virtualDev = "{{ .Network_Adapter }}" -ethernet0.wakeOnPcktRcv = "FALSE" + +// Configuration extendedConfigFile = "{{ .Name }}.vmxf" -floppy0.present = "FALSE" -guestOS = "{{ .GuestOS }}" gui.fullScreenAtPowerOn = "FALSE" gui.viewModeAtPowerOn = "windowed" hgfs.linkRootShare = "TRUE" hgfs.mapRootShare = "TRUE" - -scsi0.present = "{{ .SCSI_Present }}" -scsi0.virtualDev = "{{ .SCSI_diskAdapterType }}" -scsi0.pciSlotNumber = "16" -scsi0:0.redo = "" -sata0.present = "{{ .SATA_Present }}" -nvme0.present = "{{ .NVME_Present }}" - -{{ .DiskType }}0:0.present = "TRUE" -{{ .DiskType }}0:0.fileName = "{{ .DiskName }}.vmdk" - -{{ .CDROMType }}0:{{ .CDROMType_PrimarySecondary }}.present = "TRUE" -{{ .CDROMType }}0:{{ .CDROMType_PrimarySecondary }}.fileName = "{{ .ISOPath }}" -{{ .CDROMType }}0:{{ .CDROMType_PrimarySecondary }}.deviceType = "cdrom-image" - isolation.tools.hgfs.disable = "FALSE" -memsize = "512" -nvram = "{{ .Name }}.nvram" +proxyApps.publishToHost = "FALSE" +replay.filename = "" +replay.supported = "FALSE" + +checkpoint.vmState = "" +vmotion.checkpointFBSize = "65536000" + +// Power control +cleanShutdown = "TRUE" +powerType.powerOff = "soft" +powerType.powerOn = "soft" +powerType.reset = "soft" +powerType.suspend = "soft" + +// Tools +guestOS = "{{ .GuestOS }}" +tools.syncTime = "TRUE" +tools.upgrade.policy = "upgradeAtPowerCycle" + +// Bus pciBridge0.pciSlotNumber = "17" pciBridge0.present = "TRUE" pciBridge4.functions = "8" @@ -711,13 +712,40 @@ 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" + +ehci.present = "TRUE" +ehci.pciSlotNumber = "34" + +vmci0.present = "TRUE" +vmci0.id = "1861462627" +vmci0.pciSlotNumber = "35" + +// Network Adapter +ethernet0.addressType = "generated" +ethernet0.bsdName = "en0" +ethernet0.connectionType = "{{ .Network_Type }}" +ethernet0.vnet = "{{ .Network_Device }}" +ethernet0.displayName = "Ethernet" +ethernet0.linkStatePropagation.enable = "FALSE" +ethernet0.pciSlotNumber = "33" +ethernet0.present = "TRUE" +ethernet0.virtualDev = "{{ .Network_Adapter }}" +ethernet0.wakeOnPcktRcv = "FALSE" + +// Hard disks +scsi0.present = "{{ .SCSI_Present }}" +scsi0.virtualDev = "{{ .SCSI_diskAdapterType }}" +scsi0.pciSlotNumber = "16" +scsi0:0.redo = "" +sata0.present = "{{ .SATA_Present }}" +nvme0.present = "{{ .NVME_Present }}" + +{{ .DiskType }}0:0.present = "TRUE" +{{ .DiskType }}0:0.fileName = "{{ .DiskName }}.vmdk" + +{{ .CDROMType }}0:{{ .CDROMType_PrimarySecondary }}.present = "TRUE" +{{ .CDROMType }}0:{{ .CDROMType_PrimarySecondary }}.fileName = "{{ .ISOPath }}" +{{ .CDROMType }}0:{{ .CDROMType_PrimarySecondary }}.deviceType = "cdrom-image" // Sound sound.startConnected = "{{ .Sound_Present }}" @@ -725,9 +753,6 @@ sound.present = "{{ .Sound_Present }}" sound.fileName = "-1" sound.autodetect = "TRUE" -tools.syncTime = "TRUE" -tools.upgrade.policy = "upgradeAtPowerCycle" - // USB usb.pciSlotNumber = "32" usb.present = "{{ .Usb_Present }}" @@ -748,13 +773,6 @@ parallel0.startConnected = "{{ .Parallel_Present }}" parallel0.fileName = "{{ .Parallel_Filename }}" parallel0.autodetect = "{{ .Parallel_Auto }}" parallel0.bidirectional = "{{ .Parallel_Bidirectional }}" - -virtualHW.productCompatibility = "hosted" -virtualHW.version = "{{ .Version }}" -vmci0.id = "1861462627" -vmci0.pciSlotNumber = "35" -vmci0.present = "TRUE" -vmotion.checkpointFBSize = "65536000" ` const DefaultAdditionalDiskTemplate = ` From cd45248eaa02632cd7072ba00f65a3c7a76952bf Mon Sep 17 00:00:00 2001 From: Ali Rizvi-Santiago Date: Sat, 17 Nov 2018 01:23:28 -0600 Subject: [PATCH 2/7] Moved common hardware config options used by the vmware-iso builder into common/hw_config and added options for the CpuCount and MemorySize. --- builder/vmware/common/hw_config.go | 298 ++++++++++++++++++++++ builder/vmware/common/hw_config_test.go | 319 ++++++++++++++++++++++++ builder/vmware/iso/config.go | 26 +- builder/vmware/iso/step_create_vmx.go | 292 +++------------------- 4 files changed, 661 insertions(+), 274 deletions(-) create mode 100644 builder/vmware/common/hw_config.go create mode 100644 builder/vmware/common/hw_config_test.go diff --git a/builder/vmware/common/hw_config.go b/builder/vmware/common/hw_config.go new file mode 100644 index 000000000..69cf55970 --- /dev/null +++ b/builder/vmware/common/hw_config.go @@ -0,0 +1,298 @@ +package common + +import ( + "fmt" + "path/filepath" + "runtime" + "strings" + + "github.com/hashicorp/packer/template/interpolate" +) + +type HWConfig struct { + + // cpu information + CpuCount int `mapstructure:"cpu_count"` + MemorySize int `mapstructure:"memory_size"` + + // network type and adapter + Network string `mapstructure:"network"` + NetworkAdapterType string `mapstructure:"network_adapter_type"` + + // device presence + Sound bool `mapstructure:"sound"` + USB bool `mapstructure:"usb"` + + // communication ports + Serial string `mapstructure:"serial"` + Parallel string `mapstructure:"parallel"` +} + +func (c *HWConfig) Prepare(ctx *interpolate.Context) []error { + var errs []error + + // Hardware and cpu options + if c.CpuCount < 0 { + errs = append(errs, fmt.Errorf("An invalid cpu_count was specified (cpu_count < 0): %d", c.CpuCount)) + c.CpuCount = 0 + } + if c.CpuCount == 0 { + c.CpuCount = 1 + } + + if c.MemorySize < 0 { + errs = append(errs, fmt.Errorf("An invalid memory_size was specified (memory_size < 0): %d", c.MemorySize)) + c.MemorySize = 0 + } + if c.MemorySize == 0 { + c.MemorySize = 512 + } + + // Peripherals + if !c.Sound { + c.Sound = false + } + + if !c.USB { + c.USB = false + } + + if c.Parallel == "" { + c.Parallel = "none" + } + + if c.Serial == "" { + c.Serial = "none" + } + + return nil +} + +/* parallel port */ +type ParallelUnion struct { + Union interface{} + File *ParallelPortFile + Device *ParallelPortDevice + Auto *ParallelPortAuto +} +type ParallelPortFile struct { + Filename string +} +type ParallelPortDevice struct { + Bidirectional string + Devicename string +} +type ParallelPortAuto struct { + Bidirectional string +} + +func (c *HWConfig) HasParallel() bool { + return c.Parallel != "" +} + +func (c *HWConfig) ReadParallel() (*ParallelUnion, error) { + input := strings.SplitN(c.Parallel, ":", 2) + if len(input) < 1 { + return nil, fmt.Errorf("Unexpected format for parallel port: %s", c.Parallel) + } + + var formatType, formatOptions string + formatType = input[0] + if len(input) == 2 { + formatOptions = input[1] + } else { + formatOptions = "" + } + + switch strings.ToUpper(formatType) { + case "FILE": + res := &ParallelPortFile{Filename: filepath.FromSlash(formatOptions)} + return &ParallelUnion{Union: res, File: res}, nil + case "DEVICE": + comp := strings.Split(formatOptions, ",") + if len(comp) < 1 || len(comp) > 2 { + return nil, fmt.Errorf("Unexpected format for parallel port: %s", c.Parallel) + } + res := new(ParallelPortDevice) + res.Bidirectional = "FALSE" + res.Devicename = filepath.FromSlash(comp[0]) + if len(comp) > 1 { + switch strings.ToUpper(comp[1]) { + case "BI": + res.Bidirectional = "TRUE" + case "UNI": + res.Bidirectional = "FALSE" + default: + return nil, fmt.Errorf("Unknown direction %s specified for parallel port: %s", strings.ToUpper(comp[1]), c.Parallel) + } + } + return &ParallelUnion{Union: res, Device: res}, nil + + case "AUTO": + res := new(ParallelPortAuto) + switch strings.ToUpper(formatOptions) { + case "": + fallthrough + case "UNI": + res.Bidirectional = "FALSE" + case "BI": + res.Bidirectional = "TRUE" + default: + return nil, fmt.Errorf("Unknown direction %s specified for parallel port: %s", strings.ToUpper(formatOptions), c.Parallel) + } + return &ParallelUnion{Union: res, Auto: res}, nil + + case "NONE": + return &ParallelUnion{Union: nil}, nil + } + + return nil, fmt.Errorf("Unexpected format for parallel port: %s", c.Parallel) +} + +/* serial conversions */ +type SerialConfigPipe struct { + Filename string + Endpoint string + Host string + Yield string +} + +type SerialConfigFile struct { + Filename string + Yield string +} + +type SerialConfigDevice struct { + Devicename string + Yield string +} + +type SerialConfigAuto struct { + Devicename string + Yield string +} + +type SerialUnion struct { + Union interface{} + Pipe *SerialConfigPipe + File *SerialConfigFile + Device *SerialConfigDevice + Auto *SerialConfigAuto +} + +func (c *HWConfig) HasSerial() bool { + return c.Serial != "" +} + +func (c *HWConfig) ReadSerial() (*SerialUnion, error) { + var defaultSerialPort string + if runtime.GOOS == "windows" { + defaultSerialPort = "COM1" + } else { + defaultSerialPort = "/dev/ttyS0" + } + + input := strings.SplitN(c.Serial, ":", 2) + if len(input) < 1 { + return nil, fmt.Errorf("Unexpected format for serial port: %s", c.Serial) + } + + var formatType, formatOptions string + formatType = input[0] + if len(input) == 2 { + formatOptions = input[1] + } else { + formatOptions = "" + } + + switch strings.ToUpper(formatType) { + case "PIPE": + comp := strings.Split(formatOptions, ",") + if len(comp) < 3 || len(comp) > 4 { + return nil, fmt.Errorf("Unexpected format for serial port pipe: %s", c.Serial) + } + if res := strings.ToLower(comp[1]); res != "client" && res != "server" { + return nil, fmt.Errorf("Unexpected format for endpoint in serial port pipe: %s -> %s", c.Serial, res) + } + if res := strings.ToLower(comp[2]); res != "app" && res != "vm" { + return nil, fmt.Errorf("Unexpected format for host in serial port pipe: %s -> %s", c.Serial, res) + } + res := &SerialConfigPipe{ + Filename: comp[0], + Endpoint: comp[1], + Host: map[string]string{"app": "TRUE", "vm": "FALSE"}[strings.ToLower(comp[2])], + Yield: "FALSE", + } + if len(comp) == 4 { + res.Yield = strings.ToUpper(comp[3]) + } + if res.Yield != "TRUE" && res.Yield != "FALSE" { + return nil, fmt.Errorf("Unexpected format for yield in serial port pipe: %s -> %s", c.Serial, res.Yield) + } + return &SerialUnion{Union: res, Pipe: res}, nil + + case "FILE": + comp := strings.Split(formatOptions, ",") + if len(comp) > 2 { + return nil, fmt.Errorf("Unexpected format for serial port file: %s", c.Serial) + } + + res := &SerialConfigFile{Yield: "FALSE"} + + res.Filename = filepath.FromSlash(comp[0]) + + res.Yield = map[bool]string{true: strings.ToUpper(comp[1]), false: "FALSE"}[len(comp) > 1] + if res.Yield != "TRUE" && res.Yield != "FALSE" { + return nil, fmt.Errorf("Unexpected format for yield in serial port file: %s -> %s", c.Serial, res.Yield) + } + + return &SerialUnion{Union: res, File: res}, nil + + case "DEVICE": + comp := strings.Split(formatOptions, ",") + if len(comp) > 2 { + return nil, fmt.Errorf("Unexpected format for serial port device: %s", c.Serial) + } + + res := new(SerialConfigDevice) + + if len(comp) == 2 { + res.Devicename = map[bool]string{true: filepath.FromSlash(comp[0]), false: defaultSerialPort}[len(comp[0]) > 0] + res.Yield = strings.ToUpper(comp[1]) + } else if len(comp) == 1 { + res.Devicename = map[bool]string{true: filepath.FromSlash(comp[0]), false: defaultSerialPort}[len(comp[0]) > 0] + res.Yield = "FALSE" + } else if len(comp) == 0 { + res.Devicename = defaultSerialPort + res.Yield = "FALSE" + } + + if res.Yield != "TRUE" && res.Yield != "FALSE" { + return nil, fmt.Errorf("Unexpected format for yield in serial port device: %s -> %s", c.Serial, res.Yield) + } + + return &SerialUnion{Union: res, Device: res}, nil + + case "AUTO": + res := new(SerialConfigAuto) + res.Devicename = defaultSerialPort + + if len(formatOptions) > 0 { + res.Yield = strings.ToUpper(formatOptions) + } else { + res.Yield = "FALSE" + } + + if res.Yield != "TRUE" && res.Yield != "FALSE" { + return nil, fmt.Errorf("Unexpected format for yield in serial port auto: %s -> %s", c.Serial, res.Yield) + } + + return &SerialUnion{Union: res, Auto: res}, nil + + case "NONE": + return &SerialUnion{Union: nil}, nil + + default: + return nil, fmt.Errorf("Unknown serial type %s: %s", strings.ToUpper(formatType), c.Serial) + } +} diff --git a/builder/vmware/common/hw_config_test.go b/builder/vmware/common/hw_config_test.go new file mode 100644 index 000000000..ce1f23277 --- /dev/null +++ b/builder/vmware/common/hw_config_test.go @@ -0,0 +1,319 @@ +package common + +import ( + "strings" + "testing" +) + +func testHWConfig() *HWConfig { + return &HWConfig{ + CpuCount: 1, + MemorySize: 512, + + Sound: true, + USB: true, + } +} + +func TestHWConfigPrepare(t *testing.T) { + c := new(HWConfig) + + if errs := c.Prepare(testConfigTemplate(t)); len(errs) > 0 { + t.Fatalf("err: %#v", errs) + } + + if c.CpuCount < 1 { + t.Errorf("bad cpu count: %d", c.CpuCount) + } + + if c.MemorySize < 0 { + t.Errorf("bad memory size: %d", c.MemorySize) + } + + if c.Sound { + t.Errorf("peripheral choice (sound) should be conservative: %t", c.Sound) + } + + if c.USB { + t.Errorf("peripheral choice (usb) should be conservative: %t", c.USB) + } + + if strings.ToUpper(c.Parallel) != "NONE" { + t.Errorf("parallel port should not be defined: %s", c.Parallel) + } + + if strings.ToUpper(c.Serial) != "NONE" { + t.Errorf("serial port should not be defined: %s", c.Serial) + } +} + +func TestHWConfigParallel_File(t *testing.T) { + c := new(HWConfig) + + c.Parallel = "file:filename" + if errs := c.Prepare(testConfigTemplate(t)); len(errs) > 0 { + t.Fatalf("err: %#v", errs) + } + + if !c.HasParallel() { + t.Errorf("parallel port should be defined") + } + + parallel, err := c.ReadParallel() + if err != nil { + t.Fatalf("Unable to read parallel port definition: %s", err) + } + + switch parallel.Union.(type) { + case *ParallelPortFile: + break + default: + t.Errorf("parallel port should be a file type") + } + + if parallel.File.Filename != "filename" { + t.Errorf("parallel port filename should be \"filename\": %s", parallel.File.Filename) + } +} + +func TestHWConfigParallel_Device(t *testing.T) { + c := new(HWConfig) + + c.Parallel = "device:devicename,uni" + if errs := c.Prepare(testConfigTemplate(t)); len(errs) > 0 { + t.Fatalf("err: %#v", errs) + } + + if !c.HasParallel() { + t.Errorf("parallel port should be defined") + } + + parallel, err := c.ReadParallel() + if err != nil { + t.Fatalf("Unable to read parallel port definition: %s", err) + } + + switch parallel.Union.(type) { + case *ParallelPortDevice: + break + default: + t.Errorf("parallel port should be a device type") + } + + if strings.ToLower(parallel.Device.Bidirectional) != "false" { + t.Errorf("parallel port device should not be bidirectional: %s", parallel.Device.Bidirectional) + } + + if parallel.Device.Devicename != "devicename" { + t.Errorf("parallel port device should be \"devicename\": %s", parallel.Device.Devicename) + } +} + +func TestHWConfigParallel_Auto(t *testing.T) { + c := new(HWConfig) + + c.Parallel = "auto:bi" + if errs := c.Prepare(testConfigTemplate(t)); len(errs) > 0 { + t.Fatalf("err: %#v", errs) + } + + if !c.HasParallel() { + t.Errorf("parallel port should be defined") + } + + parallel, err := c.ReadParallel() + if err != nil { + t.Fatalf("Unable to read parallel port definition: %s", err) + } + + switch parallel.Union.(type) { + case *ParallelPortAuto: + break + default: + t.Errorf("parallel port should be an auto type") + } + + if strings.ToLower(parallel.Auto.Bidirectional) != "true" { + t.Errorf("parallel port device should be bidirectional: %s", parallel.Auto.Bidirectional) + } +} + +func TestHWConfigParallel_None(t *testing.T) { + c := new(HWConfig) + + c.Parallel = "none" + if errs := c.Prepare(testConfigTemplate(t)); len(errs) > 0 { + t.Fatalf("err: %#v", errs) + } + + if !c.HasParallel() { + t.Errorf("parallel port should be defined") + } + + parallel, err := c.ReadParallel() + if err != nil { + t.Fatalf("Unable to read parallel port definition: %s", err) + } + + if parallel.Union != nil { + t.Errorf("parallel port shouldn't exist") + } +} + +func TestHWConfigSerial_File(t *testing.T) { + c := new(HWConfig) + + c.Serial = "file:filename,true" + if errs := c.Prepare(testConfigTemplate(t)); len(errs) > 0 { + t.Fatalf("err: %#v", errs) + } + + if !c.HasSerial() { + t.Errorf("serial port should be defined") + } + + serial, err := c.ReadSerial() + if err != nil { + t.Fatalf("Unable to read serial port definition: %s", err) + } + + switch serial.Union.(type) { + case *SerialConfigFile: + break + default: + t.Errorf("serial port should be a file type") + } + + if serial.File.Filename != "filename" { + t.Errorf("serial port filename should be \"filename\": %s", serial.File.Filename) + } + + if strings.ToLower(serial.File.Yield) != "true" { + t.Errorf("serial port yield should be true: %s", serial.File.Yield) + } +} + +func TestHWConfigSerial_Device(t *testing.T) { + c := new(HWConfig) + + c.Serial = "device:devicename,true" + if errs := c.Prepare(testConfigTemplate(t)); len(errs) > 0 { + t.Fatalf("err: %#v", errs) + } + + if !c.HasSerial() { + t.Errorf("serial port should be defined") + } + + serial, err := c.ReadSerial() + if err != nil { + t.Fatalf("Unable to read serial port definition: %s", err) + } + + switch serial.Union.(type) { + case *SerialConfigDevice: + break + default: + t.Errorf("serial port should be a device type") + } + + if serial.Device.Devicename != "devicename" { + t.Errorf("serial port device should be \"devicename\": %s", serial.Device.Devicename) + } + + if strings.ToLower(serial.Device.Yield) != "true" { + t.Errorf("serial port device should yield: %s", serial.Device.Yield) + } +} + +func TestHWConfigSerial_Pipe(t *testing.T) { + c := new(HWConfig) + + c.Serial = "pipe:mypath,client,app,true" + if errs := c.Prepare(testConfigTemplate(t)); len(errs) > 0 { + t.Fatalf("err: %#v", errs) + } + + if !c.HasSerial() { + t.Errorf("serial port should be defined") + } + + serial, err := c.ReadSerial() + if err != nil { + t.Fatalf("Unable to read serial port definition: %s", err) + } + + switch serial.Union.(type) { + case *SerialConfigPipe: + break + default: + t.Errorf("serial port should be a pipe type") + } + + if serial.Pipe.Filename != "mypath" { + t.Errorf("serial port pipe name should be \"mypath\": %s", serial.Pipe.Filename) + } + + if strings.ToLower(serial.Pipe.Endpoint) != "client" { + t.Errorf("serial port endpoint should be \"client\": %s", serial.Pipe.Endpoint) + } + + if strings.ToLower(serial.Pipe.Host) != "true" { + t.Errorf("serial port host type for app should be true: %s", serial.Pipe.Host) + } + + if strings.ToLower(serial.Pipe.Yield) != "true" { + t.Errorf("serial port should yield: %s", serial.Pipe.Yield) + } +} + +func TestHWConfigSerial_Auto(t *testing.T) { + c := new(HWConfig) + + c.Serial = "auto:true" + if errs := c.Prepare(testConfigTemplate(t)); len(errs) > 0 { + t.Fatalf("err: %#v", errs) + } + + if !c.HasSerial() { + t.Errorf("serial port should be defined") + } + + serial, err := c.ReadSerial() + if err != nil { + t.Fatalf("Unable to read serial port definition: %s", err) + } + + switch serial.Union.(type) { + case *SerialConfigAuto: + break + default: + t.Errorf("serial port should be an auto type") + } + + if strings.ToLower(serial.Auto.Yield) != "true" { + t.Errorf("serial port should yield: %s", serial.Auto.Yield) + } +} + +func TestHWConfigSerial_None(t *testing.T) { + c := new(HWConfig) + + c.Serial = "none" + if errs := c.Prepare(testConfigTemplate(t)); len(errs) > 0 { + t.Fatalf("err: %#v", errs) + } + + if !c.HasSerial() { + t.Errorf("serial port should be defined") + } + + serial, err := c.ReadSerial() + if err != nil { + t.Fatalf("Unable to read serial port definition: %s", err) + } + + if serial.Union != nil { + t.Errorf("serial port shouldn't exist") + } +} diff --git a/builder/vmware/iso/config.go b/builder/vmware/iso/config.go index 99010ce26..ec7d5822b 100644 --- a/builder/vmware/iso/config.go +++ b/builder/vmware/iso/config.go @@ -21,6 +21,7 @@ type Config struct { common.FloppyConfig `mapstructure:",squash"` bootcommand.VNCConfig `mapstructure:",squash"` vmwcommon.DriverConfig `mapstructure:",squash"` + vmwcommon.HWConfig `mapstructure:",squash"` vmwcommon.OutputConfig `mapstructure:",squash"` vmwcommon.RunConfig `mapstructure:",squash"` vmwcommon.ShutdownConfig `mapstructure:",squash"` @@ -45,18 +46,6 @@ type Config struct { Version string `mapstructure:"version"` VMName string `mapstructure:"vm_name"` - // Network adapter and type - NetworkAdapterType string `mapstructure:"network_adapter_type"` - Network string `mapstructure:"network"` - - // device presence - Sound bool `mapstructure:"sound"` - USB bool `mapstructure:"usb"` - - // communication ports - Serial string `mapstructure:"serial"` - Parallel string `mapstructure:"parallel"` - VMXDiskTemplatePath string `mapstructure:"vmx_disk_template_path"` VMXTemplatePath string `mapstructure:"vmx_template_path"` @@ -87,6 +76,7 @@ func NewConfig(raws ...interface{}) (*Config, []string, error) { warnings = append(warnings, isoWarnings...) errs = packer.MultiErrorAppend(errs, isoErrs...) errs = packer.MultiErrorAppend(errs, c.HTTPConfig.Prepare(&c.ctx)...) + errs = packer.MultiErrorAppend(errs, c.HWConfig.Prepare(&c.ctx)...) errs = packer.MultiErrorAppend(errs, c.DriverConfig.Prepare(&c.ctx)...) errs = packer.MultiErrorAppend(errs, c.OutputConfig.Prepare(&c.ctx, &c.PackerConfig)...) @@ -160,16 +150,8 @@ func NewConfig(raws ...interface{}) (*Config, []string, error) { } } - if c.Network == "" { - c.Network = "nat" - } - - if !c.Sound { - c.Sound = false - } - - if !c.USB { - c.USB = false + if c.HWConfig.Network == "" { + c.HWConfig.Network = "nat" } // Remote configuration validation diff --git a/builder/vmware/iso/step_create_vmx.go b/builder/vmware/iso/step_create_vmx.go index 0255896d9..dba6746a7 100644 --- a/builder/vmware/iso/step_create_vmx.go +++ b/builder/vmware/iso/step_create_vmx.go @@ -6,7 +6,7 @@ import ( "io/ioutil" "os" "path/filepath" - "runtime" + "strconv" "strings" vmwcommon "github.com/hashicorp/packer/builder/vmware/common" @@ -21,6 +21,9 @@ type vmxTemplateData struct { ISOPath string Version string + CpuCount string + MemorySize string + HDD_BootOrder string SCSI_Present string @@ -72,227 +75,6 @@ type stepCreateVMX struct { tempDir string } -/* serial conversions */ -type serialConfigPipe struct { - filename string - endpoint string - host string - yield string -} - -type serialConfigFile struct { - filename string - yield string -} - -type serialConfigDevice struct { - devicename string - yield string -} - -type serialConfigAuto struct { - devicename string - yield string -} - -type serialUnion struct { - serialType interface{} - pipe *serialConfigPipe - file *serialConfigFile - device *serialConfigDevice - auto *serialConfigAuto -} - -func unformat_serial(config string) (*serialUnion, error) { - var defaultSerialPort string - if runtime.GOOS == "windows" { - defaultSerialPort = "COM1" - } else { - defaultSerialPort = "/dev/ttyS0" - } - - input := strings.SplitN(config, ":", 2) - if len(input) < 1 { - return nil, fmt.Errorf("Unexpected format for serial port: %s", config) - } - - var formatType, formatOptions string - formatType = input[0] - if len(input) == 2 { - formatOptions = input[1] - } else { - formatOptions = "" - } - - switch strings.ToUpper(formatType) { - case "PIPE": - comp := strings.Split(formatOptions, ",") - if len(comp) < 3 || len(comp) > 4 { - return nil, fmt.Errorf("Unexpected format for serial port : pipe : %s", config) - } - if res := strings.ToLower(comp[1]); res != "client" && res != "server" { - return nil, fmt.Errorf("Unexpected format for serial port : pipe : endpoint : %s : %s", res, config) - } - if res := strings.ToLower(comp[2]); res != "app" && res != "vm" { - return nil, fmt.Errorf("Unexpected format for serial port : pipe : host : %s : %s", res, config) - } - res := &serialConfigPipe{ - filename: comp[0], - endpoint: comp[1], - host: map[string]string{"app": "TRUE", "vm": "FALSE"}[strings.ToLower(comp[2])], - yield: "FALSE", - } - if len(comp) == 4 { - res.yield = strings.ToUpper(comp[3]) - } - if res.yield != "TRUE" && res.yield != "FALSE" { - return nil, fmt.Errorf("Unexpected format for serial port : pipe : yield : %s : %s", res.yield, config) - } - return &serialUnion{serialType: res, pipe: res}, nil - - case "FILE": - comp := strings.Split(formatOptions, ",") - if len(comp) > 2 { - return nil, fmt.Errorf("Unexpected format for serial port : file : %s", config) - } - - res := &serialConfigFile{yield: "FALSE"} - - res.filename = filepath.FromSlash(comp[0]) - - res.yield = map[bool]string{true: strings.ToUpper(comp[0]), false: "FALSE"}[len(comp) > 1] - if res.yield != "TRUE" && res.yield != "FALSE" { - return nil, fmt.Errorf("Unexpected format for serial port : file : yield : %s : %s", res.yield, config) - } - - return &serialUnion{serialType: res, file: res}, nil - - case "DEVICE": - comp := strings.Split(formatOptions, ",") - if len(comp) > 2 { - return nil, fmt.Errorf("Unexpected format for serial port : device : %s", config) - } - - res := new(serialConfigDevice) - - if len(comp) == 2 { - res.devicename = map[bool]string{true: filepath.FromSlash(comp[0]), false: defaultSerialPort}[len(comp[0]) > 0] - res.yield = strings.ToUpper(comp[1]) - } else if len(comp) == 1 { - res.devicename = map[bool]string{true: filepath.FromSlash(comp[0]), false: defaultSerialPort}[len(comp[0]) > 0] - res.yield = "FALSE" - } else if len(comp) == 0 { - res.devicename = defaultSerialPort - res.yield = "FALSE" - } - - if res.yield != "TRUE" && res.yield != "FALSE" { - return nil, fmt.Errorf("Unexpected format for serial port : device : yield : %s : %s", res.yield, config) - } - - return &serialUnion{serialType: res, device: res}, nil - - case "AUTO": - res := new(serialConfigAuto) - res.devicename = defaultSerialPort - - if len(formatOptions) > 0 { - res.yield = strings.ToUpper(formatOptions) - } else { - res.yield = "FALSE" - } - - if res.yield != "TRUE" && res.yield != "FALSE" { - return nil, fmt.Errorf("Unexpected format for serial port : auto : yield : %s : %s", res.yield, config) - } - - return &serialUnion{serialType: res, auto: res}, nil - - case "NONE": - return &serialUnion{serialType: nil}, nil - - default: - return nil, fmt.Errorf("Unknown serial type : %s : %s", strings.ToUpper(formatType), config) - } -} - -/* parallel port */ -type parallelUnion struct { - parallelType interface{} - file *parallelPortFile - device *parallelPortDevice - auto *parallelPortAuto -} -type parallelPortFile struct { - filename string -} -type parallelPortDevice struct { - bidirectional string - devicename string -} -type parallelPortAuto struct { - bidirectional string -} - -func unformat_parallel(config string) (*parallelUnion, error) { - input := strings.SplitN(config, ":", 2) - if len(input) < 1 { - return nil, fmt.Errorf("Unexpected format for parallel port: %s", config) - } - - var formatType, formatOptions string - formatType = input[0] - if len(input) == 2 { - formatOptions = input[1] - } else { - formatOptions = "" - } - - switch strings.ToUpper(formatType) { - case "FILE": - res := ¶llelPortFile{filename: filepath.FromSlash(formatOptions)} - return ¶llelUnion{parallelType: res, file: res}, nil - case "DEVICE": - comp := strings.Split(formatOptions, ",") - if len(comp) < 1 || len(comp) > 2 { - return nil, fmt.Errorf("Unexpected format for parallel port: %s", config) - } - res := new(parallelPortDevice) - res.bidirectional = "FALSE" - res.devicename = filepath.FromSlash(comp[0]) - if len(comp) > 1 { - switch strings.ToUpper(comp[1]) { - case "BI": - res.bidirectional = "TRUE" - case "UNI": - res.bidirectional = "FALSE" - default: - return nil, fmt.Errorf("Unknown parallel port direction : %s : %s", strings.ToUpper(comp[0]), config) - } - } - return ¶llelUnion{parallelType: res, device: res}, nil - - case "AUTO": - res := new(parallelPortAuto) - switch strings.ToUpper(formatOptions) { - case "": - fallthrough - case "UNI": - res.bidirectional = "FALSE" - case "BI": - res.bidirectional = "TRUE" - default: - return nil, fmt.Errorf("Unknown parallel port direction : %s : %s", strings.ToUpper(formatOptions), config) - } - return ¶llelUnion{parallelType: res, auto: res}, nil - - case "NONE": - return ¶llelUnion{parallelType: nil}, nil - } - - return nil, fmt.Errorf("Unexpected format for parallel port: %s", config) -} - /* regular steps */ func (s *stepCreateVMX) Run(_ context.Context, state multistep.StateBag) multistep.StepAction { config := state.Get("config").(*Config) @@ -378,6 +160,9 @@ func (s *stepCreateVMX) Run(_ context.Context, state multistep.StateBag) multist Version: config.Version, ISOPath: isoPath, + CpuCount: strconv.Itoa(config.HWConfig.CpuCount), + MemorySize: strconv.Itoa(config.HWConfig.MemorySize), + SCSI_Present: "FALSE", SCSI_diskAdapterType: "lsilogic", SATA_Present: "FALSE", @@ -390,8 +175,8 @@ func (s *stepCreateVMX) Run(_ context.Context, state multistep.StateBag) multist Network_Adapter: "e1000", - Sound_Present: map[bool]string{true: "TRUE", false: "FALSE"}[bool(config.Sound)], - Usb_Present: map[bool]string{true: "TRUE", false: "FALSE"}[bool(config.USB)], + Sound_Present: map[bool]string{true: "TRUE", false: "FALSE"}[bool(config.HWConfig.Sound)], + Usb_Present: map[bool]string{true: "TRUE", false: "FALSE"}[bool(config.HWConfig.USB)], Serial_Present: "FALSE", Parallel_Present: "FALSE", @@ -462,13 +247,13 @@ func (s *stepCreateVMX) Run(_ context.Context, state multistep.StateBag) multist } /// Assign the network adapter type into the template if one was specified. - network_adapter := strings.ToLower(config.NetworkAdapterType) + network_adapter := strings.ToLower(config.HWConfig.NetworkAdapterType) if network_adapter != "" { templateData.Network_Adapter = network_adapter } /// Check the network type that the user specified - network := config.Network + network := config.HWConfig.Network driver := state.Get("driver").(vmwcommon.Driver).GetVmwareDriver() // check to see if the driver implements a network mapper for mapping @@ -514,10 +299,11 @@ func (s *stepCreateVMX) Run(_ context.Context, state multistep.StateBag) multist state.Put("vmnetwork", network) /// check if serial port has been configured - if config.Serial == "" { + if !config.HWConfig.HasSerial() { templateData.Serial_Present = "FALSE" } else { - serial, err := unformat_serial(config.Serial) + // FIXME + serial, err := config.HWConfig.ReadSerial() if err != nil { err := fmt.Errorf("Error processing VMX template: %s", err) state.Put("error", err) @@ -532,23 +318,23 @@ func (s *stepCreateVMX) Run(_ context.Context, state multistep.StateBag) multist templateData.Serial_Host = "" templateData.Serial_Auto = "FALSE" - switch serial.serialType.(type) { - case *serialConfigPipe: + switch serial.Union.(type) { + case *vmwcommon.SerialConfigPipe: templateData.Serial_Type = "pipe" - templateData.Serial_Endpoint = serial.pipe.endpoint - templateData.Serial_Host = serial.pipe.host - templateData.Serial_Yield = serial.pipe.yield - templateData.Serial_Filename = filepath.FromSlash(serial.pipe.filename) - case *serialConfigFile: + templateData.Serial_Endpoint = serial.Pipe.Endpoint + templateData.Serial_Host = serial.Pipe.Host + templateData.Serial_Yield = serial.Pipe.Yield + templateData.Serial_Filename = filepath.FromSlash(serial.Pipe.Filename) + case *vmwcommon.SerialConfigFile: templateData.Serial_Type = "file" - templateData.Serial_Filename = filepath.FromSlash(serial.file.filename) - case *serialConfigDevice: + templateData.Serial_Filename = filepath.FromSlash(serial.File.Filename) + case *vmwcommon.SerialConfigDevice: templateData.Serial_Type = "device" - templateData.Serial_Filename = filepath.FromSlash(serial.device.devicename) - case *serialConfigAuto: + templateData.Serial_Filename = filepath.FromSlash(serial.Device.Devicename) + case *vmwcommon.SerialConfigAuto: templateData.Serial_Type = "device" - templateData.Serial_Filename = filepath.FromSlash(serial.auto.devicename) - templateData.Serial_Yield = serial.auto.yield + templateData.Serial_Filename = filepath.FromSlash(serial.Auto.Devicename) + templateData.Serial_Yield = serial.Auto.Yield templateData.Serial_Auto = "TRUE" case nil: templateData.Serial_Present = "FALSE" @@ -563,10 +349,11 @@ func (s *stepCreateVMX) Run(_ context.Context, state multistep.StateBag) multist } /// check if parallel port has been configured - if config.Parallel == "" { + if !config.HWConfig.HasParallel() { templateData.Parallel_Present = "FALSE" } else { - parallel, err := unformat_parallel(config.Parallel) + // FIXME + parallel, err := config.HWConfig.ReadParallel() if err != nil { err := fmt.Errorf("Error processing VMX template: %s", err) state.Put("error", err) @@ -575,18 +362,18 @@ func (s *stepCreateVMX) Run(_ context.Context, state multistep.StateBag) multist } templateData.Parallel_Auto = "FALSE" - switch parallel.parallelType.(type) { - case *parallelPortFile: + switch parallel.Union.(type) { + case *vmwcommon.ParallelPortFile: templateData.Parallel_Present = "TRUE" - templateData.Parallel_Filename = filepath.FromSlash(parallel.file.filename) - case *parallelPortDevice: + templateData.Parallel_Filename = filepath.FromSlash(parallel.File.Filename) + case *vmwcommon.ParallelPortDevice: templateData.Parallel_Present = "TRUE" - templateData.Parallel_Bidirectional = parallel.device.bidirectional - templateData.Parallel_Filename = filepath.FromSlash(parallel.device.devicename) - case *parallelPortAuto: + templateData.Parallel_Bidirectional = parallel.Device.Bidirectional + templateData.Parallel_Filename = filepath.FromSlash(parallel.Device.Devicename) + case *vmwcommon.ParallelPortAuto: templateData.Parallel_Present = "TRUE" templateData.Parallel_Auto = "TRUE" - templateData.Parallel_Bidirectional = parallel.auto.bidirectional + templateData.Parallel_Bidirectional = parallel.Auto.Bidirectional case nil: templateData.Parallel_Present = "FALSE" break @@ -654,7 +441,8 @@ const DefaultVMXTemplate = ` displayName = "{{ .Name }}" // Hardware -memsize = "512" +numvcpus = "{{ .CpuCount }}" +memsize = "{{ .MemorySize }}" config.version = "8" virtualHW.productCompatibility = "hosted" From e5f8ed7a0f411879f323529b783b8163cb5f4084 Mon Sep 17 00:00:00 2001 From: Ali Rizvi-Santiago Date: Sat, 17 Nov 2018 01:28:10 -0600 Subject: [PATCH 3/7] Added docs for the vmware-iso builder to describe the cpu_count and memory_size options. --- website/source/docs/builders/vmware-iso.html.md.erb | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/website/source/docs/builders/vmware-iso.html.md.erb b/website/source/docs/builders/vmware-iso.html.md.erb index afd532d30..62865d221 100644 --- a/website/source/docs/builders/vmware-iso.html.md.erb +++ b/website/source/docs/builders/vmware-iso.html.md.erb @@ -98,6 +98,8 @@ builder. five seconds and one minute 30 seconds, respectively. If this isn't specified, the default is `10s` or 10 seconds. +- `cpu_count` (number) - The number of cpus to use for the VM. + - `cdrom_adapter_type` (string) - The adapter type (or bus) that will be used by the cdrom device. This is chosen by default based on the disk adapter type. VMware tends to lean towards `ide` for the cdrom device unless @@ -221,6 +223,8 @@ builder. URLs must point to the same file (same checksum). By default this is empty and `iso_url` is used. Only one of `iso_url` or `iso_urls` can be specified. +- `memory_size` (number) - The amount of memory to use for the VM in megabytes. + - `network` (string) - This is the network type that the virtual machine will be created with. This can be one of the generic values that map to a device such as `hostonly`, `nat`, or `bridged`. If the network is not one of these @@ -403,7 +407,7 @@ builder. - `vmx_data` (object of key/value strings) - Arbitrary key/values to enter into the virtual machine VMX file. This is for advanced users who want to - set properties such as memory, CPU, etc. + set properties that aren't yet supported by the builder. - `vmx_data_post` (object of key/value strings) - Identical to `vmx_data`, except that it is run after the virtual machine is shutdown, and before the From 5467edbbc0c20f40a792ab0e5dd0f3e302215ab5 Mon Sep 17 00:00:00 2001 From: Ali Rizvi-Santiago Date: Sat, 17 Nov 2018 05:42:12 -0600 Subject: [PATCH 4/7] Updated the docs for the vmware-iso builder to be more descriptive wrt the cpu_count, memory_size, sound, and usb options. --- .../source/docs/builders/vmware-iso.html.md.erb | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/website/source/docs/builders/vmware-iso.html.md.erb b/website/source/docs/builders/vmware-iso.html.md.erb index 62865d221..11c1da61b 100644 --- a/website/source/docs/builders/vmware-iso.html.md.erb +++ b/website/source/docs/builders/vmware-iso.html.md.erb @@ -98,7 +98,8 @@ builder. five seconds and one minute 30 seconds, respectively. If this isn't specified, the default is `10s` or 10 seconds. -- `cpu_count` (number) - The number of cpus to use for the VM. +- `cpu_count` (number) - The number of cpus to use when building the VM. + Defaults to building with just one. - `cdrom_adapter_type` (string) - The adapter type (or bus) that will be used by the cdrom device. This is chosen by default based on the disk adapter @@ -223,7 +224,8 @@ builder. URLs must point to the same file (same checksum). By default this is empty and `iso_url` is used. Only one of `iso_url` or `iso_urls` can be specified. -- `memory_size` (number) - The amount of memory to use for the VM in megabytes. +- `memory_size` (number) - The amount of memory to use when building the VM + in megabytes. Defaults to `512` megabytes. - `network` (string) - This is the network type that the virtual machine will be created with. This can be one of the generic values that map to a device @@ -375,7 +377,8 @@ builder. given are valid. If you set this flag to `true`, Packer will skip this validation. Default: `false`. -- `sound` (boolean) - Enable VMware's virtual soundcard device for the VM. +- `sound` (boolean) - Specify whether to enable VMware's virtual soundcard + device when building the VM. Defaults to `false`. - `tools_upload_flavor` (string) - The flavor of the VMware Tools ISO to upload into the VM. Valid values are `darwin`, `linux`, and `windows`. By @@ -389,9 +392,10 @@ builder. By default the upload path is set to `{{.Flavor}}.iso`. This setting is not used when `remote_type` is `esx5`. -- `usb` (boolean) - Enable VMware's USB bus for the guest VM. To enable usage - of the XHCI bus for USB 3 (5 Gbit/s), one can use the `vmx_data` option to - enable it by specifying `true` for the `usb_xhci.present` property. +- `usb` (boolean) - Enable VMware's USB bus when building the guest VM. + Defaults to `false`. To enable usage of the XHCI bus for USB 3 (5 Gbit/s), + one can use the `vmx_data` option to enable it by specifying `true` for + the `usb_xhci.present` property. - `version` (string) - The [vmx hardware version](http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=1003746) From fb7ce9f2b5d451f3c35982c6847702aeadcd5999 Mon Sep 17 00:00:00 2001 From: Ali Rizvi-Santiago Date: Sat, 17 Nov 2018 06:36:02 -0600 Subject: [PATCH 5/7] Renamed both `cpu_count` and `memory_size` to `cpus` and `memory` (respective). --- builder/vmware/common/hw_config.go | 8 ++++---- website/source/docs/builders/vmware-iso.html.md.erb | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/builder/vmware/common/hw_config.go b/builder/vmware/common/hw_config.go index 69cf55970..7f6b65034 100644 --- a/builder/vmware/common/hw_config.go +++ b/builder/vmware/common/hw_config.go @@ -12,8 +12,8 @@ import ( type HWConfig struct { // cpu information - CpuCount int `mapstructure:"cpu_count"` - MemorySize int `mapstructure:"memory_size"` + CpuCount int `mapstructure:"cpus"` + MemorySize int `mapstructure:"memory"` // network type and adapter Network string `mapstructure:"network"` @@ -33,7 +33,7 @@ func (c *HWConfig) Prepare(ctx *interpolate.Context) []error { // Hardware and cpu options if c.CpuCount < 0 { - errs = append(errs, fmt.Errorf("An invalid cpu_count was specified (cpu_count < 0): %d", c.CpuCount)) + errs = append(errs, fmt.Errorf("An invalid number of cpus was specified (cpus < 0): %d", c.CpuCount)) c.CpuCount = 0 } if c.CpuCount == 0 { @@ -41,7 +41,7 @@ func (c *HWConfig) Prepare(ctx *interpolate.Context) []error { } if c.MemorySize < 0 { - errs = append(errs, fmt.Errorf("An invalid memory_size was specified (memory_size < 0): %d", c.MemorySize)) + errs = append(errs, fmt.Errorf("An invalid amount of memory was specified (memory < 0): %d", c.MemorySize)) c.MemorySize = 0 } if c.MemorySize == 0 { diff --git a/website/source/docs/builders/vmware-iso.html.md.erb b/website/source/docs/builders/vmware-iso.html.md.erb index 11c1da61b..d0f8f5f13 100644 --- a/website/source/docs/builders/vmware-iso.html.md.erb +++ b/website/source/docs/builders/vmware-iso.html.md.erb @@ -98,7 +98,7 @@ builder. five seconds and one minute 30 seconds, respectively. If this isn't specified, the default is `10s` or 10 seconds. -- `cpu_count` (number) - The number of cpus to use when building the VM. +- `cpus` (number) - The number of cpus to use when building the VM. Defaults to building with just one. - `cdrom_adapter_type` (string) - The adapter type (or bus) that will be used @@ -224,7 +224,7 @@ builder. URLs must point to the same file (same checksum). By default this is empty and `iso_url` is used. Only one of `iso_url` or `iso_urls` can be specified. -- `memory_size` (number) - The amount of memory to use when building the VM +- `memory` (number) - The amount of memory to use when building the VM in megabytes. Defaults to `512` megabytes. - `network` (string) - This is the network type that the virtual machine will From 61ee3a44f5365032549e684f23cc10ab7daff1e3 Mon Sep 17 00:00:00 2001 From: Ali Rizvi-Santiago Date: Wed, 21 Nov 2018 00:43:14 -0600 Subject: [PATCH 6/7] Modified the cpus and memory options for the vmware builders to only apply them if they were specified. --- builder/vmware/common/hw_config.go | 6 ------ builder/vmware/common/hw_config_test.go | 2 +- builder/vmware/iso/step_create_vmx.go | 19 +++++++++++++++---- 3 files changed, 16 insertions(+), 11 deletions(-) diff --git a/builder/vmware/common/hw_config.go b/builder/vmware/common/hw_config.go index 7f6b65034..fa092402b 100644 --- a/builder/vmware/common/hw_config.go +++ b/builder/vmware/common/hw_config.go @@ -36,17 +36,11 @@ func (c *HWConfig) Prepare(ctx *interpolate.Context) []error { errs = append(errs, fmt.Errorf("An invalid number of cpus was specified (cpus < 0): %d", c.CpuCount)) c.CpuCount = 0 } - if c.CpuCount == 0 { - c.CpuCount = 1 - } if c.MemorySize < 0 { errs = append(errs, fmt.Errorf("An invalid amount of memory was specified (memory < 0): %d", c.MemorySize)) c.MemorySize = 0 } - if c.MemorySize == 0 { - c.MemorySize = 512 - } // Peripherals if !c.Sound { diff --git a/builder/vmware/common/hw_config_test.go b/builder/vmware/common/hw_config_test.go index ce1f23277..be884b144 100644 --- a/builder/vmware/common/hw_config_test.go +++ b/builder/vmware/common/hw_config_test.go @@ -22,7 +22,7 @@ func TestHWConfigPrepare(t *testing.T) { t.Fatalf("err: %#v", errs) } - if c.CpuCount < 1 { + if c.CpuCount < 0 { t.Errorf("bad cpu count: %d", c.CpuCount) } diff --git a/builder/vmware/iso/step_create_vmx.go b/builder/vmware/iso/step_create_vmx.go index dba6746a7..5aca4485f 100644 --- a/builder/vmware/iso/step_create_vmx.go +++ b/builder/vmware/iso/step_create_vmx.go @@ -160,9 +160,6 @@ func (s *stepCreateVMX) Run(_ context.Context, state multistep.StateBag) multist Version: config.Version, ISOPath: isoPath, - CpuCount: strconv.Itoa(config.HWConfig.CpuCount), - MemorySize: strconv.Itoa(config.HWConfig.MemorySize), - SCSI_Present: "FALSE", SCSI_diskAdapterType: "lsilogic", SATA_Present: "FALSE", @@ -413,8 +410,22 @@ func (s *stepCreateVMX) Run(_ context.Context, state multistep.StateBag) multist s.tempDir = vmxDir } + /// Now to handle options that will modify the template + vmxData := vmwcommon.ParseVMX(vmxContents) + + // Set the number of cpus if it was specified + if config.HWConfig.CpuCount > 0 { + vmxData["numvcpus"] = strconv.Itoa(config.HWConfig.CpuCount) + } + + // Apply the memory size that was specified + if config.HWConfig.MemorySize > 0 { + vmxData["memsize"] = strconv.Itoa(config.HWConfig.MemorySize) + } + + /// Write the vmxData to the vmxPath vmxPath := filepath.Join(vmxDir, config.VMName+".vmx") - if err := vmwcommon.WriteVMX(vmxPath, vmwcommon.ParseVMX(vmxContents)); err != nil { + if err := vmwcommon.WriteVMX(vmxPath, vmxData); err != nil { err := fmt.Errorf("Error creating VMX file: %s", err) state.Put("error", err) ui.Error(err.Error()) From f8c23c1808e603f48fb9e779030cac4e224dcb27 Mon Sep 17 00:00:00 2001 From: Ali Rizvi-Santiago Date: Thu, 22 Nov 2018 21:03:06 -0600 Subject: [PATCH 7/7] Updated things related to the vmware-iso builder to include @azr's suggestions. --- builder/vmware/common/hw_config.go | 4 +--- website/source/docs/builders/vmware-iso.html.md.erb | 3 +-- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/builder/vmware/common/hw_config.go b/builder/vmware/common/hw_config.go index fa092402b..d740025c2 100644 --- a/builder/vmware/common/hw_config.go +++ b/builder/vmware/common/hw_config.go @@ -34,12 +34,10 @@ func (c *HWConfig) Prepare(ctx *interpolate.Context) []error { // Hardware and cpu options if c.CpuCount < 0 { errs = append(errs, fmt.Errorf("An invalid number of cpus was specified (cpus < 0): %d", c.CpuCount)) - c.CpuCount = 0 } if c.MemorySize < 0 { errs = append(errs, fmt.Errorf("An invalid amount of memory was specified (memory < 0): %d", c.MemorySize)) - c.MemorySize = 0 } // Peripherals @@ -59,7 +57,7 @@ func (c *HWConfig) Prepare(ctx *interpolate.Context) []error { c.Serial = "none" } - return nil + return errs } /* parallel port */ diff --git a/website/source/docs/builders/vmware-iso.html.md.erb b/website/source/docs/builders/vmware-iso.html.md.erb index d0f8f5f13..12d0d77cc 100644 --- a/website/source/docs/builders/vmware-iso.html.md.erb +++ b/website/source/docs/builders/vmware-iso.html.md.erb @@ -99,7 +99,6 @@ builder. specified, the default is `10s` or 10 seconds. - `cpus` (number) - The number of cpus to use when building the VM. - Defaults to building with just one. - `cdrom_adapter_type` (string) - The adapter type (or bus) that will be used by the cdrom device. This is chosen by default based on the disk adapter @@ -225,7 +224,7 @@ builder. and `iso_url` is used. Only one of `iso_url` or `iso_urls` can be specified. - `memory` (number) - The amount of memory to use when building the VM - in megabytes. Defaults to `512` megabytes. + in megabytes. - `network` (string) - This is the network type that the virtual machine will be created with. This can be one of the generic values that map to a device