From 8e1cc16ab5c8a0d3c926dc8b7feaf73e4b6769b8 Mon Sep 17 00:00:00 2001 From: Vasiliy Tolstov Date: Thu, 29 Oct 2015 10:54:25 +0000 Subject: [PATCH] add convert step for qcow2 image format https://ext4.wiki.kernel.org/index.php/Ext4_VM_Images does not recommends to dd zero file and deletes it, but in case of enabling discards and qcow2 image we can recreate qcow2 file with less used space. Also qemu-img able to enable compression for qcow2 files, that sometimes may be useful because it natively supported by qemu. Signed-off-by: Vasiliy Tolstov --- builder/qemu/builder.go | 8 +++ builder/qemu/step_convert_disk.go | 67 +++++++++++++++++++ .../source/docs/builders/qemu.html.markdown | 6 ++ 3 files changed, 81 insertions(+) create mode 100644 builder/qemu/step_convert_disk.go diff --git a/builder/qemu/builder.go b/builder/qemu/builder.go index eb38ba0c7..2e7e107d7 100644 --- a/builder/qemu/builder.go +++ b/builder/qemu/builder.go @@ -88,6 +88,8 @@ type Config struct { DiskSize uint `mapstructure:"disk_size"` DiskCache string `mapstructure:"disk_cache"` DiskDiscard string `mapstructure:"disk_discard"` + SkipCompaction bool `mapstructure:"skip_compaction"` + DiskCompression bool `mapstructure:"disk_compression"` FloppyFiles []string `mapstructure:"floppy_files"` Format string `mapstructure:"format"` Headless bool `mapstructure:"headless"` @@ -242,6 +244,11 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { errs, errors.New("invalid format, only 'qcow2' or 'raw' are allowed")) } + if b.config.Format != "qcow2" { + b.config.SkipCompaction = true + b.config.DiskCompression = false + } + if _, ok := accels[b.config.Accelerator]; !ok { errs = packer.MultiErrorAppend( errs, errors.New("invalid accelerator, only 'kvm', 'tcg', 'xen', or 'none' are allowed")) @@ -364,6 +371,7 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe }, new(common.StepProvision), new(stepShutdown), + new(stepConvertDisk), } // Setup the state bag diff --git a/builder/qemu/step_convert_disk.go b/builder/qemu/step_convert_disk.go new file mode 100644 index 000000000..dcf5e97de --- /dev/null +++ b/builder/qemu/step_convert_disk.go @@ -0,0 +1,67 @@ +package qemu + +import ( + "fmt" + "path/filepath" + + "github.com/mitchellh/multistep" + "github.com/mitchellh/packer/packer" + + "os" +) + +// This step converts the virtual disk that was used as the +// hard drive for the virtual machine. +type stepConvertDisk struct{} + +func (s *stepConvertDisk) Run(state multistep.StateBag) multistep.StepAction { + config := state.Get("config").(*Config) + driver := state.Get("driver").(Driver) + diskName := state.Get("disk_filename").(string) + ui := state.Get("ui").(packer.Ui) + + if config.SkipCompaction && !config.DiskCompression { + return multistep.ActionContinue + } + + name := diskName + ".convert" + + sourcePath := filepath.Join(config.OutputDir, diskName) + targetPath := filepath.Join(config.OutputDir, name) + + command := []string{ + "convert", + "-q", + } + + if config.DiskCompression { + command = append(command, "-c") + } + + command = append(command, []string{ + "-f", config.Format, + "-O", config.Format, + sourcePath, + targetPath, + }..., + ) + + ui.Say("Converting hard drive...") + if err := driver.QemuImg(command...); err != nil { + err := fmt.Errorf("Error converting hard drive: %s", err) + state.Put("error", err) + ui.Error(err.Error()) + return multistep.ActionHalt + } + + if err := os.Rename(targetPath, sourcePath); err != nil { + err := fmt.Errorf("Error moving converted hard drive: %s", err) + state.Put("error", err) + ui.Error(err.Error()) + return multistep.ActionHalt + } + + return multistep.ActionContinue +} + +func (s *stepConvertDisk) Cleanup(state multistep.StateBag) {} diff --git a/website/source/docs/builders/qemu.html.markdown b/website/source/docs/builders/qemu.html.markdown index 13ad4bda2..5cfc767d3 100644 --- a/website/source/docs/builders/qemu.html.markdown +++ b/website/source/docs/builders/qemu.html.markdown @@ -136,6 +136,12 @@ builder. - `disk_size` (integer) - The size, in megabytes, of the hard disk to create for the VM. By default, this is 40000 (about 40 GB). +- `skip_compaction` (boolean) - Packer compacts the QCOW2 image using `qemu-img convert`. + Set this option to `true` to disable compacting. Defaults to `false`. + +- `disk_compression` (boolean) - Apply compression to the QCOW2 disk file + using `qemu-img convert`. Defaults to `false`. + - `floppy_files` (array of strings) - A list of files to place onto a floppy disk that is attached when the VM is booted. This is most useful for unattended Windows installs, which look for an `Autounattend.xml` file on