Merge pull request #7019 from arizvisa/vmware.cpu-memory
Add configuration options to vmware builder to specify cpu count and memory size
This commit is contained in:
commit
e539133d8c
|
@ -0,0 +1,290 @@
|
||||||
|
package common
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"path/filepath"
|
||||||
|
"runtime"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/hashicorp/packer/template/interpolate"
|
||||||
|
)
|
||||||
|
|
||||||
|
type HWConfig struct {
|
||||||
|
|
||||||
|
// cpu information
|
||||||
|
CpuCount int `mapstructure:"cpus"`
|
||||||
|
MemorySize int `mapstructure:"memory"`
|
||||||
|
|
||||||
|
// 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 number of cpus was specified (cpus < 0): %d", c.CpuCount))
|
||||||
|
}
|
||||||
|
|
||||||
|
if c.MemorySize < 0 {
|
||||||
|
errs = append(errs, fmt.Errorf("An invalid amount of memory was specified (memory < 0): %d", c.MemorySize))
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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 errs
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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 < 0 {
|
||||||
|
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"`
|
common.FloppyConfig `mapstructure:",squash"`
|
||||||
bootcommand.VNCConfig `mapstructure:",squash"`
|
bootcommand.VNCConfig `mapstructure:",squash"`
|
||||||
vmwcommon.DriverConfig `mapstructure:",squash"`
|
vmwcommon.DriverConfig `mapstructure:",squash"`
|
||||||
|
vmwcommon.HWConfig `mapstructure:",squash"`
|
||||||
vmwcommon.OutputConfig `mapstructure:",squash"`
|
vmwcommon.OutputConfig `mapstructure:",squash"`
|
||||||
vmwcommon.RunConfig `mapstructure:",squash"`
|
vmwcommon.RunConfig `mapstructure:",squash"`
|
||||||
vmwcommon.ShutdownConfig `mapstructure:",squash"`
|
vmwcommon.ShutdownConfig `mapstructure:",squash"`
|
||||||
|
@ -45,18 +46,6 @@ type Config struct {
|
||||||
Version string `mapstructure:"version"`
|
Version string `mapstructure:"version"`
|
||||||
VMName string `mapstructure:"vm_name"`
|
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"`
|
VMXDiskTemplatePath string `mapstructure:"vmx_disk_template_path"`
|
||||||
VMXTemplatePath string `mapstructure:"vmx_template_path"`
|
VMXTemplatePath string `mapstructure:"vmx_template_path"`
|
||||||
|
|
||||||
|
@ -87,6 +76,7 @@ func NewConfig(raws ...interface{}) (*Config, []string, error) {
|
||||||
warnings = append(warnings, isoWarnings...)
|
warnings = append(warnings, isoWarnings...)
|
||||||
errs = packer.MultiErrorAppend(errs, isoErrs...)
|
errs = packer.MultiErrorAppend(errs, isoErrs...)
|
||||||
errs = packer.MultiErrorAppend(errs, c.HTTPConfig.Prepare(&c.ctx)...)
|
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.DriverConfig.Prepare(&c.ctx)...)
|
||||||
errs = packer.MultiErrorAppend(errs,
|
errs = packer.MultiErrorAppend(errs,
|
||||||
c.OutputConfig.Prepare(&c.ctx, &c.PackerConfig)...)
|
c.OutputConfig.Prepare(&c.ctx, &c.PackerConfig)...)
|
||||||
|
@ -160,16 +150,8 @@ func NewConfig(raws ...interface{}) (*Config, []string, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.Network == "" {
|
if c.HWConfig.Network == "" {
|
||||||
c.Network = "nat"
|
c.HWConfig.Network = "nat"
|
||||||
}
|
|
||||||
|
|
||||||
if !c.Sound {
|
|
||||||
c.Sound = false
|
|
||||||
}
|
|
||||||
|
|
||||||
if !c.USB {
|
|
||||||
c.USB = false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remote configuration validation
|
// Remote configuration validation
|
||||||
|
|
|
@ -6,7 +6,7 @@ import (
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
vmwcommon "github.com/hashicorp/packer/builder/vmware/common"
|
vmwcommon "github.com/hashicorp/packer/builder/vmware/common"
|
||||||
|
@ -21,6 +21,9 @@ type vmxTemplateData struct {
|
||||||
ISOPath string
|
ISOPath string
|
||||||
Version string
|
Version string
|
||||||
|
|
||||||
|
CpuCount string
|
||||||
|
MemorySize string
|
||||||
|
|
||||||
HDD_BootOrder string
|
HDD_BootOrder string
|
||||||
|
|
||||||
SCSI_Present string
|
SCSI_Present string
|
||||||
|
@ -72,227 +75,6 @@ type stepCreateVMX struct {
|
||||||
tempDir string
|
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 */
|
/* regular steps */
|
||||||
func (s *stepCreateVMX) Run(_ context.Context, state multistep.StateBag) multistep.StepAction {
|
func (s *stepCreateVMX) Run(_ context.Context, state multistep.StateBag) multistep.StepAction {
|
||||||
config := state.Get("config").(*Config)
|
config := state.Get("config").(*Config)
|
||||||
|
@ -390,8 +172,8 @@ func (s *stepCreateVMX) Run(_ context.Context, state multistep.StateBag) multist
|
||||||
|
|
||||||
Network_Adapter: "e1000",
|
Network_Adapter: "e1000",
|
||||||
|
|
||||||
Sound_Present: map[bool]string{true: "TRUE", false: "FALSE"}[bool(config.Sound)],
|
Sound_Present: map[bool]string{true: "TRUE", false: "FALSE"}[bool(config.HWConfig.Sound)],
|
||||||
Usb_Present: map[bool]string{true: "TRUE", false: "FALSE"}[bool(config.USB)],
|
Usb_Present: map[bool]string{true: "TRUE", false: "FALSE"}[bool(config.HWConfig.USB)],
|
||||||
|
|
||||||
Serial_Present: "FALSE",
|
Serial_Present: "FALSE",
|
||||||
Parallel_Present: "FALSE",
|
Parallel_Present: "FALSE",
|
||||||
|
@ -462,13 +244,13 @@ func (s *stepCreateVMX) Run(_ context.Context, state multistep.StateBag) multist
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Assign the network adapter type into the template if one was specified.
|
/// 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 != "" {
|
if network_adapter != "" {
|
||||||
templateData.Network_Adapter = network_adapter
|
templateData.Network_Adapter = network_adapter
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Check the network type that the user specified
|
/// Check the network type that the user specified
|
||||||
network := config.Network
|
network := config.HWConfig.Network
|
||||||
driver := state.Get("driver").(vmwcommon.Driver).GetVmwareDriver()
|
driver := state.Get("driver").(vmwcommon.Driver).GetVmwareDriver()
|
||||||
|
|
||||||
// check to see if the driver implements a network mapper for mapping
|
// check to see if the driver implements a network mapper for mapping
|
||||||
|
@ -514,10 +296,11 @@ func (s *stepCreateVMX) Run(_ context.Context, state multistep.StateBag) multist
|
||||||
state.Put("vmnetwork", network)
|
state.Put("vmnetwork", network)
|
||||||
|
|
||||||
/// check if serial port has been configured
|
/// check if serial port has been configured
|
||||||
if config.Serial == "" {
|
if !config.HWConfig.HasSerial() {
|
||||||
templateData.Serial_Present = "FALSE"
|
templateData.Serial_Present = "FALSE"
|
||||||
} else {
|
} else {
|
||||||
serial, err := unformat_serial(config.Serial)
|
// FIXME
|
||||||
|
serial, err := config.HWConfig.ReadSerial()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err := fmt.Errorf("Error processing VMX template: %s", err)
|
err := fmt.Errorf("Error processing VMX template: %s", err)
|
||||||
state.Put("error", err)
|
state.Put("error", err)
|
||||||
|
@ -532,23 +315,23 @@ func (s *stepCreateVMX) Run(_ context.Context, state multistep.StateBag) multist
|
||||||
templateData.Serial_Host = ""
|
templateData.Serial_Host = ""
|
||||||
templateData.Serial_Auto = "FALSE"
|
templateData.Serial_Auto = "FALSE"
|
||||||
|
|
||||||
switch serial.serialType.(type) {
|
switch serial.Union.(type) {
|
||||||
case *serialConfigPipe:
|
case *vmwcommon.SerialConfigPipe:
|
||||||
templateData.Serial_Type = "pipe"
|
templateData.Serial_Type = "pipe"
|
||||||
templateData.Serial_Endpoint = serial.pipe.endpoint
|
templateData.Serial_Endpoint = serial.Pipe.Endpoint
|
||||||
templateData.Serial_Host = serial.pipe.host
|
templateData.Serial_Host = serial.Pipe.Host
|
||||||
templateData.Serial_Yield = serial.pipe.yield
|
templateData.Serial_Yield = serial.Pipe.Yield
|
||||||
templateData.Serial_Filename = filepath.FromSlash(serial.pipe.filename)
|
templateData.Serial_Filename = filepath.FromSlash(serial.Pipe.Filename)
|
||||||
case *serialConfigFile:
|
case *vmwcommon.SerialConfigFile:
|
||||||
templateData.Serial_Type = "file"
|
templateData.Serial_Type = "file"
|
||||||
templateData.Serial_Filename = filepath.FromSlash(serial.file.filename)
|
templateData.Serial_Filename = filepath.FromSlash(serial.File.Filename)
|
||||||
case *serialConfigDevice:
|
case *vmwcommon.SerialConfigDevice:
|
||||||
templateData.Serial_Type = "device"
|
templateData.Serial_Type = "device"
|
||||||
templateData.Serial_Filename = filepath.FromSlash(serial.device.devicename)
|
templateData.Serial_Filename = filepath.FromSlash(serial.Device.Devicename)
|
||||||
case *serialConfigAuto:
|
case *vmwcommon.SerialConfigAuto:
|
||||||
templateData.Serial_Type = "device"
|
templateData.Serial_Type = "device"
|
||||||
templateData.Serial_Filename = filepath.FromSlash(serial.auto.devicename)
|
templateData.Serial_Filename = filepath.FromSlash(serial.Auto.Devicename)
|
||||||
templateData.Serial_Yield = serial.auto.yield
|
templateData.Serial_Yield = serial.Auto.Yield
|
||||||
templateData.Serial_Auto = "TRUE"
|
templateData.Serial_Auto = "TRUE"
|
||||||
case nil:
|
case nil:
|
||||||
templateData.Serial_Present = "FALSE"
|
templateData.Serial_Present = "FALSE"
|
||||||
|
@ -563,10 +346,11 @@ func (s *stepCreateVMX) Run(_ context.Context, state multistep.StateBag) multist
|
||||||
}
|
}
|
||||||
|
|
||||||
/// check if parallel port has been configured
|
/// check if parallel port has been configured
|
||||||
if config.Parallel == "" {
|
if !config.HWConfig.HasParallel() {
|
||||||
templateData.Parallel_Present = "FALSE"
|
templateData.Parallel_Present = "FALSE"
|
||||||
} else {
|
} else {
|
||||||
parallel, err := unformat_parallel(config.Parallel)
|
// FIXME
|
||||||
|
parallel, err := config.HWConfig.ReadParallel()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err := fmt.Errorf("Error processing VMX template: %s", err)
|
err := fmt.Errorf("Error processing VMX template: %s", err)
|
||||||
state.Put("error", err)
|
state.Put("error", err)
|
||||||
|
@ -575,18 +359,18 @@ func (s *stepCreateVMX) Run(_ context.Context, state multistep.StateBag) multist
|
||||||
}
|
}
|
||||||
|
|
||||||
templateData.Parallel_Auto = "FALSE"
|
templateData.Parallel_Auto = "FALSE"
|
||||||
switch parallel.parallelType.(type) {
|
switch parallel.Union.(type) {
|
||||||
case *parallelPortFile:
|
case *vmwcommon.ParallelPortFile:
|
||||||
templateData.Parallel_Present = "TRUE"
|
templateData.Parallel_Present = "TRUE"
|
||||||
templateData.Parallel_Filename = filepath.FromSlash(parallel.file.filename)
|
templateData.Parallel_Filename = filepath.FromSlash(parallel.File.Filename)
|
||||||
case *parallelPortDevice:
|
case *vmwcommon.ParallelPortDevice:
|
||||||
templateData.Parallel_Present = "TRUE"
|
templateData.Parallel_Present = "TRUE"
|
||||||
templateData.Parallel_Bidirectional = parallel.device.bidirectional
|
templateData.Parallel_Bidirectional = parallel.Device.Bidirectional
|
||||||
templateData.Parallel_Filename = filepath.FromSlash(parallel.device.devicename)
|
templateData.Parallel_Filename = filepath.FromSlash(parallel.Device.Devicename)
|
||||||
case *parallelPortAuto:
|
case *vmwcommon.ParallelPortAuto:
|
||||||
templateData.Parallel_Present = "TRUE"
|
templateData.Parallel_Present = "TRUE"
|
||||||
templateData.Parallel_Auto = "TRUE"
|
templateData.Parallel_Auto = "TRUE"
|
||||||
templateData.Parallel_Bidirectional = parallel.auto.bidirectional
|
templateData.Parallel_Bidirectional = parallel.Auto.Bidirectional
|
||||||
case nil:
|
case nil:
|
||||||
templateData.Parallel_Present = "FALSE"
|
templateData.Parallel_Present = "FALSE"
|
||||||
break
|
break
|
||||||
|
@ -626,8 +410,22 @@ func (s *stepCreateVMX) Run(_ context.Context, state multistep.StateBag) multist
|
||||||
s.tempDir = vmxDir
|
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")
|
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)
|
err := fmt.Errorf("Error creating VMX file: %s", err)
|
||||||
state.Put("error", err)
|
state.Put("error", err)
|
||||||
ui.Error(err.Error())
|
ui.Error(err.Error())
|
||||||
|
@ -650,49 +448,51 @@ func (s *stepCreateVMX) Cleanup(multistep.StateBag) {
|
||||||
// do so by specifying in the builder configuration.
|
// do so by specifying in the builder configuration.
|
||||||
const DefaultVMXTemplate = `
|
const DefaultVMXTemplate = `
|
||||||
.encoding = "UTF-8"
|
.encoding = "UTF-8"
|
||||||
|
|
||||||
|
displayName = "{{ .Name }}"
|
||||||
|
|
||||||
|
// Hardware
|
||||||
|
numvcpus = "{{ .CpuCount }}"
|
||||||
|
memsize = "{{ .MemorySize }}"
|
||||||
|
|
||||||
|
config.version = "8"
|
||||||
|
virtualHW.productCompatibility = "hosted"
|
||||||
|
virtualHW.version = "{{ .Version }}"
|
||||||
|
|
||||||
|
// Bootup
|
||||||
|
nvram = "{{ .Name }}.nvram"
|
||||||
|
|
||||||
|
floppy0.present = "FALSE"
|
||||||
bios.bootOrder = "hdd,cdrom"
|
bios.bootOrder = "hdd,cdrom"
|
||||||
bios.hddOrder = "{{ .HDD_BootOrder }}"
|
bios.hddOrder = "{{ .HDD_BootOrder }}"
|
||||||
checkpoint.vmState = ""
|
|
||||||
cleanShutdown = "TRUE"
|
// Configuration
|
||||||
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"
|
|
||||||
extendedConfigFile = "{{ .Name }}.vmxf"
|
extendedConfigFile = "{{ .Name }}.vmxf"
|
||||||
floppy0.present = "FALSE"
|
|
||||||
guestOS = "{{ .GuestOS }}"
|
|
||||||
gui.fullScreenAtPowerOn = "FALSE"
|
gui.fullScreenAtPowerOn = "FALSE"
|
||||||
gui.viewModeAtPowerOn = "windowed"
|
gui.viewModeAtPowerOn = "windowed"
|
||||||
hgfs.linkRootShare = "TRUE"
|
hgfs.linkRootShare = "TRUE"
|
||||||
hgfs.mapRootShare = "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"
|
isolation.tools.hgfs.disable = "FALSE"
|
||||||
memsize = "512"
|
proxyApps.publishToHost = "FALSE"
|
||||||
nvram = "{{ .Name }}.nvram"
|
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.pciSlotNumber = "17"
|
||||||
pciBridge0.present = "TRUE"
|
pciBridge0.present = "TRUE"
|
||||||
pciBridge4.functions = "8"
|
pciBridge4.functions = "8"
|
||||||
|
@ -711,13 +511,40 @@ pciBridge7.functions = "8"
|
||||||
pciBridge7.pciSlotNumber = "24"
|
pciBridge7.pciSlotNumber = "24"
|
||||||
pciBridge7.present = "TRUE"
|
pciBridge7.present = "TRUE"
|
||||||
pciBridge7.virtualDev = "pcieRootPort"
|
pciBridge7.virtualDev = "pcieRootPort"
|
||||||
powerType.powerOff = "soft"
|
|
||||||
powerType.powerOn = "soft"
|
ehci.present = "TRUE"
|
||||||
powerType.reset = "soft"
|
ehci.pciSlotNumber = "34"
|
||||||
powerType.suspend = "soft"
|
|
||||||
proxyApps.publishToHost = "FALSE"
|
vmci0.present = "TRUE"
|
||||||
replay.filename = ""
|
vmci0.id = "1861462627"
|
||||||
replay.supported = "FALSE"
|
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
|
||||||
sound.startConnected = "{{ .Sound_Present }}"
|
sound.startConnected = "{{ .Sound_Present }}"
|
||||||
|
@ -725,9 +552,6 @@ sound.present = "{{ .Sound_Present }}"
|
||||||
sound.fileName = "-1"
|
sound.fileName = "-1"
|
||||||
sound.autodetect = "TRUE"
|
sound.autodetect = "TRUE"
|
||||||
|
|
||||||
tools.syncTime = "TRUE"
|
|
||||||
tools.upgrade.policy = "upgradeAtPowerCycle"
|
|
||||||
|
|
||||||
// USB
|
// USB
|
||||||
usb.pciSlotNumber = "32"
|
usb.pciSlotNumber = "32"
|
||||||
usb.present = "{{ .Usb_Present }}"
|
usb.present = "{{ .Usb_Present }}"
|
||||||
|
@ -748,13 +572,6 @@ parallel0.startConnected = "{{ .Parallel_Present }}"
|
||||||
parallel0.fileName = "{{ .Parallel_Filename }}"
|
parallel0.fileName = "{{ .Parallel_Filename }}"
|
||||||
parallel0.autodetect = "{{ .Parallel_Auto }}"
|
parallel0.autodetect = "{{ .Parallel_Auto }}"
|
||||||
parallel0.bidirectional = "{{ .Parallel_Bidirectional }}"
|
parallel0.bidirectional = "{{ .Parallel_Bidirectional }}"
|
||||||
|
|
||||||
virtualHW.productCompatibility = "hosted"
|
|
||||||
virtualHW.version = "{{ .Version }}"
|
|
||||||
vmci0.id = "1861462627"
|
|
||||||
vmci0.pciSlotNumber = "35"
|
|
||||||
vmci0.present = "TRUE"
|
|
||||||
vmotion.checkpointFBSize = "65536000"
|
|
||||||
`
|
`
|
||||||
|
|
||||||
const DefaultAdditionalDiskTemplate = `
|
const DefaultAdditionalDiskTemplate = `
|
||||||
|
|
|
@ -98,6 +98,8 @@ builder.
|
||||||
five seconds and one minute 30 seconds, respectively. If this isn't
|
five seconds and one minute 30 seconds, respectively. If this isn't
|
||||||
specified, the default is `10s` or 10 seconds.
|
specified, the default is `10s` or 10 seconds.
|
||||||
|
|
||||||
|
- `cpus` (number) - The number of cpus to use when building the VM.
|
||||||
|
|
||||||
- `cdrom_adapter_type` (string) - The adapter type (or bus) that will be used
|
- `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
|
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
|
type. VMware tends to lean towards `ide` for the cdrom device unless
|
||||||
|
@ -221,6 +223,9 @@ builder.
|
||||||
URLs must point to the same file (same checksum). By default this is empty
|
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.
|
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.
|
||||||
|
|
||||||
- `network` (string) - This is the network type that the virtual machine will
|
- `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
|
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
|
such as `hostonly`, `nat`, or `bridged`. If the network is not one of these
|
||||||
|
@ -371,7 +376,8 @@ builder.
|
||||||
given are valid. If you set this flag to `true`, Packer will skip this
|
given are valid. If you set this flag to `true`, Packer will skip this
|
||||||
validation. Default: `false`.
|
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
|
- `tools_upload_flavor` (string) - The flavor of the VMware Tools ISO to
|
||||||
upload into the VM. Valid values are `darwin`, `linux`, and `windows`. By
|
upload into the VM. Valid values are `darwin`, `linux`, and `windows`. By
|
||||||
|
@ -385,9 +391,10 @@ builder.
|
||||||
By default the upload path is set to `{{.Flavor}}.iso`. This setting is not
|
By default the upload path is set to `{{.Flavor}}.iso`. This setting is not
|
||||||
used when `remote_type` is `esx5`.
|
used when `remote_type` is `esx5`.
|
||||||
|
|
||||||
- `usb` (boolean) - Enable VMware's USB bus for the guest VM. To enable usage
|
- `usb` (boolean) - Enable VMware's USB bus when building the guest VM.
|
||||||
of the XHCI bus for USB 3 (5 Gbit/s), one can use the `vmx_data` option to
|
Defaults to `false`. To enable usage of the XHCI bus for USB 3 (5 Gbit/s),
|
||||||
enable it by specifying `true` for the `usb_xhci.present` property.
|
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` (string) - The [vmx hardware
|
||||||
version](http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=1003746)
|
version](http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=1003746)
|
||||||
|
@ -403,7 +410,7 @@ builder.
|
||||||
|
|
||||||
- `vmx_data` (object of key/value strings) - Arbitrary key/values to enter
|
- `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
|
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`,
|
- `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
|
except that it is run after the virtual machine is shutdown, and before the
|
||||||
|
|
Loading…
Reference in New Issue