Added VirtualBox ISO builder option to create additional disks (#10674)
This commit is contained in:
parent
9944031580
commit
1a5678dd86
|
@ -8,6 +8,8 @@ import (
|
||||||
|
|
||||||
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
||||||
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
|
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
|
||||||
|
|
||||||
|
"strconv"
|
||||||
)
|
)
|
||||||
|
|
||||||
// This step attaches the boot ISO, cd_files iso, and guest additions to the
|
// This step attaches the boot ISO, cd_files iso, and guest additions to the
|
||||||
|
@ -69,49 +71,50 @@ func (s *StepAttachISOs) Run(ctx context.Context, state multistep.StateBag) mult
|
||||||
|
|
||||||
// We have three different potential isos we can attach, so let's
|
// We have three different potential isos we can attach, so let's
|
||||||
// assign each one its own spot so they don't conflict.
|
// assign each one its own spot so they don't conflict.
|
||||||
var controllerName, device, port string
|
var controllerName string
|
||||||
|
var device, port int
|
||||||
switch diskCategory {
|
switch diskCategory {
|
||||||
case "boot_iso":
|
case "boot_iso":
|
||||||
// figure out controller path
|
// figure out controller path
|
||||||
controllerName = "IDE Controller"
|
controllerName = "IDE Controller"
|
||||||
port = "0"
|
port = 0
|
||||||
device = "1"
|
device = 1
|
||||||
if s.ISOInterface == "sata" {
|
if s.ISOInterface == "sata" {
|
||||||
controllerName = "SATA Controller"
|
controllerName = "SATA Controller"
|
||||||
port = "1"
|
port = 15
|
||||||
device = "0"
|
device = 0
|
||||||
} else if s.ISOInterface == "virtio" {
|
} else if s.ISOInterface == "virtio" {
|
||||||
controllerName = "VirtIO Controller"
|
controllerName = "VirtIO Controller"
|
||||||
port = "1"
|
port = 15
|
||||||
device = "0"
|
device = 0
|
||||||
}
|
}
|
||||||
ui.Message("Mounting boot ISO...")
|
ui.Message("Mounting boot ISO...")
|
||||||
case "guest_additions":
|
case "guest_additions":
|
||||||
controllerName = "IDE Controller"
|
controllerName = "IDE Controller"
|
||||||
port = "1"
|
port = 1
|
||||||
device = "0"
|
device = 0
|
||||||
if s.GuestAdditionsInterface == "sata" {
|
if s.GuestAdditionsInterface == "sata" {
|
||||||
controllerName = "SATA Controller"
|
controllerName = "SATA Controller"
|
||||||
port = "2"
|
port = 14
|
||||||
device = "0"
|
device = 0
|
||||||
} else if s.GuestAdditionsInterface == "virtio" {
|
} else if s.GuestAdditionsInterface == "virtio" {
|
||||||
controllerName = "VirtIO Controller"
|
controllerName = "VirtIO Controller"
|
||||||
port = "2"
|
port = 14
|
||||||
device = "0"
|
device = 0
|
||||||
}
|
}
|
||||||
ui.Message("Mounting guest additions ISO...")
|
ui.Message("Mounting guest additions ISO...")
|
||||||
case "cd_files":
|
case "cd_files":
|
||||||
controllerName = "IDE Controller"
|
controllerName = "IDE Controller"
|
||||||
port = "1"
|
port = 1
|
||||||
device = "1"
|
device = 1
|
||||||
if s.ISOInterface == "sata" {
|
if s.ISOInterface == "sata" {
|
||||||
controllerName = "SATA Controller"
|
controllerName = "SATA Controller"
|
||||||
port = "3"
|
port = 13
|
||||||
device = "0"
|
device = 0
|
||||||
} else if s.ISOInterface == "virtio" {
|
} else if s.ISOInterface == "virtio" {
|
||||||
controllerName = "VirtIO Controller"
|
controllerName = "VirtIO Controller"
|
||||||
port = "3"
|
port = 13
|
||||||
device = "0"
|
device = 0
|
||||||
}
|
}
|
||||||
ui.Message("Mounting cd_files ISO...")
|
ui.Message("Mounting cd_files ISO...")
|
||||||
}
|
}
|
||||||
|
@ -120,8 +123,8 @@ func (s *StepAttachISOs) Run(ctx context.Context, state multistep.StateBag) mult
|
||||||
command := []string{
|
command := []string{
|
||||||
"storageattach", vmName,
|
"storageattach", vmName,
|
||||||
"--storagectl", controllerName,
|
"--storagectl", controllerName,
|
||||||
"--port", port,
|
"--port", strconv.Itoa(port),
|
||||||
"--device", device,
|
"--device", strconv.Itoa(device),
|
||||||
"--type", "dvddrive",
|
"--type", "dvddrive",
|
||||||
"--medium", isoPath,
|
"--medium", isoPath,
|
||||||
}
|
}
|
||||||
|
@ -137,8 +140,8 @@ func (s *StepAttachISOs) Run(ctx context.Context, state multistep.StateBag) mult
|
||||||
unmountCommand := []string{
|
unmountCommand := []string{
|
||||||
"storageattach", vmName,
|
"storageattach", vmName,
|
||||||
"--storagectl", controllerName,
|
"--storagectl", controllerName,
|
||||||
"--port", port,
|
"--port", strconv.Itoa(port),
|
||||||
"--device", device,
|
"--device", strconv.Itoa(device),
|
||||||
"--type", "dvddrive",
|
"--type", "dvddrive",
|
||||||
"--medium", "none",
|
"--medium", "none",
|
||||||
}
|
}
|
||||||
|
|
|
@ -149,6 +149,12 @@ type Config struct {
|
||||||
// When set to sata, the drive is attached to an AHCI SATA controller.
|
// When set to sata, the drive is attached to an AHCI SATA controller.
|
||||||
// When set to virtio, the drive is attached to a VirtIO controller.
|
// When set to virtio, the drive is attached to a VirtIO controller.
|
||||||
ISOInterface string `mapstructure:"iso_interface" required:"false"`
|
ISOInterface string `mapstructure:"iso_interface" required:"false"`
|
||||||
|
// 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 value represents the disk image size in MiB.
|
||||||
|
// Each additional disk uses the same disk parameters as the default disk.
|
||||||
|
// Unset by default.
|
||||||
|
AdditionalDiskSize []uint `mapstructure:"disk_additional_size" required:"false"`
|
||||||
// Set this to true if you would like to keep the VM registered with
|
// Set this to true if you would like to keep the VM registered with
|
||||||
// virtualbox. Defaults to false.
|
// virtualbox. Defaults to false.
|
||||||
KeepRegistered bool `mapstructure:"keep_registered" required:"false"`
|
KeepRegistered bool `mapstructure:"keep_registered" required:"false"`
|
||||||
|
|
|
@ -135,6 +135,7 @@ type FlatConfig struct {
|
||||||
NVMePortCount *int `mapstructure:"nvme_port_count" required:"false" cty:"nvme_port_count" hcl:"nvme_port_count"`
|
NVMePortCount *int `mapstructure:"nvme_port_count" required:"false" cty:"nvme_port_count" hcl:"nvme_port_count"`
|
||||||
HardDriveNonrotational *bool `mapstructure:"hard_drive_nonrotational" required:"false" cty:"hard_drive_nonrotational" hcl:"hard_drive_nonrotational"`
|
HardDriveNonrotational *bool `mapstructure:"hard_drive_nonrotational" required:"false" cty:"hard_drive_nonrotational" hcl:"hard_drive_nonrotational"`
|
||||||
ISOInterface *string `mapstructure:"iso_interface" required:"false" cty:"iso_interface" hcl:"iso_interface"`
|
ISOInterface *string `mapstructure:"iso_interface" required:"false" cty:"iso_interface" hcl:"iso_interface"`
|
||||||
|
AdditionalDiskSize []uint `mapstructure:"disk_additional_size" required:"false" cty:"disk_additional_size" hcl:"disk_additional_size"`
|
||||||
KeepRegistered *bool `mapstructure:"keep_registered" required:"false" cty:"keep_registered" hcl:"keep_registered"`
|
KeepRegistered *bool `mapstructure:"keep_registered" required:"false" cty:"keep_registered" hcl:"keep_registered"`
|
||||||
SkipExport *bool `mapstructure:"skip_export" required:"false" cty:"skip_export" hcl:"skip_export"`
|
SkipExport *bool `mapstructure:"skip_export" required:"false" cty:"skip_export" hcl:"skip_export"`
|
||||||
VMName *string `mapstructure:"vm_name" required:"false" cty:"vm_name" hcl:"vm_name"`
|
VMName *string `mapstructure:"vm_name" required:"false" cty:"vm_name" hcl:"vm_name"`
|
||||||
|
@ -277,6 +278,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
||||||
"nvme_port_count": &hcldec.AttrSpec{Name: "nvme_port_count", Type: cty.Number, Required: false},
|
"nvme_port_count": &hcldec.AttrSpec{Name: "nvme_port_count", Type: cty.Number, Required: false},
|
||||||
"hard_drive_nonrotational": &hcldec.AttrSpec{Name: "hard_drive_nonrotational", Type: cty.Bool, Required: false},
|
"hard_drive_nonrotational": &hcldec.AttrSpec{Name: "hard_drive_nonrotational", Type: cty.Bool, Required: false},
|
||||||
"iso_interface": &hcldec.AttrSpec{Name: "iso_interface", Type: cty.String, Required: false},
|
"iso_interface": &hcldec.AttrSpec{Name: "iso_interface", Type: cty.String, Required: false},
|
||||||
|
"disk_additional_size": &hcldec.AttrSpec{Name: "disk_additional_size", Type: cty.List(cty.Number), Required: false},
|
||||||
"keep_registered": &hcldec.AttrSpec{Name: "keep_registered", Type: cty.Bool, Required: false},
|
"keep_registered": &hcldec.AttrSpec{Name: "keep_registered", Type: cty.Bool, Required: false},
|
||||||
"skip_export": &hcldec.AttrSpec{Name: "skip_export", Type: cty.Bool, Required: false},
|
"skip_export": &hcldec.AttrSpec{Name: "skip_export", Type: cty.Bool, Required: false},
|
||||||
"vm_name": &hcldec.AttrSpec{Name: "vm_name", Type: cty.String, Required: false},
|
"vm_name": &hcldec.AttrSpec{Name: "vm_name", Type: cty.String, Required: false},
|
||||||
|
|
|
@ -22,19 +22,37 @@ func (s *stepCreateDisk) Run(ctx context.Context, state multistep.StateBag) mult
|
||||||
driver := state.Get("driver").(vboxcommon.Driver)
|
driver := state.Get("driver").(vboxcommon.Driver)
|
||||||
ui := state.Get("ui").(packersdk.Ui)
|
ui := state.Get("ui").(packersdk.Ui)
|
||||||
vmName := state.Get("vmName").(string)
|
vmName := state.Get("vmName").(string)
|
||||||
|
|
||||||
format := "VDI"
|
format := "VDI"
|
||||||
path := filepath.Join(config.OutputDir, fmt.Sprintf("%s.%s", config.VMName, strings.ToLower(format)))
|
|
||||||
|
// The main disk and additional disks
|
||||||
|
diskFullPaths := []string{}
|
||||||
|
diskSizes := []uint{config.DiskSize}
|
||||||
|
if len(config.AdditionalDiskSize) == 0 {
|
||||||
|
// If there are no additional disks, use disk naming as before
|
||||||
|
diskFullPaths = append(diskFullPaths, filepath.Join(config.OutputDir, fmt.Sprintf("%s.%s", config.VMName, strings.ToLower(format))))
|
||||||
|
} else {
|
||||||
|
// If there are additional disks, use consistent naming with numbers
|
||||||
|
diskFullPaths = append(diskFullPaths, filepath.Join(config.OutputDir, fmt.Sprintf("%s-0.%s", config.VMName, strings.ToLower(format))))
|
||||||
|
|
||||||
|
for i, diskSize := range config.AdditionalDiskSize {
|
||||||
|
path := filepath.Join(config.OutputDir, fmt.Sprintf("%s-%d.%s", config.VMName, i+1, strings.ToLower(format)))
|
||||||
|
diskFullPaths = append(diskFullPaths, path)
|
||||||
|
diskSizes = append(diskSizes, diskSize)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create all required disks
|
||||||
|
for i := range diskFullPaths {
|
||||||
|
ui.Say(fmt.Sprintf("Creating hard drive %s with size %d MiB...", diskFullPaths[i], diskSizes[i]))
|
||||||
|
|
||||||
command := []string{
|
command := []string{
|
||||||
"createhd",
|
"createhd",
|
||||||
"--filename", path,
|
"--filename", diskFullPaths[i],
|
||||||
"--size", strconv.FormatUint(uint64(config.DiskSize), 10),
|
"--size", strconv.FormatUint(uint64(diskSizes[i]), 10),
|
||||||
"--format", format,
|
"--format", format,
|
||||||
"--variant", "Standard",
|
"--variant", "Standard",
|
||||||
}
|
}
|
||||||
|
|
||||||
ui.Say("Creating hard drive...")
|
|
||||||
err := driver.VBoxManage(command...)
|
err := driver.VBoxManage(command...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err := fmt.Errorf("Error creating hard drive: %s", err)
|
err := fmt.Errorf("Error creating hard drive: %s", err)
|
||||||
|
@ -42,11 +60,12 @@ func (s *stepCreateDisk) Run(ctx context.Context, state multistep.StateBag) mult
|
||||||
ui.Error(err.Error())
|
ui.Error(err.Error())
|
||||||
return multistep.ActionHalt
|
return multistep.ActionHalt
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Add the IDE controller so we can later attach the disk.
|
// Add the IDE controller so we can later attach the disk.
|
||||||
// When the hard disk controller is not IDE, this device is still used
|
// When the hard disk controller is not IDE, this device is still used
|
||||||
// by VirtualBox to deliver the guest extensions.
|
// by VirtualBox to deliver the guest extensions.
|
||||||
err = driver.VBoxManage("storagectl", vmName, "--name", "IDE Controller", "--add", "ide")
|
err := driver.VBoxManage("storagectl", vmName, "--name", "IDE Controller", "--add", "ide")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err := fmt.Errorf("Error creating disk controller: %s", err)
|
err := fmt.Errorf("Error creating disk controller: %s", err)
|
||||||
state.Put("error", err)
|
state.Put("error", err)
|
||||||
|
@ -116,13 +135,14 @@ func (s *stepCreateDisk) Run(ctx context.Context, state multistep.StateBag) mult
|
||||||
discard = "on"
|
discard = "on"
|
||||||
}
|
}
|
||||||
|
|
||||||
command = []string{
|
for i := range diskFullPaths {
|
||||||
|
command := []string{
|
||||||
"storageattach", vmName,
|
"storageattach", vmName,
|
||||||
"--storagectl", controllerName,
|
"--storagectl", controllerName,
|
||||||
"--port", "0",
|
"--port", strconv.FormatUint(uint64(i), 10),
|
||||||
"--device", "0",
|
"--device", "0",
|
||||||
"--type", "hdd",
|
"--type", "hdd",
|
||||||
"--medium", path,
|
"--medium", diskFullPaths[i],
|
||||||
"--nonrotational", nonrotational,
|
"--nonrotational", nonrotational,
|
||||||
"--discard", discard,
|
"--discard", discard,
|
||||||
}
|
}
|
||||||
|
@ -132,6 +152,7 @@ func (s *stepCreateDisk) Run(ctx context.Context, state multistep.StateBag) mult
|
||||||
ui.Error(err.Error())
|
ui.Error(err.Error())
|
||||||
return multistep.ActionHalt
|
return multistep.ActionHalt
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return multistep.ActionContinue
|
return multistep.ActionContinue
|
||||||
}
|
}
|
||||||
|
|
|
@ -103,6 +103,12 @@
|
||||||
When set to sata, the drive is attached to an AHCI SATA controller.
|
When set to sata, the drive is attached to an AHCI SATA controller.
|
||||||
When set to virtio, the drive is attached to a VirtIO controller.
|
When set to virtio, the drive is attached to a VirtIO controller.
|
||||||
|
|
||||||
|
- `disk_additional_size` ([]uint) - 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 value represents the disk image size in MiB.
|
||||||
|
Each additional disk uses the same disk parameters as the default disk.
|
||||||
|
Unset by default.
|
||||||
|
|
||||||
- `keep_registered` (bool) - Set this to true if you would like to keep the VM registered with
|
- `keep_registered` (bool) - Set this to true if you would like to keep the VM registered with
|
||||||
virtualbox. Defaults to false.
|
virtualbox. Defaults to false.
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue