Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(vm): add support for boot_order argument for VM #219

Merged
merged 3 commits into from
Apr 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion docs/resources/virtual_environment_vm.md
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,8 @@ output "ubuntu_vm_public_key" {
- `bios` - (Optional) The BIOS implementation (defaults to `seabios`).
- `ovmf` - OVMF (UEFI).
- `seabios` - SeaBIOS.
- `boot_order` - (Optional) Specify a list of devices to boot from in the order
they appear in the list (defaults to `[]`).
- `cdrom` - (Optional) The CDROM configuration.
- `enabled` - (Optional) Whether to enable the CDROM drive (defaults
to `false`).
Expand Down Expand Up @@ -361,7 +363,8 @@ output "ubuntu_vm_public_key" {
- `device` - (Optional) The device (defaults to `socket`).
- `/dev/*` - A host serial device.
- `socket` - A unix socket.
- `scsi_hardware` - (Optional) The SCSI hardware type (defaults to `virtio-scsi-pci`).
- `scsi_hardware` - (Optional) The SCSI hardware type (defaults
to `virtio-scsi-pci`).
- `lsi` - LSI Logic SAS1068E.
- `lsi53c810` - LSI Logic 53C810.
- `virtio-scsi-pci` - VirtIO SCSI.
Expand Down
40 changes: 38 additions & 2 deletions proxmox/virtual_environment_vm_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ type CustomAudioDevice struct {
// CustomAudioDevices handles QEMU audio device parameters.
type CustomAudioDevices []CustomAudioDevice

type CustomBoot struct {
Order *[]string `json:"order,omitempty" url:"order,omitempty,semicolon"`
}

// CustomCloudInitConfig handles QEMU cloud-init parameters.
type CustomCloudInitConfig struct {
Files *CustomCloudInitFiles `json:"cicustom,omitempty" url:"cicustom,omitempty"`
Expand Down Expand Up @@ -236,8 +240,7 @@ type VirtualEnvironmentVMCreateRequestBody struct {
BackupFile *string `json:"archive,omitempty" url:"archive,omitempty"`
BandwidthLimit *int `json:"bwlimit,omitempty" url:"bwlimit,omitempty"`
BIOS *string `json:"bios,omitempty" url:"bios,omitempty"`
BootDisk *string `json:"bootdisk,omitempty" url:"bootdisk,omitempty"`
BootOrder *string `json:"boot,omitempty" url:"boot,omitempty"`
Boot *CustomBoot `json:"boot,omitempty" url:"boot,omitempty"`
CDROM *string `json:"cdrom,omitempty" url:"cdrom,omitempty"`
CloudInitConfig *CustomCloudInitConfig `json:"cloudinit,omitempty" url:"cloudinit,omitempty"`
CPUArchitecture *string `json:"arch,omitempty" url:"arch,omitempty"`
Expand Down Expand Up @@ -646,6 +649,14 @@ func (r CustomAudioDevices) EncodeValues(key string, v *url.Values) error {
return nil
}

func (r CustomBoot) EncodeValues(key string, v *url.Values) error {
if r.Order != nil && len(*r.Order) > 0 {
v.Add(key, fmt.Sprintf("order=%s", strings.Join(*r.Order, ";")))
}

return nil
}

// EncodeValues converts a CustomCloudInitConfig struct to multiple URL values.
func (r CustomCloudInitConfig) EncodeValues(_ string, v *url.Values) error {
if r.Files != nil {
Expand Down Expand Up @@ -1299,6 +1310,31 @@ func (r *CustomAudioDevice) UnmarshalJSON(b []byte) error {
return nil
}

// UnmarshalJSON converts a CustomBoot string to an object.
func (r *CustomBoot) UnmarshalJSON(b []byte) error {
var s string

err := json.Unmarshal(b, &s)
if err != nil {
return fmt.Errorf("error unmarshalling CustomBoot: %w", err)
}

pairs := strings.Split(s, ",")

for _, p := range pairs {
v := strings.Split(strings.TrimSpace(p), "=")

if len(v) == 2 {
if v[0] == "order" {
v := strings.Split(strings.TrimSpace(v[1]), ";")
r.Order = &v
}
}
}

return nil
}

// UnmarshalJSON converts a CustomCloudInitFiles string to an object.
func (r *CustomCloudInitFiles) UnmarshalJSON(b []byte) error {
var s string
Expand Down
60 changes: 51 additions & 9 deletions proxmoxtf/resource/vm.go
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ const (

mkResourceVirtualEnvironmentVMRebootAfterCreation = "reboot"
mkResourceVirtualEnvironmentVMOnBoot = "on_boot"
mkResourceVirtualEnvironmentVMBootOrder = "boot_order"
mkResourceVirtualEnvironmentVMACPI = "acpi"
mkResourceVirtualEnvironmentVMAgent = "agent"
mkResourceVirtualEnvironmentVMAgentEnabled = "enabled"
Expand Down Expand Up @@ -242,6 +243,15 @@ func VM() *schema.Resource {
Optional: true,
Default: dvResourceVirtualEnvironmentVMOnBoot,
},
mkResourceVirtualEnvironmentVMBootOrder: {
Type: schema.TypeList,
Description: "The guest will attempt to boot from devices in the order they appear here",
Optional: true,
Elem: &schema.Schema{Type: schema.TypeString},
DefaultFunc: func() (interface{}, error) {
return []interface{}{}, nil
},
},
mkResourceVirtualEnvironmentVMACPI: {
Type: schema.TypeBool,
Description: "Whether to enable ACPI",
Expand Down Expand Up @@ -1915,15 +1925,33 @@ func vmCreateCustom(ctx context.Context, d *schema.ResourceData, m interface{})

var memorySharedObject *proxmox.CustomSharedMemory

bootDisk := "scsi0"
bootOrder := "c"

var bootOrderConverted []string
if cdromEnabled {
bootOrder = "cd"
bootOrderConverted = []string{"ide3"}
}
bootOrder := d.Get(mkResourceVirtualEnvironmentVMBootOrder).([]interface{})
//nolint:nestif
if len(bootOrder) == 0 {
if sataDeviceObjects != nil {
bootOrderConverted = append(bootOrderConverted, "sata0")
}
if scsiDeviceObjects != nil {
bootOrderConverted = append(bootOrderConverted, "scsi0")
}
if virtioDeviceObjects != nil {
bootOrderConverted = append(bootOrderConverted, "virtio0")
}
if networkDeviceObjects != nil {
bootOrderConverted = append(bootOrderConverted, "net0")
}
} else {
bootOrderConverted = make([]string, len(bootOrder))
for i, device := range bootOrder {
bootOrderConverted[i] = device.(string)
}
}

cpuFlagsConverted := make([]string, len(cpuFlags))

for fi, flag := range cpuFlags {
cpuFlagsConverted[fi] = flag.(string)
}
Expand Down Expand Up @@ -1959,10 +1987,11 @@ func vmCreateCustom(ctx context.Context, d *schema.ResourceData, m interface{})
TrimClonedDisks: &agentTrim,
Type: &agentType,
},
AudioDevices: audioDevices,
BIOS: &bios,
BootDisk: &bootDisk,
BootOrder: &bootOrder,
AudioDevices: audioDevices,
BIOS: &bios,
Boot: &proxmox.CustomBoot{
Order: &bootOrderConverted,
},
CloudInitConfig: initializationConfig,
CPUCores: &cpuCores,
CPUEmulation: &proxmox.CustomCPUEmulation{
Expand Down Expand Up @@ -4036,6 +4065,19 @@ func vmUpdate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.D
rebootRequired = true
}

// Prepare the new boot configuration.
if d.HasChange(mkResourceVirtualEnvironmentVMBootOrder) {
bootOrder := d.Get(mkResourceVirtualEnvironmentVMBootOrder).([]interface{})
bootOrderConverted := make([]string, len(bootOrder))
for i, device := range bootOrder {
bootOrderConverted[i] = device.(string)
}
updateBody.Boot = &proxmox.CustomBoot{
Order: &bootOrderConverted,
}
rebootRequired = true
}

// Prepare the new CDROM configuration.
if d.HasChange(mkResourceVirtualEnvironmentVMCDROM) {
cdromBlock, err := getSchemaBlock(
Expand Down
2 changes: 2 additions & 0 deletions proxmoxtf/resource/vm_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ func TestVMSchema(t *testing.T) {
mkResourceVirtualEnvironmentVMAgent,
mkResourceVirtualEnvironmentVMAudioDevice,
mkResourceVirtualEnvironmentVMBIOS,
mkResourceVirtualEnvironmentVMBootOrder,
mkResourceVirtualEnvironmentVMCDROM,
mkResourceVirtualEnvironmentVMClone,
mkResourceVirtualEnvironmentVMCPU,
Expand Down Expand Up @@ -73,6 +74,7 @@ func TestVMSchema(t *testing.T) {
mkResourceVirtualEnvironmentVMAgent: schema.TypeList,
mkResourceVirtualEnvironmentVMAudioDevice: schema.TypeList,
mkResourceVirtualEnvironmentVMBIOS: schema.TypeString,
mkResourceVirtualEnvironmentVMBootOrder: schema.TypeList,
mkResourceVirtualEnvironmentVMCDROM: schema.TypeList,
mkResourceVirtualEnvironmentVMCPU: schema.TypeList,
mkResourceVirtualEnvironmentVMDescription: schema.TypeString,
Expand Down