Add additional disk support for QEMU builder.
This commit is contained in:
parent
757bd4bed9
commit
c9b693080a
|
@ -99,6 +99,7 @@ type Config struct {
|
|||
ISOSkipCache bool `mapstructure:"iso_skip_cache"`
|
||||
Accelerator string `mapstructure:"accelerator"`
|
||||
CpuCount int `mapstructure:"cpus"`
|
||||
AdditionalDiskSize []string `mapstructure:"disk_additional_size"`
|
||||
DiskInterface string `mapstructure:"disk_interface"`
|
||||
DiskSize uint `mapstructure:"disk_size"`
|
||||
DiskCache string `mapstructure:"disk_cache"`
|
||||
|
@ -286,6 +287,11 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) {
|
|||
errs, errors.New("use_backing_file can only be enabled for QCOW2 images and when disk_image is true"))
|
||||
}
|
||||
|
||||
if b.config.DiskImage && len(b.config.AdditionalDiskSize) > 0 {
|
||||
errs = packer.MultiErrorAppend(
|
||||
errs, errors.New("disk_additional_size can only be used when disk_image is false"))
|
||||
}
|
||||
|
||||
if _, ok := accels[b.config.Accelerator]; !ok {
|
||||
errs = packer.MultiErrorAppend(
|
||||
errs, errors.New("invalid accelerator, only 'kvm', 'tcg', 'xen', 'hax', 'hvf', 'whpx', or 'none' are allowed"))
|
||||
|
@ -500,7 +506,11 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
|
|||
state: make(map[string]interface{}),
|
||||
}
|
||||
|
||||
artifact.state["diskName"] = state.Get("disk_filename").(string)
|
||||
artifact.state["diskName"] = b.config.VMName
|
||||
diskpaths, ok := state.Get("qemu_disk_paths").([]string)
|
||||
if ok {
|
||||
artifact.state["diskPaths"] = diskpaths
|
||||
}
|
||||
artifact.state["diskType"] = b.config.Format
|
||||
artifact.state["diskSize"] = uint64(b.config.DiskSize)
|
||||
artifact.state["domainType"] = b.config.Accelerator
|
||||
|
|
|
@ -22,7 +22,7 @@ type stepConvertDisk struct{}
|
|||
func (s *stepConvertDisk) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
|
||||
config := state.Get("config").(*Config)
|
||||
driver := state.Get("driver").(Driver)
|
||||
diskName := state.Get("disk_filename").(string)
|
||||
diskName := config.VMName
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
|
||||
if config.SkipCompaction && !config.DiskCompression {
|
||||
|
|
|
@ -19,7 +19,6 @@ func (s *stepCopyDisk) Run(ctx context.Context, state multistep.StateBag) multis
|
|||
isoPath := state.Get("iso_path").(string)
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
path := filepath.Join(config.OutputDir, fmt.Sprintf("%s", config.VMName))
|
||||
name := config.VMName
|
||||
|
||||
command := []string{
|
||||
"convert",
|
||||
|
@ -40,8 +39,6 @@ func (s *stepCopyDisk) Run(ctx context.Context, state multistep.StateBag) multis
|
|||
return multistep.ActionHalt
|
||||
}
|
||||
|
||||
state.Put("disk_filename", name)
|
||||
|
||||
return multistep.ActionContinue
|
||||
}
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@ package qemu
|
|||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/hashicorp/packer/helper/multistep"
|
||||
|
@ -18,36 +19,54 @@ func (s *stepCreateDisk) Run(ctx context.Context, state multistep.StateBag) mult
|
|||
driver := state.Get("driver").(Driver)
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
name := config.VMName
|
||||
path := filepath.Join(config.OutputDir, name)
|
||||
|
||||
command := []string{
|
||||
"create",
|
||||
"-f", config.Format,
|
||||
}
|
||||
|
||||
if config.UseBackingFile {
|
||||
isoPath := state.Get("iso_path").(string)
|
||||
command = append(command, "-b", isoPath)
|
||||
}
|
||||
|
||||
command = append(command,
|
||||
path,
|
||||
fmt.Sprintf("%vM", config.DiskSize),
|
||||
)
|
||||
|
||||
if config.DiskImage && !config.UseBackingFile {
|
||||
return multistep.ActionContinue
|
||||
}
|
||||
|
||||
ui.Say("Creating hard drive...")
|
||||
if err := driver.QemuImg(command...); err != nil {
|
||||
err := fmt.Errorf("Error creating hard drive: %s", err)
|
||||
state.Put("error", err)
|
||||
ui.Error(err.Error())
|
||||
return multistep.ActionHalt
|
||||
var diskFullPaths, diskSizes []string
|
||||
|
||||
ui.Say("Creating required virtual machine disks")
|
||||
// The 'main' or 'default' disk
|
||||
diskFullPaths = append(diskFullPaths, filepath.Join(config.OutputDir, name))
|
||||
diskSizes = append(diskSizes, fmt.Sprintf("%dM", uint64(config.DiskSize)))
|
||||
// Additional disks
|
||||
if len(config.AdditionalDiskSize) > 0 {
|
||||
for i, diskSize := range config.AdditionalDiskSize {
|
||||
path := filepath.Join(config.OutputDir, fmt.Sprintf("%s-%d", name, i+1))
|
||||
diskFullPaths = append(diskFullPaths, path)
|
||||
size := fmt.Sprintf("%s", diskSize)
|
||||
diskSizes = append(diskSizes, size)
|
||||
}
|
||||
}
|
||||
|
||||
state.Put("disk_filename", name)
|
||||
// Create all required disks
|
||||
for i, diskFullPath := range diskFullPaths {
|
||||
log.Printf("[INFO] Creating disk with Path: %s and Size: %s", diskFullPath, diskSizes[i])
|
||||
command := []string{
|
||||
"create",
|
||||
"-f", config.Format,
|
||||
}
|
||||
|
||||
if config.UseBackingFile && i == 0 {
|
||||
isoPath := state.Get("iso_path").(string)
|
||||
command = append(command, "-b", isoPath)
|
||||
}
|
||||
|
||||
command = append(command,
|
||||
diskFullPath,
|
||||
diskSizes[i])
|
||||
|
||||
if err := driver.QemuImg(command...); err != nil {
|
||||
err := fmt.Errorf("Error creating hard drive: %s", err)
|
||||
state.Put("error", err)
|
||||
ui.Error(err.Error())
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
}
|
||||
|
||||
// Stash the disk paths so we can retrieve later
|
||||
state.Put("qemu_disk_paths", diskFullPaths)
|
||||
|
||||
return multistep.ActionContinue
|
||||
}
|
||||
|
|
|
@ -94,19 +94,42 @@ func getCommandArgs(bootDrive string, state multistep.StateBag) ([]string, error
|
|||
|
||||
if qemuVersion.GreaterThanOrEqual(v2) {
|
||||
if config.DiskInterface == "virtio-scsi" {
|
||||
deviceArgs = append(deviceArgs, "virtio-scsi-pci,id=scsi0", "scsi-hd,bus=scsi0.0,drive=drive0")
|
||||
driveArgumentString := fmt.Sprintf("if=none,file=%s,id=drive0,cache=%s,discard=%s,format=%s", imgPath, config.DiskCache, config.DiskDiscard, config.Format)
|
||||
if config.DetectZeroes != "off" {
|
||||
driveArgumentString = fmt.Sprintf("%s,detect-zeroes=%s", driveArgumentString, config.DetectZeroes)
|
||||
if config.DiskImage {
|
||||
deviceArgs = append(deviceArgs, "virtio-scsi-pci,id=scsi0", "scsi-hd,bus=scsi0.0,drive=drive0")
|
||||
driveArgumentString := fmt.Sprintf("if=none,file=%s,id=drive0,cache=%s,discard=%s,format=%s", imgPath, config.DiskCache, config.DiskDiscard, config.Format)
|
||||
if config.DetectZeroes != "off" {
|
||||
driveArgumentString = fmt.Sprintf("%s,detect-zeroes=%s", driveArgumentString, config.DetectZeroes)
|
||||
}
|
||||
driveArgs = append(driveArgs, driveArgumentString)
|
||||
} else {
|
||||
deviceArgs = append(deviceArgs, "virtio-scsi-pci,id=scsi0")
|
||||
diskFullPaths := state.Get("qemu_disk_paths").([]string)
|
||||
for i, diskFullPath := range diskFullPaths {
|
||||
deviceArgs = append(deviceArgs, fmt.Sprintf("scsi-hd,bus=scsi0.0,drive=drive%d", i))
|
||||
driveArgumentString := fmt.Sprintf("if=none,file=%s,id=drive%d,cache=%s,discard=%s,format=%s", diskFullPath, i, config.DiskCache, config.DiskDiscard, config.Format)
|
||||
if config.DetectZeroes != "off" {
|
||||
driveArgumentString = fmt.Sprintf("%s,detect-zeroes=%s", driveArgumentString, config.DetectZeroes)
|
||||
}
|
||||
driveArgs = append(driveArgs, driveArgumentString)
|
||||
}
|
||||
}
|
||||
driveArgs = append(driveArgs, driveArgumentString)
|
||||
} else {
|
||||
driveArgumentString := fmt.Sprintf("file=%s,if=%s,cache=%s,discard=%s,format=%s", imgPath, config.DiskInterface, config.DiskCache, config.DiskDiscard, config.Format)
|
||||
if config.DetectZeroes != "off" {
|
||||
driveArgumentString = fmt.Sprintf("%s,detect-zeroes=%s", driveArgumentString, config.DetectZeroes)
|
||||
if config.DiskImage {
|
||||
driveArgumentString := fmt.Sprintf("file=%s,if=%s,cache=%s,discard=%s,format=%s", imgPath, config.DiskInterface, config.DiskCache, config.DiskDiscard, config.Format)
|
||||
if config.DetectZeroes != "off" {
|
||||
driveArgumentString = fmt.Sprintf("%s,detect-zeroes=%s", driveArgumentString, config.DetectZeroes)
|
||||
}
|
||||
driveArgs = append(driveArgs, driveArgumentString)
|
||||
} else {
|
||||
diskFullPaths := state.Get("qemu_disk_paths").([]string)
|
||||
for _, diskFullPath := range diskFullPaths {
|
||||
driveArgumentString := fmt.Sprintf("file=%s,if=%s,cache=%s,discard=%s,format=%s", diskFullPath, config.DiskInterface, config.DiskCache, config.DiskDiscard, config.Format)
|
||||
if config.DetectZeroes != "off" {
|
||||
driveArgumentString = fmt.Sprintf("%s,detect-zeroes=%s", driveArgumentString, config.DetectZeroes)
|
||||
}
|
||||
driveArgs = append(driveArgs, driveArgumentString)
|
||||
}
|
||||
}
|
||||
driveArgs = append(driveArgs, driveArgumentString)
|
||||
|
||||
}
|
||||
} else {
|
||||
driveArgs = append(driveArgs, fmt.Sprintf("file=%s,if=%s,cache=%s,format=%s", imgPath, config.DiskInterface, config.DiskCache, config.Format))
|
||||
|
|
|
@ -142,6 +142,16 @@ Linux server and have not enabled X11 forwarding (`ssh -X`).
|
|||
- `cpus` (number) - The number of cpus to use when building the VM.
|
||||
The default is `1` CPU.
|
||||
|
||||
- `disk_additional_size` (array of strings) - Additional disks to create.
|
||||
Uses `vm_name` as the disk name template and appends `-#` where `#` is
|
||||
the position in the array. `#` starts at 1 since 0 is the default disk.
|
||||
Each string represents the disk image size in bytes. Optional suffixes
|
||||
'k' or 'K' (kilobyte, 1024), 'M' (megabyte, 1024k), 'G' (gigabyte, 1024M),
|
||||
'T' (terabyte, 1024G), 'P' (petabyte, 1024T) and 'E' (exabyte, 1024P) are
|
||||
supported. 'b' is ignored. Per qemu-img documentation.
|
||||
Each additional disk uses the same disk parameters as the default disk.
|
||||
Unset by default.
|
||||
|
||||
- `disk_cache` (string) - The cache mode to use for disk. Allowed values
|
||||
include any of `writethrough`, `writeback`, `none`, `unsafe`
|
||||
or `directsync`. By default, this is set to `writeback`.
|
||||
|
|
Loading…
Reference in New Issue