From cd45248eaa02632cd7072ba00f65a3c7a76952bf Mon Sep 17 00:00:00 2001 From: Ali Rizvi-Santiago Date: Sat, 17 Nov 2018 01:23:28 -0600 Subject: [PATCH] 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"