Merge pull request #9928 from hashicorp/cd_files_impl_remaining_builders

implement cd_files option for qemu, hyperv-vmcx, and vmware-vmx builders
This commit is contained in:
Megan Marsh 2020-09-14 13:07:53 -07:00 committed by GitHub
commit 4f1892f6b9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 293 additions and 110 deletions

View File

@ -294,7 +294,10 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
GuestAdditionsPath: b.config.GuestAdditionsPath,
Generation: b.config.Generation,
},
&common.StepCreateCD{
Files: b.config.CDConfig.CDFiles,
Label: b.config.CDConfig.CDLabel,
},
&hypervcommon.StepMountSecondaryDvdImages{
IsoPaths: b.config.SecondaryDvdImages,
Generation: b.config.Generation,

View File

@ -77,6 +77,7 @@ type Config struct {
shutdowncommand.ShutdownConfig `mapstructure:",squash"`
CommConfig CommConfig `mapstructure:",squash"`
common.FloppyConfig `mapstructure:",squash"`
common.CDConfig `mapstructure:",squash"`
// Use iso from provided url. Qemu must support
// curl block device. This defaults to `false`.
ISOSkipCache bool `mapstructure:"iso_skip_cache" required:"false"`
@ -469,6 +470,7 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, []string, error) {
}
errs = packer.MultiErrorAppend(errs, b.config.FloppyConfig.Prepare(&b.config.ctx)...)
errs = packer.MultiErrorAppend(errs, b.config.CDConfig.Prepare(&b.config.ctx)...)
errs = packer.MultiErrorAppend(errs, b.config.VNCConfig.Prepare(&b.config.ctx)...)
if b.config.NetDevice == "" {
@ -622,6 +624,10 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
Directories: b.config.FloppyConfig.FloppyDirectories,
Label: b.config.FloppyConfig.FloppyLabel,
},
&common.StepCreateCD{
Files: b.config.CDConfig.CDFiles,
Label: b.config.CDConfig.CDLabel,
},
new(stepCreateDisk),
new(stepCopyDisk),
new(stepResizeDisk),

View File

@ -88,6 +88,8 @@ type FlatConfig struct {
FloppyFiles []string `mapstructure:"floppy_files" cty:"floppy_files" hcl:"floppy_files"`
FloppyDirectories []string `mapstructure:"floppy_dirs" cty:"floppy_dirs" hcl:"floppy_dirs"`
FloppyLabel *string `mapstructure:"floppy_label" cty:"floppy_label" hcl:"floppy_label"`
CDFiles []string `mapstructure:"cd_files" cty:"cd_files" hcl:"cd_files"`
CDLabel *string `mapstructure:"cd_label" cty:"cd_label" hcl:"cd_label"`
ISOSkipCache *bool `mapstructure:"iso_skip_cache" required:"false" cty:"iso_skip_cache" hcl:"iso_skip_cache"`
Accelerator *string `mapstructure:"accelerator" required:"false" cty:"accelerator" hcl:"accelerator"`
AdditionalDiskSize []string `mapstructure:"disk_additional_size" required:"false" cty:"disk_additional_size" hcl:"disk_additional_size"`
@ -215,6 +217,8 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
"floppy_files": &hcldec.AttrSpec{Name: "floppy_files", Type: cty.List(cty.String), Required: false},
"floppy_dirs": &hcldec.AttrSpec{Name: "floppy_dirs", Type: cty.List(cty.String), Required: false},
"floppy_label": &hcldec.AttrSpec{Name: "floppy_label", Type: cty.String, Required: false},
"cd_files": &hcldec.AttrSpec{Name: "cd_files", Type: cty.List(cty.String), Required: false},
"cd_label": &hcldec.AttrSpec{Name: "cd_label", Type: cty.String, Required: false},
"iso_skip_cache": &hcldec.AttrSpec{Name: "iso_skip_cache", Type: cty.Bool, Required: false},
"accelerator": &hcldec.AttrSpec{Name: "accelerator", Type: cty.String, Required: false},
"disk_additional_size": &hcldec.AttrSpec{Name: "disk_additional_size", Type: cty.List(cty.String), Required: false},

View File

@ -190,14 +190,26 @@ func getCommandArgs(bootDrive string, state multistep.StateBag) ([]string, error
}
}
cdPaths := []string{}
// Add the installation CD to the run command
if !config.DiskImage {
cdPaths = append(cdPaths, isoPath)
}
// Add our custom CD created from cd_files, if it exists
cdFilesPath, ok := state.Get("cd_path").(string)
if ok {
if cdFilesPath != "" {
cdPaths = append(cdPaths, cdFilesPath)
}
}
for i, cdPath := range cdPaths {
if config.CDROMInterface == "" {
defaultArgs["-cdrom"] = isoPath
driveArgs = append(driveArgs, fmt.Sprintf("file=%s,index=%d,media=cdrom", cdPath, i))
} else if config.CDROMInterface == "virtio-scsi" {
driveArgs = append(driveArgs, fmt.Sprintf("file=%s,if=none,id=cdrom,media=cdrom", isoPath))
deviceArgs = append(deviceArgs, "virtio-scsi-device", "scsi-cd,drive=cdrom")
driveArgs = append(driveArgs, fmt.Sprintf("file=%s,if=none,index=%d,id=cdrom%d,media=cdrom", cdPath, i, i))
deviceArgs = append(deviceArgs, "virtio-scsi-device", fmt.Sprintf("scsi-cd,drive=cdrom%d", i))
} else {
driveArgs = append(driveArgs, fmt.Sprintf("file=%s,if=%s,id=cdrom,media=cdrom", isoPath, config.CDROMInterface))
driveArgs = append(driveArgs, fmt.Sprintf("file=%s,if=%s,index=%d,id=cdrom%d,media=cdrom", cdPath, config.CDROMInterface, i, i))
}
}

View File

@ -20,10 +20,12 @@ import (
// Produces:
// display_name string - Value of the displayName key set in the VMX file
type StepConfigureVMX struct {
CustomData map[string]string
DisplayName string
SkipFloppy bool
VMName string
CustomData map[string]string
DisplayName string
SkipFloppy bool
VMName string
DiskAdapterType string
CDROMAdapterType string
}
func (s *StepConfigureVMX) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
@ -83,6 +85,17 @@ func (s *StepConfigureVMX) Run(ctx context.Context, state multistep.StateBag) mu
state.Put("temporaryDevices", tmpBuildDevices)
}
// Add our custom CD, if it exists
if cdPath, ok := state.GetOk("cd_path"); ok {
if cdPath != "" {
diskAndCDConfigData := DefaultDiskAndCDROMTypes(s.DiskAdapterType, s.CDROMAdapterType)
cdromPrefix := diskAndCDConfigData.CDROMType + "1:" + diskAndCDConfigData.CDROMType_PrimarySecondary
vmxData[cdromPrefix+".present"] = "TRUE"
vmxData[cdromPrefix+".fileName"] = cdPath.(string)
vmxData[cdromPrefix+".deviceType"] = "cdrom-image"
}
}
// If the build is taking place on a remote ESX server, the displayName
// will be needed for discovery of the VM's IP address and for export
// of the VM. The displayName key should always be set in the VMX file,
@ -125,5 +138,86 @@ func (s *StepConfigureVMX) Run(ctx context.Context, state multistep.StateBag) mu
return multistep.ActionContinue
}
type DiskAndCDConfigData struct {
SCSI_Present string
SCSI_diskAdapterType string
SATA_Present string
NVME_Present string
DiskType string
CDROMType string
CDROMType_PrimarySecondary string
CDROM_PATH string
}
// DefaultDiskAndCDROMTypes takes the disk adapter type and cdrom adapter type from the config and converts them
// into template interpolation data for creating or configuring a vmx.
func DefaultDiskAndCDROMTypes(diskAdapterType string, cdromAdapterType string) DiskAndCDConfigData {
diskData := DiskAndCDConfigData{
SCSI_Present: "FALSE",
SCSI_diskAdapterType: "lsilogic",
SATA_Present: "FALSE",
NVME_Present: "FALSE",
DiskType: "scsi",
CDROMType: "ide",
CDROMType_PrimarySecondary: "0",
}
/// Use the disk adapter type that the user specified to tweak the .vmx
// Also sync the cdrom adapter type according to what's common for that disk type.
// XXX: If the cdrom type is modified, make sure to update common/step_clean_vmx.go
// so that it will regex the correct cdrom device for removal.
diskAdapterType = strings.ToLower(diskAdapterType)
switch diskAdapterType {
case "ide":
diskData.DiskType = "ide"
diskData.CDROMType = "ide"
diskData.CDROMType_PrimarySecondary = "1"
case "sata":
diskData.SATA_Present = "TRUE"
diskData.DiskType = "sata"
diskData.CDROMType = "sata"
diskData.CDROMType_PrimarySecondary = "1"
case "nvme":
diskData.NVME_Present = "TRUE"
diskData.DiskType = "nvme"
diskData.SATA_Present = "TRUE"
diskData.CDROMType = "sata"
diskData.CDROMType_PrimarySecondary = "0"
case "scsi":
diskAdapterType = "lsilogic"
fallthrough
default:
diskData.SCSI_Present = "TRUE"
diskData.SCSI_diskAdapterType = diskAdapterType // defaults to lsilogic
diskData.DiskType = "scsi"
diskData.CDROMType = "ide"
diskData.CDROMType_PrimarySecondary = "0"
}
/// Handle the cdrom adapter type. If the disk adapter type and the
// cdrom adapter type are the same, then ensure that the cdrom is the
// secondary device on whatever bus the disk adapter is on.
if cdromAdapterType == "" {
cdromAdapterType = diskData.CDROMType
} else if cdromAdapterType == diskAdapterType {
diskData.CDROMType_PrimarySecondary = "1"
} else {
diskData.CDROMType_PrimarySecondary = "0"
}
switch cdromAdapterType {
case "ide":
diskData.CDROMType = "ide"
case "sata":
diskData.SATA_Present = "TRUE"
diskData.CDROMType = "sata"
case "scsi":
diskData.SCSI_Present = "TRUE"
diskData.CDROMType = "scsi"
}
return diskData
}
func (s *StepConfigureVMX) Cleanup(state multistep.StateBag) {
}

View File

@ -7,6 +7,7 @@ import (
"testing"
"github.com/hashicorp/packer/helper/multistep"
"github.com/stretchr/testify/assert"
)
func testVMXFile(t *testing.T) string {
@ -271,3 +272,108 @@ func TestStepConfigureVMX_vmxPathBad(t *testing.T) {
}
}
func TestStepConfigureVMX_DefaultDiskAndCDROMTypes(t *testing.T) {
type testCase struct {
inDiskAdapter string
inCDromAdapter string
expectedOut DiskAndCDConfigData
reason string
}
testcases := []testCase{
{
inDiskAdapter: "",
inCDromAdapter: "",
expectedOut: DiskAndCDConfigData{
SCSI_Present: "TRUE",
SCSI_diskAdapterType: "",
SATA_Present: "FALSE",
NVME_Present: "FALSE",
DiskType: "scsi",
CDROMType: "ide",
CDROMType_PrimarySecondary: "0",
},
reason: "Test that default creases scsi disk with ide cd",
},
{
inDiskAdapter: "ide",
inCDromAdapter: "",
expectedOut: DiskAndCDConfigData{
SCSI_Present: "FALSE",
SCSI_diskAdapterType: "lsilogic",
SATA_Present: "FALSE",
NVME_Present: "FALSE",
DiskType: "ide",
CDROMType: "ide",
CDROMType_PrimarySecondary: "1",
},
reason: "ide disk adapter should pass through and not get defaulted to scsi",
},
{
inDiskAdapter: "sata",
inCDromAdapter: "",
expectedOut: DiskAndCDConfigData{
SCSI_Present: "FALSE",
SCSI_diskAdapterType: "lsilogic",
SATA_Present: "TRUE",
NVME_Present: "FALSE",
DiskType: "sata",
CDROMType: "sata",
CDROMType_PrimarySecondary: "1",
},
reason: "when disk is set to sata, cdromtype should also default to sata",
},
{
inDiskAdapter: "nvme",
inCDromAdapter: "",
expectedOut: DiskAndCDConfigData{
SCSI_Present: "FALSE",
SCSI_diskAdapterType: "lsilogic",
SATA_Present: "TRUE",
NVME_Present: "TRUE",
DiskType: "nvme",
CDROMType: "sata",
CDROMType_PrimarySecondary: "0",
},
reason: "when disk is set to nvme, cdromtype should default to sata",
},
{
inDiskAdapter: "scsi",
inCDromAdapter: "",
expectedOut: DiskAndCDConfigData{
SCSI_Present: "TRUE",
SCSI_diskAdapterType: "lsilogic",
SATA_Present: "FALSE",
NVME_Present: "FALSE",
DiskType: "scsi",
CDROMType: "ide",
CDROMType_PrimarySecondary: "0",
},
reason: "when disk is set to scsi, adapter should default back to lsilogic",
},
{
inDiskAdapter: "scsi",
inCDromAdapter: "scsi",
expectedOut: DiskAndCDConfigData{
SCSI_Present: "TRUE",
SCSI_diskAdapterType: "lsilogic",
SATA_Present: "FALSE",
NVME_Present: "FALSE",
DiskType: "scsi",
CDROMType: "scsi",
CDROMType_PrimarySecondary: "0",
},
reason: "when cdrom adapter is set, it should override the default",
},
}
for _, tc := range testcases {
diskConfigData := DefaultDiskAndCDROMTypes(tc.inDiskAdapter, tc.inCDromAdapter)
assert.Equal(t, diskConfigData, tc.expectedOut, tc.reason)
}
}

View File

@ -123,9 +123,11 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
},
&stepCreateVMX{},
&vmwcommon.StepConfigureVMX{
CustomData: b.config.VMXData,
VMName: b.config.VMName,
DisplayName: b.config.VMXDisplayName,
CustomData: b.config.VMXData,
VMName: b.config.VMName,
DisplayName: b.config.VMXDisplayName,
DiskAdapterType: b.config.DiskAdapterType,
CDROMAdapterType: b.config.CdromAdapterType,
},
&vmwcommon.StepSuppressMessages{},
&vmwcommon.StepHTTPIPDiscover{},

View File

@ -193,6 +193,15 @@ func (c *Config) Prepare(raws ...interface{}) ([]string, error) {
errs = packer.MultiErrorAppend(errs, err)
}
if c.CdromAdapterType != "" {
c.CdromAdapterType = strings.ToLower(c.CdromAdapterType)
if c.CdromAdapterType != "ide" && c.CdromAdapterType != "sata" && c.CdromAdapterType != "scsi" {
errs = packer.MultiErrorAppend(errs,
fmt.Errorf("cdrom_adapter_type must be one of ide, sata, or scsi"))
}
}
// Warnings
if c.ShutdownCommand == "" {
warnings = append(warnings,
"A shutdown_command was not specified. Without a shutdown command, Packer\n"+

View File

@ -25,16 +25,8 @@ type vmxTemplateData struct {
CpuCount string
MemorySize string
SCSI_Present string
SCSI_diskAdapterType string
SATA_Present string
NVME_Present string
DiskName string
DiskType string
CDROMType string
CDROMType_PrimarySecondary string
CDROM_PATH string
DiskName string
vmwcommon.DiskAndCDConfigData
Network_Type string
Network_Device string
@ -162,15 +154,6 @@ func (s *stepCreateVMX) Run(ctx context.Context, state multistep.StateBag) multi
Version: config.Version,
ISOPath: isoPath,
SCSI_Present: "FALSE",
SCSI_diskAdapterType: "lsilogic",
SATA_Present: "FALSE",
NVME_Present: "FALSE",
DiskType: "scsi",
CDROMType: "ide",
CDROMType_PrimarySecondary: "0",
Network_Adapter: "e1000",
Sound_Present: map[bool]string{true: "TRUE", false: "FALSE"}[bool(config.HWConfig.Sound)],
@ -180,74 +163,7 @@ func (s *stepCreateVMX) Run(ctx context.Context, state multistep.StateBag) multi
Parallel_Present: "FALSE",
}
/// Use the disk adapter type that the user specified to tweak the .vmx
// Also sync the cdrom adapter type according to what's common for that disk type.
// XXX: If the cdrom type is modified, make sure to update common/step_clean_vmx.go
// so that it will regex the correct cdrom device for removal.
diskAdapterType := strings.ToLower(config.DiskAdapterType)
switch diskAdapterType {
case "ide":
templateData.DiskType = "ide"
templateData.CDROMType = "ide"
templateData.CDROMType_PrimarySecondary = "1"
case "sata":
templateData.SATA_Present = "TRUE"
templateData.DiskType = "sata"
templateData.CDROMType = "sata"
templateData.CDROMType_PrimarySecondary = "1"
case "nvme":
templateData.NVME_Present = "TRUE"
templateData.DiskType = "nvme"
templateData.SATA_Present = "TRUE"
templateData.CDROMType = "sata"
templateData.CDROMType_PrimarySecondary = "0"
case "scsi":
diskAdapterType = "lsilogic"
fallthrough
default:
templateData.SCSI_Present = "TRUE"
templateData.SCSI_diskAdapterType = diskAdapterType
templateData.DiskType = "scsi"
templateData.CDROMType = "ide"
templateData.CDROMType_PrimarySecondary = "0"
}
/// Handle the cdrom adapter type. If the disk adapter type and the
// cdrom adapter type are the same, then ensure that the cdrom is the
// secondary device on whatever bus the disk adapter is on.
cdromAdapterType := strings.ToLower(config.CdromAdapterType)
if cdromAdapterType == "" {
cdromAdapterType = templateData.CDROMType
} else if cdromAdapterType == diskAdapterType {
templateData.CDROMType_PrimarySecondary = "1"
} else {
templateData.CDROMType_PrimarySecondary = "0"
}
switch cdromAdapterType {
case "ide":
templateData.CDROMType = "ide"
case "sata":
templateData.SATA_Present = "TRUE"
templateData.CDROMType = "sata"
case "scsi":
templateData.SCSI_Present = "TRUE"
templateData.CDROMType = "scsi"
default:
err := fmt.Errorf("Error processing VMX template: %s", cdromAdapterType)
state.Put("error", err)
ui.Error(err.Error())
return multistep.ActionHalt
}
// Add our custom CD, if it exists
cd_path, ok := state.Get("cd_path").(string)
if ok {
if cd_path != "" {
vmxTemplate += ExtraCDRomTemplate
templateData.CDROM_PATH = cd_path
}
}
templateData.DiskAndCDConfigData = vmwcommon.DefaultDiskAndCDROMTypes(config.DiskAdapterType, config.CdromAdapterType)
/// Now that we figured out the CDROM device to add, store it
/// to the list of temporary build devices in our statebag
@ -607,9 +523,3 @@ scsi0:{{ .DiskNumber }}.fileName = "{{ .DiskName}}-{{ .DiskNumber }}.vmdk"
scsi0:{{ .DiskNumber }}.present = "TRUE"
scsi0:{{ .DiskNumber }}.redo = ""
`
const ExtraCDRomTemplate = `
{{ .CDROMType }}1:{{ .CDROMType_PrimarySecondary }}.present = "TRUE"
{{ .CDROMType }}1:{{ .CDROMType_PrimarySecondary }}.fileName = "{{ .CDROM_PATH }}"
{{ .CDROMType }}1:{{ .CDROMType_PrimarySecondary }}.deviceType = "cdrom-image"
`

View File

@ -87,6 +87,10 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
Directories: b.config.FloppyConfig.FloppyDirectories,
Label: b.config.FloppyConfig.FloppyLabel,
},
&common.StepCreateCD{
Files: b.config.CDConfig.CDFiles,
Label: b.config.CDConfig.CDLabel,
},
&vmwcommon.StepRemoteUpload{
Key: "floppy_path",
Message: "Uploading Floppy to remote machine...",
@ -109,9 +113,11 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
Linked: b.config.Linked,
},
&vmwcommon.StepConfigureVMX{
CustomData: b.config.VMXData,
VMName: b.config.VMName,
DisplayName: b.config.VMXDisplayName,
CustomData: b.config.VMXData,
VMName: b.config.VMName,
DisplayName: b.config.VMXDisplayName,
DiskAdapterType: b.config.DiskAdapterType,
CDROMAdapterType: "",
},
&vmwcommon.StepSuppressMessages{},
&vmwcommon.StepHTTPIPDiscover{},

View File

@ -21,6 +21,7 @@ type Config struct {
common.HTTPConfig `mapstructure:",squash"`
common.FloppyConfig `mapstructure:",squash"`
vmwcommon.BootConfigWrapper `mapstructure:",squash"`
common.CDConfig `mapstructure:",squash"`
vmwcommon.DriverConfig `mapstructure:",squash"`
vmwcommon.OutputConfig `mapstructure:",squash"`
vmwcommon.RunConfig `mapstructure:",squash"`
@ -91,6 +92,7 @@ func (c *Config) Prepare(raws ...interface{}) ([]string, error) {
errs = packer.MultiErrorAppend(errs, c.SSHConfig.Prepare(&c.ctx)...)
errs = packer.MultiErrorAppend(errs, c.ToolsConfig.Prepare(&c.ctx)...)
errs = packer.MultiErrorAppend(errs, c.FloppyConfig.Prepare(&c.ctx)...)
errs = packer.MultiErrorAppend(errs, c.CDConfig.Prepare(&c.ctx)...)
errs = packer.MultiErrorAppend(errs, c.VNCConfig.Prepare(&c.ctx)...)
errs = packer.MultiErrorAppend(errs, c.ExportConfig.Prepare(&c.ctx)...)
errs = packer.MultiErrorAppend(errs, c.DiskConfig.Prepare(&c.ctx)...)

View File

@ -30,6 +30,8 @@ type FlatConfig struct {
DisableVNC *bool `mapstructure:"disable_vnc" cty:"disable_vnc" hcl:"disable_vnc"`
BootKeyInterval *string `mapstructure:"boot_key_interval" cty:"boot_key_interval" hcl:"boot_key_interval"`
USBKeyBoard *bool `mapstructure:"usb_keyboard" cty:"usb_keyboard" hcl:"usb_keyboard"`
CDFiles []string `mapstructure:"cd_files" cty:"cd_files" hcl:"cd_files"`
CDLabel *string `mapstructure:"cd_label" cty:"cd_label" hcl:"cd_label"`
CleanUpRemoteCache *bool `mapstructure:"cleanup_remote_cache" required:"false" cty:"cleanup_remote_cache" hcl:"cleanup_remote_cache"`
FusionAppPath *string `mapstructure:"fusion_app_path" required:"false" cty:"fusion_app_path" hcl:"fusion_app_path"`
RemoteType *string `mapstructure:"remote_type" required:"false" cty:"remote_type" hcl:"remote_type"`
@ -152,6 +154,8 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
"disable_vnc": &hcldec.AttrSpec{Name: "disable_vnc", Type: cty.Bool, Required: false},
"boot_key_interval": &hcldec.AttrSpec{Name: "boot_key_interval", Type: cty.String, Required: false},
"usb_keyboard": &hcldec.AttrSpec{Name: "usb_keyboard", Type: cty.Bool, Required: false},
"cd_files": &hcldec.AttrSpec{Name: "cd_files", Type: cty.List(cty.String), Required: false},
"cd_label": &hcldec.AttrSpec{Name: "cd_label", Type: cty.String, Required: false},
"cleanup_remote_cache": &hcldec.AttrSpec{Name: "cleanup_remote_cache", Type: cty.Bool, Required: false},
"fusion_app_path": &hcldec.AttrSpec{Name: "fusion_app_path", Type: cty.String, Required: false},
"remote_type": &hcldec.AttrSpec{Name: "remote_type", Type: cty.String, Required: false},

View File

@ -144,6 +144,7 @@ var supportedCDISOCreationCommands []cdISOCreationCommand = []cdISOCreationComma
"hdiutil", func(path string, label string, source string, dest string) *exec.Cmd {
return exec.Command(
path,
"makehybrid",
"-o", dest,
"-hfs",
"-joliet",

View File

@ -119,6 +119,14 @@ builder.
@include 'helper/communicator/WinRM-not-required.mdx'
### CD configuration
@include 'common/CDConfig.mdx'
#### Optional:
@include 'common/CDConfig-not-required.mdx'
## Boot Command
The `boot_command` configuration is very important: it specifies the keys to
@ -164,7 +172,7 @@ for the version of Hyper-V that is running.
Floppy drives are no longer supported by generation 2 machines. This requires
you to take another approach when dealing with preseed or answer files. Two
possible options are using virtual DVD drives or using Packers built in web
possible options are using the `cd_files` option or using Packer's built in web
server.
When dealing with Windows you need to enable UEFI drives for generation 2

View File

@ -12,7 +12,7 @@ sidebar_title: QEMU
Type: `qemu`
The Qemu Packer builder is able to create [KVM](http://www.linux-kvm.org) virtual
The Qemu Packer builder is able to create [KVM](http://www.linux-kvm.org) virtual
machine images.
The builder builds a virtual machine by creating a new virtual machine from
@ -144,6 +144,14 @@ necessary for this build to succeed and can be found further down the page.
@include 'common/FloppyConfig-not-required.mdx'
### CD configuration
@include 'common/CDConfig.mdx'
#### Optional:
@include 'common/CDConfig-not-required.mdx'
## Shutdown configuration
### Optional:

View File

@ -119,6 +119,14 @@ necessary for this build to succeed and can be found further down the page.
@include 'common/FloppyConfig-not-required.mdx'
### CD configuration
@include 'common/CDConfig.mdx'
#### Optional:
@include 'common/CDConfig-not-required.mdx'
### Export configuration
#### Optional: