[builder/qemu] Skip resize step when skip_resize_disk is enable #9860 (#9896)

* [builder/qemu] Skip resize step when skip_resize_disk is enable #9860

* Update builder/qemu/builder_test.go

Improve the code quality

Co-authored-by: Wilken Rivera <dev@wilkenrivera.com>

* Update files for unit tests

Co-authored-by: Wilken Rivera <dev@wilkenrivera.com>
This commit is contained in:
Richard Turc 2020-09-08 20:32:08 +02:00 committed by GitHub
parent 2da89db272
commit b4ff0ea4bc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 197 additions and 1 deletions

View File

@ -130,6 +130,10 @@ type Config struct {
// for disk_size, Packer uses a default of `40960M` (40 GB). If a disk_size
// number is provided with no units, Packer will default to Megabytes.
DiskSize string `mapstructure:"disk_size" required:"false"`
// Packer resizes the QCOW2 image using
// qemu-img resize. Set this option to true to disable resizing.
// Defaults to false.
SkipResizeDisk bool `mapstructure:"skip_resize_disk" required:"false"`
// 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`.
@ -509,6 +513,11 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, []string, error) {
errs, errors.New("disk_additional_size can only be used when disk_image is false"))
}
if b.config.SkipResizeDisk && !(b.config.DiskImage) {
errs = packer.MultiErrorAppend(
errs, errors.New("skip_resize_disk can only be used when disk_image is true"))
}
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"))

View File

@ -93,6 +93,7 @@ type FlatConfig struct {
CpuCount *int `mapstructure:"cpus" required:"false" cty:"cpus" hcl:"cpus"`
DiskInterface *string `mapstructure:"disk_interface" required:"false" cty:"disk_interface" hcl:"disk_interface"`
DiskSize *string `mapstructure:"disk_size" required:"false" cty:"disk_size" hcl:"disk_size"`
SkipResizeDisk *bool `mapstructure:"skip_resize_disk" required:"false" cty:"skip_resize_disk" hcl:"skip_resize_disk"`
DiskCache *string `mapstructure:"disk_cache" required:"false" cty:"disk_cache" hcl:"disk_cache"`
DiskDiscard *string `mapstructure:"disk_discard" required:"false" cty:"disk_discard" hcl:"disk_discard"`
DetectZeroes *string `mapstructure:"disk_detect_zeroes" required:"false" cty:"disk_detect_zeroes" hcl:"disk_detect_zeroes"`
@ -218,6 +219,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
"cpus": &hcldec.AttrSpec{Name: "cpus", Type: cty.Number, Required: false},
"disk_interface": &hcldec.AttrSpec{Name: "disk_interface", Type: cty.String, Required: false},
"disk_size": &hcldec.AttrSpec{Name: "disk_size", Type: cty.String, Required: false},
"skip_resize_disk": &hcldec.AttrSpec{Name: "skip_resize_disk", Type: cty.Bool, Required: false},
"disk_cache": &hcldec.AttrSpec{Name: "disk_cache", Type: cty.String, Required: false},
"disk_discard": &hcldec.AttrSpec{Name: "disk_discard", Type: cty.String, Required: false},
"disk_detect_zeroes": &hcldec.AttrSpec{Name: "disk_detect_zeroes", Type: cty.String, Required: false},

View File

@ -302,6 +302,21 @@ func TestBuilderPrepare_UseBackingFile(t *testing.T) {
}
}
func TestBuilderPrepare_SkipResizeDisk(t *testing.T) {
config := testConfig()
config["skip_resize_disk"] = true
config["disk_image"] = false
b := Builder{}
_, warns, err := b.Prepare(config)
if len(warns) > 0 {
t.Errorf("unexpected warns when calling prepare with skip_resize_disk set to true: %#v", warns)
}
if err == nil {
t.Errorf("setting skip_resize_disk to true when disk_image is false should have error")
}
}
func TestBuilderPrepare_FloppyFiles(t *testing.T) {
var b Builder
config := testConfig()

View File

@ -0,0 +1,64 @@
package qemu
import "sync"
type DriverMock struct {
sync.Mutex
StopCalled bool
StopErr error
QemuCalls [][]string
QemuErrs []error
WaitForShutdownCalled bool
WaitForShutdownState bool
QemuImgCalls [][]string
QemuImgErrs []error
VerifyCalled bool
VerifyErr error
VersionCalled bool
VersionResult string
VersionErr error
}
func (d *DriverMock) Stop() error {
d.StopCalled = true
return d.StopErr
}
func (d *DriverMock) Qemu(args ...string) error {
d.QemuCalls = append(d.QemuCalls, args)
if len(d.QemuErrs) >= len(d.QemuCalls) {
return d.QemuErrs[len(d.QemuCalls)-1]
}
return nil
}
func (d *DriverMock) WaitForShutdown(cancelCh <-chan struct{}) bool {
d.WaitForShutdownCalled = true
return d.WaitForShutdownState
}
func (d *DriverMock) QemuImg(args ...string) error {
d.QemuImgCalls = append(d.QemuImgCalls, args)
if len(d.QemuImgErrs) >= len(d.QemuImgCalls) {
return d.QemuImgErrs[len(d.QemuImgCalls)-1]
}
return nil
}
func (d *DriverMock) Verify() error {
d.VerifyCalled = true
return d.VerifyErr
}
func (d *DriverMock) Version() (string, error) {
d.VersionCalled = true
return d.VersionResult, d.VersionErr
}

View File

@ -25,7 +25,8 @@ func (s *stepResizeDisk) Run(ctx context.Context, state multistep.StateBag) mult
path,
config.DiskSize,
}
if config.DiskImage == false {
if config.DiskImage == false || config.SkipResizeDisk == true {
return multistep.ActionContinue
}

View File

@ -0,0 +1,82 @@
package qemu
import (
"context"
"testing"
"github.com/hashicorp/packer/helper/multistep"
)
func TestStepResizeDisk_Run(t *testing.T) {
state := testState(t)
driver := state.Get("driver").(*DriverMock)
config := &Config{
DiskImage: true,
SkipResizeDisk: false,
DiskSize: "4096M",
Format: "qcow2",
OutputDir: "/test/",
VMName: "test",
}
state.Put("config", config)
step := new(stepResizeDisk)
// Test the run
if action := step.Run(context.Background(), state); action != multistep.ActionContinue {
t.Fatalf("bad action: %#v", action)
}
if _, ok := state.GetOk("error"); ok {
t.Fatal("should NOT have error")
}
if len(driver.QemuImgCalls) == 0 {
t.Fatal("should qemu-img called")
}
if len(driver.QemuImgCalls[0]) != 5 {
t.Fatal("should 5 qemu-img parameters")
}
}
func TestStepResizeDisk_SkipIso(t *testing.T) {
state := testState(t)
driver := state.Get("driver").(*DriverMock)
config := &Config{
DiskImage: false,
SkipResizeDisk: false,
}
state.Put("config", config)
step := new(stepResizeDisk)
// Test the run
if action := step.Run(context.Background(), state); action != multistep.ActionContinue {
t.Fatalf("bad action: %#v", action)
}
if _, ok := state.GetOk("error"); ok {
t.Fatal("should NOT have error")
}
if len(driver.QemuImgCalls) > 0 {
t.Fatal("should NOT qemu-img called")
}
}
func TestStepResizeDisk_SkipOption(t *testing.T) {
state := testState(t)
driver := state.Get("driver").(*DriverMock)
config := &Config{
DiskImage: false,
SkipResizeDisk: true,
}
state.Put("config", config)
step := new(stepResizeDisk)
// Test the run
if action := step.Run(context.Background(), state); action != multistep.ActionContinue {
t.Fatalf("bad action: %#v", action)
}
if _, ok := state.GetOk("error"); ok {
t.Fatal("should NOT have error")
}
if len(driver.QemuImgCalls) > 0 {
t.Fatal("should NOT qemu-img called")
}
}

19
builder/qemu/step_test.go Normal file
View File

@ -0,0 +1,19 @@
package qemu
import (
"bytes"
"testing"
"github.com/hashicorp/packer/helper/multistep"
"github.com/hashicorp/packer/packer"
)
func testState(t *testing.T) multistep.StateBag {
state := new(multistep.BasicStateBag)
state.Put("driver", new(DriverMock))
state.Put("ui", &packer.BasicUi{
Reader: new(bytes.Buffer),
Writer: new(bytes.Buffer),
})
return state
}

View File

@ -53,6 +53,10 @@
for disk_size, Packer uses a default of `40960M` (40 GB). If a disk_size
number is provided with no units, Packer will default to Megabytes.
- `skip_resize_disk` (bool) - Packer resizes the QCOW2 image using
qemu-img resize. Set this option to true to disable resizing.
Defaults to false.
- `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`.