diff --git a/builder/openstack/builder.go b/builder/openstack/builder.go index b69181daf..3007d0461 100644 --- a/builder/openstack/builder.go +++ b/builder/openstack/builder.go @@ -153,6 +153,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack &stepUpdateImageTags{}, &stepUpdateImageVisibility{}, &stepAddImageMembers{}, + &stepUpdateImageMinDisk{}, } // Run! diff --git a/builder/openstack/image_config.go b/builder/openstack/image_config.go index ffc9c6896..dd61bae36 100644 --- a/builder/openstack/image_config.go +++ b/builder/openstack/image_config.go @@ -16,6 +16,7 @@ type ImageConfig struct { ImageMembers []string `mapstructure:"image_members"` ImageDiskFormat string `mapstructure:"image_disk_format"` ImageTags []string `mapstructure:"image_tags"` + ImageMinDisk int `mapstructure:"image_min_disk"` } func (c *ImageConfig) Prepare(ctx *interpolate.Context) []error { @@ -52,6 +53,10 @@ func (c *ImageConfig) Prepare(ctx *interpolate.Context) []error { } } + if c.ImageMinDisk < 0 { + errs = append(errs, fmt.Errorf("An image min disk size must be greater than or equal to 0")) + } + if len(errs) > 0 { return errs } diff --git a/builder/openstack/step_update_image_mindisk.go b/builder/openstack/step_update_image_mindisk.go new file mode 100644 index 000000000..4279aac6f --- /dev/null +++ b/builder/openstack/step_update_image_mindisk.go @@ -0,0 +1,52 @@ +package openstack + +import ( + "context" + "fmt" + + "github.com/gophercloud/gophercloud/openstack/imageservice/v2/images" + "github.com/hashicorp/packer/helper/multistep" + "github.com/hashicorp/packer/packer" +) + +type stepUpdateImageMinDisk struct{} + +func (s *stepUpdateImageMinDisk) Run(_ context.Context, state multistep.StateBag) multistep.StepAction { + imageId := state.Get("image").(string) + ui := state.Get("ui").(packer.Ui) + config := state.Get("config").(*Config) + + if config.ImageMinDisk == 0 { + return multistep.ActionContinue + } + imageClient, err := config.imageV2Client() + if err != nil { + err := fmt.Errorf("Error initializing image service client: %s", err) + state.Put("error", err) + return multistep.ActionHalt + } + + ui.Say(fmt.Sprintf("Updatind image min disk to %d", config.ImageMinDisk)) + + r := images.Update( + imageClient, + imageId, + images.UpdateOpts{ + images.ReplaceImageMinDisk{ + NewMinDisk: config.ImageMinDisk, + }, + }, + ) + + if _, err := r.Extract(); err != nil { + err = fmt.Errorf("Error updating image min disk: %s", err) + state.Put("error", err) + return multistep.ActionHalt + } + + return multistep.ActionContinue +} + +func (s *stepUpdateImageMinDisk) Cleanup(multistep.StateBag) { + // No cleanup... +} diff --git a/website/source/docs/builders/openstack.html.md b/website/source/docs/builders/openstack.html.md index a11780db0..e341f63e4 100644 --- a/website/source/docs/builders/openstack.html.md +++ b/website/source/docs/builders/openstack.html.md @@ -144,6 +144,8 @@ builder. after creation. An image member is usually a project (also called the "tenant") with whom the image is shared. +- `image_min_disk` (int) - Minimum disk of needed to boot image size in GB. + - `image_tags` (array of strings) - List of tags to add to the image after creation.