Moved common hardware config options used by the vmware-iso builder into common/hw_config and added options for the CpuCount and MemorySize.
This commit is contained in:
parent
4e73c85e22
commit
cd45248eaa
|
@ -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)
|
||||
}
|
||||
}
|
|
@ -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")
|
||||
}
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
|
Loading…
Reference in New Issue