0
0
mirror of https://github.com/bpg/terraform-provider-proxmox.git synced 2025-08-23 11:58:34 +00:00

Add audio_device argument to VM resource

This commit is contained in:
Dan Petersen 2020-01-14 21:31:21 +01:00
parent 23466ab289
commit 1c96dc1803
6 changed files with 319 additions and 118 deletions

View File

@ -2,8 +2,13 @@
ENHANCEMENTS: ENHANCEMENTS:
* resource/virtual_environment_vm: Add `audio_device` argument
* resource/virtual_environment_vm: Add `serial_device` argument * resource/virtual_environment_vm: Add `serial_device` argument
BUG FIXES:
* resource/virtual_environment_vm: Fix `network_device` deletion issue
## 0.2.0 ## 0.2.0
BREAKING CHANGES: BREAKING CHANGES:

View File

@ -475,6 +475,14 @@ This resource doesn't expose any additional attributes.
* `type` - (Optional) The QEMU agent interface type (defaults to `virtio`) * `type` - (Optional) The QEMU agent interface type (defaults to `virtio`)
* `isa` - ISA Serial Port * `isa` - ISA Serial Port
* `virtio` - VirtIO (paravirtualized) * `virtio` - VirtIO (paravirtualized)
* `audio_device` - (Optional) An audio device
* `device` - (Optional) The device (defaults to `intel-hda`)
* `AC97` - Intel 82801AA AC97 Audio
* `ich9-intel-hda` - Intel HD Audio Controller (ich9)
* `intel-hda` - Intel HD Audio
* `driver` - (Optional) The driver (defaults to `spice`)
* `spice` - Spice
* `enabled` - (Optional) Whether to enable the audio device (defaults to `true`)
* `bios` - (Optional) The BIOS implementation (defaults to `seabios`) * `bios` - (Optional) The BIOS implementation (defaults to `seabios`)
* `ovmf` - OVMF (UEFI) * `ovmf` - OVMF (UEFI)
* `seabios` - SeaBIOS * `seabios` - SeaBIOS

View File

@ -23,9 +23,13 @@ type CustomAgent struct {
// CustomAudioDevice handles QEMU audio parameters. // CustomAudioDevice handles QEMU audio parameters.
type CustomAudioDevice struct { type CustomAudioDevice struct {
Device string `json:"device" url:"device"` Device string `json:"device" url:"device"`
Driver string `json:"driver" url:"driver"` Driver *string `json:"driver" url:"driver"`
Enabled bool `json:"-" url:"-"`
} }
// CustomAudioDevices handles QEMU audio device parameters.
type CustomAudioDevices []CustomAudioDevice
// CustomCloudInitConfig handles QEMU cloud-init parameters. // CustomCloudInitConfig handles QEMU cloud-init parameters.
type CustomCloudInitConfig struct { type CustomCloudInitConfig struct {
Files *CustomCloudInitFiles `json:"cicustom,omitempty" url:"cicustom,omitempty"` Files *CustomCloudInitFiles `json:"cicustom,omitempty" url:"cicustom,omitempty"`
@ -200,7 +204,7 @@ type VirtualEnvironmentVMCreateRequestBody struct {
ACPI *CustomBool `json:"acpi,omitempty" url:"acpi,omitempty,int"` ACPI *CustomBool `json:"acpi,omitempty" url:"acpi,omitempty,int"`
Agent *CustomAgent `json:"agent,omitempty" url:"agent,omitempty"` Agent *CustomAgent `json:"agent,omitempty" url:"agent,omitempty"`
AllowReboot *CustomBool `json:"reboot,omitempty" url:"reboot,omitempty,int"` AllowReboot *CustomBool `json:"reboot,omitempty" url:"reboot,omitempty,int"`
AudioDevice *CustomAudioDevice `json:"audio0,omitempty" url:"audio0,omitempty"` AudioDevices CustomAudioDevices `json:"audio,omitempty" url:"audio,omitempty"`
Autostart *CustomBool `json:"autostart,omitempty" url:"autostart,omitempty,int"` Autostart *CustomBool `json:"autostart,omitempty" url:"autostart,omitempty,int"`
BackupFile *string `json:"archive,omitempty" url:"archive,omitempty"` BackupFile *string `json:"archive,omitempty" url:"archive,omitempty"`
BandwidthLimit *int `json:"bwlimit,omitempty" url:"bwlimit,omitempty"` BandwidthLimit *int `json:"bwlimit,omitempty" url:"bwlimit,omitempty"`
@ -508,7 +512,24 @@ func (r CustomAgent) EncodeValues(key string, v *url.Values) error {
// EncodeValues converts a CustomAudioDevice struct to a URL vlaue. // EncodeValues converts a CustomAudioDevice struct to a URL vlaue.
func (r CustomAudioDevice) EncodeValues(key string, v *url.Values) error { func (r CustomAudioDevice) EncodeValues(key string, v *url.Values) error {
v.Add(key, fmt.Sprintf("device=%s,driver=%s", r.Device, r.Driver)) values := []string{fmt.Sprintf("device=%s", r.Device)}
if r.Driver != nil {
values = append(values, fmt.Sprintf("driver=%s", *r.Driver))
}
v.Add(key, strings.Join(values, ","))
return nil
}
// EncodeValues converts a CustomAudioDevices array to multiple URL values.
func (r CustomAudioDevices) EncodeValues(key string, v *url.Values) error {
for i, d := range r {
if d.Enabled {
d.EncodeValues(fmt.Sprintf("%s%d", key, i), v)
}
}
return nil return nil
} }
@ -1088,6 +1109,34 @@ func (r *CustomAgent) UnmarshalJSON(b []byte) error {
return nil return nil
} }
// UnmarshalJSON converts a CustomAgent string to an object.
func (r *CustomAudioDevice) UnmarshalJSON(b []byte) error {
var s string
err := json.Unmarshal(b, &s)
if err != nil {
return err
}
pairs := strings.Split(s, ",")
for _, p := range pairs {
v := strings.Split(strings.TrimSpace(p), "=")
if len(v) == 2 {
switch v[0] {
case "device":
r.Device = v[1]
case "driver":
r.Driver = &v[1]
}
}
}
return nil
}
// UnmarshalJSON converts a CustomCloudInitFiles string to an object. // UnmarshalJSON converts a CustomCloudInitFiles string to an object.
func (r *CustomCloudInitFiles) UnmarshalJSON(b []byte) error { func (r *CustomCloudInitFiles) UnmarshalJSON(b []byte) error {
var s string var s string

View File

@ -102,16 +102,13 @@ func resourceVirtualEnvironmentContainer() *schema.Resource {
Description: "The console configuration", Description: "The console configuration",
Optional: true, Optional: true,
DefaultFunc: func() (interface{}, error) { DefaultFunc: func() (interface{}, error) {
defaultList := make([]interface{}, 1) return []interface{}{
defaultMap := map[string]interface{}{} map[string]interface{}{
mkResourceVirtualEnvironmentContainerConsoleEnabled: dvResourceVirtualEnvironmentContainerConsoleEnabled,
defaultMap[mkResourceVirtualEnvironmentContainerConsoleEnabled] = dvResourceVirtualEnvironmentContainerConsoleEnabled mkResourceVirtualEnvironmentContainerConsoleMode: dvResourceVirtualEnvironmentContainerConsoleMode,
defaultMap[mkResourceVirtualEnvironmentContainerConsoleMode] = dvResourceVirtualEnvironmentContainerConsoleMode mkResourceVirtualEnvironmentContainerConsoleTTYCount: dvResourceVirtualEnvironmentContainerConsoleTTYCount,
defaultMap[mkResourceVirtualEnvironmentContainerConsoleTTYCount] = dvResourceVirtualEnvironmentContainerConsoleTTYCount },
}, nil
defaultList[0] = defaultMap
return defaultList, nil
}, },
Elem: &schema.Resource{ Elem: &schema.Resource{
Schema: map[string]*schema.Schema{ Schema: map[string]*schema.Schema{
@ -145,16 +142,13 @@ func resourceVirtualEnvironmentContainer() *schema.Resource {
Description: "The CPU allocation", Description: "The CPU allocation",
Optional: true, Optional: true,
DefaultFunc: func() (interface{}, error) { DefaultFunc: func() (interface{}, error) {
defaultList := make([]interface{}, 1) return []interface{}{
defaultMap := map[string]interface{}{} map[string]interface{}{
mkResourceVirtualEnvironmentContainerCPUArchitecture: dvResourceVirtualEnvironmentContainerCPUArchitecture,
defaultMap[mkResourceVirtualEnvironmentContainerCPUArchitecture] = dvResourceVirtualEnvironmentContainerCPUArchitecture mkResourceVirtualEnvironmentContainerCPUCores: dvResourceVirtualEnvironmentContainerCPUCores,
defaultMap[mkResourceVirtualEnvironmentContainerCPUCores] = dvResourceVirtualEnvironmentContainerCPUCores mkResourceVirtualEnvironmentContainerCPUUnits: dvResourceVirtualEnvironmentContainerCPUUnits,
defaultMap[mkResourceVirtualEnvironmentContainerCPUUnits] = dvResourceVirtualEnvironmentContainerCPUUnits },
}, nil
defaultList[0] = defaultMap
return defaultList, nil
}, },
Elem: &schema.Resource{ Elem: &schema.Resource{
Schema: map[string]*schema.Schema{ Schema: map[string]*schema.Schema{
@ -343,15 +337,12 @@ func resourceVirtualEnvironmentContainer() *schema.Resource {
Description: "The memory allocation", Description: "The memory allocation",
Optional: true, Optional: true,
DefaultFunc: func() (interface{}, error) { DefaultFunc: func() (interface{}, error) {
defaultList := make([]interface{}, 1) return []interface{}{
defaultMap := map[string]interface{}{} map[string]interface{}{
mkResourceVirtualEnvironmentContainerMemoryDedicated: dvResourceVirtualEnvironmentContainerMemoryDedicated,
defaultMap[mkResourceVirtualEnvironmentContainerMemoryDedicated] = dvResourceVirtualEnvironmentContainerMemoryDedicated mkResourceVirtualEnvironmentContainerMemorySwap: dvResourceVirtualEnvironmentContainerMemorySwap,
defaultMap[mkResourceVirtualEnvironmentContainerMemorySwap] = dvResourceVirtualEnvironmentContainerMemorySwap },
}, nil
defaultList[0] = defaultMap
return defaultList, nil
}, },
Elem: &schema.Resource{ Elem: &schema.Resource{
Schema: map[string]*schema.Schema{ Schema: map[string]*schema.Schema{

View File

@ -16,10 +16,17 @@ import (
) )
const ( const (
maxAudioDevices = 1
maxNetworkDevices = 8
maxSerialDevices = 4
dvResourceVirtualEnvironmentVMACPI = true dvResourceVirtualEnvironmentVMACPI = true
dvResourceVirtualEnvironmentVMAgentEnabled = false dvResourceVirtualEnvironmentVMAgentEnabled = false
dvResourceVirtualEnvironmentVMAgentTrim = false dvResourceVirtualEnvironmentVMAgentTrim = false
dvResourceVirtualEnvironmentVMAgentType = "virtio" dvResourceVirtualEnvironmentVMAgentType = "virtio"
dvResourceVirtualEnvironmentVMAudioDeviceDevice = "intel-hda"
dvResourceVirtualEnvironmentVMAudioDeviceDriver = "spice"
dvResourceVirtualEnvironmentVMAudioDeviceEnabled = true
dvResourceVirtualEnvironmentVMBIOS = "seabios" dvResourceVirtualEnvironmentVMBIOS = "seabios"
dvResourceVirtualEnvironmentVMCDROMEnabled = false dvResourceVirtualEnvironmentVMCDROMEnabled = false
dvResourceVirtualEnvironmentVMCDROMFileID = "" dvResourceVirtualEnvironmentVMCDROMFileID = ""
@ -72,6 +79,10 @@ const (
mkResourceVirtualEnvironmentVMAgentEnabled = "enabled" mkResourceVirtualEnvironmentVMAgentEnabled = "enabled"
mkResourceVirtualEnvironmentVMAgentTrim = "trim" mkResourceVirtualEnvironmentVMAgentTrim = "trim"
mkResourceVirtualEnvironmentVMAgentType = "type" mkResourceVirtualEnvironmentVMAgentType = "type"
mkResourceVirtualEnvironmentVMAudioDevice = "audio_device"
mkResourceVirtualEnvironmentVMAudioDeviceDevice = "device"
mkResourceVirtualEnvironmentVMAudioDeviceDriver = "driver"
mkResourceVirtualEnvironmentVMAudioDeviceEnabled = "enabled"
mkResourceVirtualEnvironmentVMBIOS = "bios" mkResourceVirtualEnvironmentVMBIOS = "bios"
mkResourceVirtualEnvironmentVMCDROM = "cdrom" mkResourceVirtualEnvironmentVMCDROM = "cdrom"
mkResourceVirtualEnvironmentVMCDROMEnabled = "enabled" mkResourceVirtualEnvironmentVMCDROMEnabled = "enabled"
@ -157,16 +168,13 @@ func resourceVirtualEnvironmentVM() *schema.Resource {
Description: "The QEMU agent configuration", Description: "The QEMU agent configuration",
Optional: true, Optional: true,
DefaultFunc: func() (interface{}, error) { DefaultFunc: func() (interface{}, error) {
defaultList := make([]interface{}, 1) return []interface{}{
defaultMap := map[string]interface{}{} map[string]interface{}{
mkResourceVirtualEnvironmentVMAgentEnabled: dvResourceVirtualEnvironmentVMAgentEnabled,
defaultMap[mkResourceVirtualEnvironmentVMAgentEnabled] = dvResourceVirtualEnvironmentVMAgentEnabled mkResourceVirtualEnvironmentVMAgentTrim: dvResourceVirtualEnvironmentVMAgentEnabled,
defaultMap[mkResourceVirtualEnvironmentVMAgentTrim] = dvResourceVirtualEnvironmentVMAgentTrim mkResourceVirtualEnvironmentVMAgentType: dvResourceVirtualEnvironmentVMAgentType,
defaultMap[mkResourceVirtualEnvironmentVMAgentType] = dvResourceVirtualEnvironmentVMAgentType },
}, nil
defaultList[0] = defaultMap
return defaultList, nil
}, },
Elem: &schema.Resource{ Elem: &schema.Resource{
Schema: map[string]*schema.Schema{ Schema: map[string]*schema.Schema{
@ -194,6 +202,40 @@ func resourceVirtualEnvironmentVM() *schema.Resource {
MaxItems: 1, MaxItems: 1,
MinItems: 0, MinItems: 0,
}, },
mkResourceVirtualEnvironmentVMAudioDevice: &schema.Schema{
Type: schema.TypeList,
Description: "The audio devices",
Optional: true,
DefaultFunc: func() (interface{}, error) {
return []interface{}{}, nil
},
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
mkResourceVirtualEnvironmentVMAudioDeviceDevice: {
Type: schema.TypeString,
Description: "The device",
Optional: true,
Default: dvResourceVirtualEnvironmentVMAudioDeviceDevice,
ValidateFunc: resourceVirtualEnvironmentVMGetAudioDeviceValidator(),
},
mkResourceVirtualEnvironmentVMAudioDeviceDriver: {
Type: schema.TypeString,
Description: "The driver",
Optional: true,
Default: dvResourceVirtualEnvironmentVMAudioDeviceDriver,
ValidateFunc: resourceVirtualEnvironmentVMGetAudioDriverValidator(),
},
mkResourceVirtualEnvironmentVMAudioDeviceEnabled: {
Type: schema.TypeBool,
Description: "Whether to enable the audio device",
Optional: true,
Default: dvResourceVirtualEnvironmentVMAudioDeviceEnabled,
},
},
},
MaxItems: maxAudioDevices,
MinItems: 0,
},
mkResourceVirtualEnvironmentVMBIOS: { mkResourceVirtualEnvironmentVMBIOS: {
Type: schema.TypeString, Type: schema.TypeString,
Description: "The BIOS implementation", Description: "The BIOS implementation",
@ -206,15 +248,12 @@ func resourceVirtualEnvironmentVM() *schema.Resource {
Description: "The CDROM drive", Description: "The CDROM drive",
Optional: true, Optional: true,
DefaultFunc: func() (interface{}, error) { DefaultFunc: func() (interface{}, error) {
defaultList := make([]interface{}, 1) return []interface{}{
defaultMap := map[string]interface{}{} map[string]interface{}{
mkResourceVirtualEnvironmentVMCDROMEnabled: dvResourceVirtualEnvironmentVMCDROMEnabled,
defaultMap[mkResourceVirtualEnvironmentVMCDROMEnabled] = dvResourceVirtualEnvironmentVMCDROMEnabled mkResourceVirtualEnvironmentVMCDROMFileID: dvResourceVirtualEnvironmentVMCDROMFileID,
defaultMap[mkResourceVirtualEnvironmentVMCDROMFileID] = dvResourceVirtualEnvironmentVMCDROMFileID },
}, nil
defaultList[0] = defaultMap
return defaultList, nil
}, },
Elem: &schema.Resource{ Elem: &schema.Resource{
Schema: map[string]*schema.Schema{ Schema: map[string]*schema.Schema{
@ -241,20 +280,17 @@ func resourceVirtualEnvironmentVM() *schema.Resource {
Description: "The CPU allocation", Description: "The CPU allocation",
Optional: true, Optional: true,
DefaultFunc: func() (interface{}, error) { DefaultFunc: func() (interface{}, error) {
defaultList := make([]interface{}, 1) return []interface{}{
defaultMap := map[string]interface{}{} map[string]interface{}{
mkResourceVirtualEnvironmentVMCPUArchitecture: dvResourceVirtualEnvironmentVMCPUArchitecture,
defaultMap[mkResourceVirtualEnvironmentVMCPUArchitecture] = dvResourceVirtualEnvironmentVMCPUArchitecture mkResourceVirtualEnvironmentVMCPUCores: dvResourceVirtualEnvironmentVMCPUCores,
defaultMap[mkResourceVirtualEnvironmentVMCPUCores] = dvResourceVirtualEnvironmentVMCPUCores mkResourceVirtualEnvironmentVMCPUFlags: []interface{}{},
defaultMap[mkResourceVirtualEnvironmentVMCPUFlags] = []interface{}{} mkResourceVirtualEnvironmentVMCPUHotplugged: dvResourceVirtualEnvironmentVMCPUHotplugged,
defaultMap[mkResourceVirtualEnvironmentVMCPUHotplugged] = dvResourceVirtualEnvironmentVMCPUHotplugged mkResourceVirtualEnvironmentVMCPUSockets: dvResourceVirtualEnvironmentVMCPUSockets,
defaultMap[mkResourceVirtualEnvironmentVMCPUSockets] = dvResourceVirtualEnvironmentVMCPUSockets mkResourceVirtualEnvironmentVMCPUType: dvResourceVirtualEnvironmentVMCPUType,
defaultMap[mkResourceVirtualEnvironmentVMCPUType] = dvResourceVirtualEnvironmentVMCPUType mkResourceVirtualEnvironmentVMCPUUnits: dvResourceVirtualEnvironmentVMCPUUnits,
defaultMap[mkResourceVirtualEnvironmentVMCPUUnits] = dvResourceVirtualEnvironmentVMCPUUnits },
}, nil
defaultList[0] = defaultMap
return defaultList, nil
}, },
Elem: &schema.Resource{ Elem: &schema.Resource{
Schema: map[string]*schema.Schema{ Schema: map[string]*schema.Schema{
@ -326,17 +362,14 @@ func resourceVirtualEnvironmentVM() *schema.Resource {
Optional: true, Optional: true,
ForceNew: true, ForceNew: true,
DefaultFunc: func() (interface{}, error) { DefaultFunc: func() (interface{}, error) {
defaultList := make([]interface{}, 1) return []interface{}{
defaultMap := map[string]interface{}{} map[string]interface{}{
mkResourceVirtualEnvironmentVMDiskDatastoreID: dvResourceVirtualEnvironmentVMDiskDatastoreID,
defaultMap[mkResourceVirtualEnvironmentVMDiskDatastoreID] = dvResourceVirtualEnvironmentVMDiskDatastoreID mkResourceVirtualEnvironmentVMDiskFileFormat: dvResourceVirtualEnvironmentVMDiskFileFormat,
defaultMap[mkResourceVirtualEnvironmentVMDiskFileFormat] = dvResourceVirtualEnvironmentVMDiskFileFormat mkResourceVirtualEnvironmentVMDiskFileID: dvResourceVirtualEnvironmentVMDiskFileID,
defaultMap[mkResourceVirtualEnvironmentVMDiskFileID] = dvResourceVirtualEnvironmentVMDiskFileID mkResourceVirtualEnvironmentVMDiskSize: dvResourceVirtualEnvironmentVMDiskSize,
defaultMap[mkResourceVirtualEnvironmentVMDiskSize] = dvResourceVirtualEnvironmentVMDiskSize },
}, nil
defaultList[0] = defaultMap
return defaultList, nil
}, },
Elem: &schema.Resource{ Elem: &schema.Resource{
Schema: map[string]*schema.Schema{ Schema: map[string]*schema.Schema{
@ -376,17 +409,14 @@ func resourceVirtualEnvironmentVM() *schema.Resource {
Description: "The speed limits", Description: "The speed limits",
Optional: true, Optional: true,
DefaultFunc: func() (interface{}, error) { DefaultFunc: func() (interface{}, error) {
defaultList := make([]interface{}, 1) return []interface{}{
defaultMap := map[string]interface{}{} map[string]interface{}{
mkResourceVirtualEnvironmentVMDiskSpeedRead: dvResourceVirtualEnvironmentVMDiskSpeedRead,
defaultMap[mkResourceVirtualEnvironmentVMDiskSpeedRead] = dvResourceVirtualEnvironmentVMDiskSpeedRead mkResourceVirtualEnvironmentVMDiskSpeedReadBurstable: dvResourceVirtualEnvironmentVMDiskSpeedReadBurstable,
defaultMap[mkResourceVirtualEnvironmentVMDiskSpeedReadBurstable] = dvResourceVirtualEnvironmentVMDiskSpeedReadBurstable mkResourceVirtualEnvironmentVMDiskSpeedWrite: dvResourceVirtualEnvironmentVMDiskSpeedWrite,
defaultMap[mkResourceVirtualEnvironmentVMDiskSpeedWrite] = dvResourceVirtualEnvironmentVMDiskSpeedWrite mkResourceVirtualEnvironmentVMDiskSpeedWriteBurstable: dvResourceVirtualEnvironmentVMDiskSpeedWriteBurstable,
defaultMap[mkResourceVirtualEnvironmentVMDiskSpeedWriteBurstable] = dvResourceVirtualEnvironmentVMDiskSpeedWriteBurstable },
}, nil
defaultList[0] = defaultMap
return defaultList, nil
}, },
Elem: &schema.Resource{ Elem: &schema.Resource{
Schema: map[string]*schema.Schema{ Schema: map[string]*schema.Schema{
@ -613,16 +643,13 @@ func resourceVirtualEnvironmentVM() *schema.Resource {
Description: "The memory allocation", Description: "The memory allocation",
Optional: true, Optional: true,
DefaultFunc: func() (interface{}, error) { DefaultFunc: func() (interface{}, error) {
defaultList := make([]interface{}, 1) return []interface{}{
defaultMap := map[string]interface{}{} map[string]interface{}{
mkResourceVirtualEnvironmentVMMemoryDedicated: dvResourceVirtualEnvironmentVMMemoryDedicated,
defaultMap[mkResourceVirtualEnvironmentVMMemoryDedicated] = dvResourceVirtualEnvironmentVMMemoryDedicated mkResourceVirtualEnvironmentVMMemoryFloating: dvResourceVirtualEnvironmentVMMemoryFloating,
defaultMap[mkResourceVirtualEnvironmentVMMemoryFloating] = dvResourceVirtualEnvironmentVMMemoryFloating mkResourceVirtualEnvironmentVMMemoryShared: dvResourceVirtualEnvironmentVMMemoryShared,
defaultMap[mkResourceVirtualEnvironmentVMMemoryShared] = dvResourceVirtualEnvironmentVMMemoryShared },
}, nil
defaultList[0] = defaultMap
return defaultList, nil
}, },
Elem: &schema.Resource{ Elem: &schema.Resource{
Schema: map[string]*schema.Schema{ Schema: map[string]*schema.Schema{
@ -710,7 +737,7 @@ func resourceVirtualEnvironmentVM() *schema.Resource {
}, },
}, },
}, },
MaxItems: 8, MaxItems: maxNetworkDevices,
MinItems: 0, MinItems: 0,
}, },
mkResourceVirtualEnvironmentVMNetworkInterfaceNames: { mkResourceVirtualEnvironmentVMNetworkInterfaceNames: {
@ -730,14 +757,11 @@ func resourceVirtualEnvironmentVM() *schema.Resource {
Description: "The operating system configuration", Description: "The operating system configuration",
Optional: true, Optional: true,
DefaultFunc: func() (interface{}, error) { DefaultFunc: func() (interface{}, error) {
defaultList := make([]interface{}, 1) return []interface{}{
defaultMap := map[string]interface{}{} map[string]interface{}{
mkResourceVirtualEnvironmentVMOperatingSystemType: dvResourceVirtualEnvironmentVMOperatingSystemType,
defaultMap[mkResourceVirtualEnvironmentVMOperatingSystemType] = dvResourceVirtualEnvironmentVMOperatingSystemType },
}, nil
defaultList[0] = defaultMap
return defaultList, nil
}, },
Elem: &schema.Resource{ Elem: &schema.Resource{
Schema: map[string]*schema.Schema{ Schema: map[string]*schema.Schema{
@ -782,7 +806,7 @@ func resourceVirtualEnvironmentVM() *schema.Resource {
}, },
}, },
}, },
MaxItems: 4, MaxItems: maxSerialDevices,
MinItems: 0, MinItems: 0,
}, },
mkResourceVirtualEnvironmentVMStarted: { mkResourceVirtualEnvironmentVMStarted: {
@ -802,16 +826,13 @@ func resourceVirtualEnvironmentVM() *schema.Resource {
Description: "The VGA configuration", Description: "The VGA configuration",
Optional: true, Optional: true,
DefaultFunc: func() (interface{}, error) { DefaultFunc: func() (interface{}, error) {
defaultList := make([]interface{}, 1) return []interface{}{
defaultMap := map[string]interface{}{} map[string]interface{}{
mkResourceVirtualEnvironmentVMVGAEnabled: dvResourceVirtualEnvironmentVMVGAEnabled,
defaultMap[mkResourceVirtualEnvironmentVMVGAEnabled] = dvResourceVirtualEnvironmentVMVGAEnabled mkResourceVirtualEnvironmentVMVGAMemory: dvResourceVirtualEnvironmentVMVGAMemory,
defaultMap[mkResourceVirtualEnvironmentVMVGAMemory] = dvResourceVirtualEnvironmentVMVGAMemory mkResourceVirtualEnvironmentVMVGAType: dvResourceVirtualEnvironmentVMVGAType,
defaultMap[mkResourceVirtualEnvironmentVMVGAType] = dvResourceVirtualEnvironmentVMVGAType },
}, nil
defaultList[0] = defaultMap
return defaultList, nil
}, },
Elem: &schema.Resource{ Elem: &schema.Resource{
Schema: map[string]*schema.Schema{ Schema: map[string]*schema.Schema{
@ -878,6 +899,12 @@ func resourceVirtualEnvironmentVMCreate(d *schema.ResourceData, m interface{}) e
agentTrim := proxmox.CustomBool(agentBlock[mkResourceVirtualEnvironmentVMAgentTrim].(bool)) agentTrim := proxmox.CustomBool(agentBlock[mkResourceVirtualEnvironmentVMAgentTrim].(bool))
agentType := agentBlock[mkResourceVirtualEnvironmentVMAgentType].(string) agentType := agentBlock[mkResourceVirtualEnvironmentVMAgentType].(string)
audioDevices, err := resourceVirtualEnvironmentVMGetAudioDeviceList(d, m)
if err != nil {
return err
}
bios := d.Get(mkResourceVirtualEnvironmentVMBIOS).(string) bios := d.Get(mkResourceVirtualEnvironmentVMBIOS).(string)
cdromBlock, err := getSchemaBlock(resource, d, m, []string{mkResourceVirtualEnvironmentVMCDROM}, 0, true) cdromBlock, err := getSchemaBlock(resource, d, m, []string{mkResourceVirtualEnvironmentVMCDROM}, 0, true)
@ -1030,6 +1057,7 @@ func resourceVirtualEnvironmentVMCreate(d *schema.ResourceData, m interface{}) e
TrimClonedDisks: &agentTrim, TrimClonedDisks: &agentTrim,
Type: &agentType, Type: &agentType,
}, },
AudioDevices: audioDevices,
BIOS: &bios, BIOS: &bios,
BootDisk: &bootDisk, BootDisk: &bootDisk,
BootOrder: &bootOrder, BootOrder: &bootOrder,
@ -1347,6 +1375,39 @@ func resourceVirtualEnvironmentVMGetCloudInitConfig(d *schema.ResourceData, m in
return initializationConfig, nil return initializationConfig, nil
} }
func resourceVirtualEnvironmentVMGetAudioDeviceList(d *schema.ResourceData, m interface{}) (proxmox.CustomAudioDevices, error) {
devices := d.Get(mkResourceVirtualEnvironmentVMAudioDevice).([]interface{})
list := make(proxmox.CustomAudioDevices, len(devices))
for i, v := range devices {
block := v.(map[string]interface{})
device, _ := block[mkResourceVirtualEnvironmentVMAudioDeviceDevice].(string)
driver, _ := block[mkResourceVirtualEnvironmentVMAudioDeviceDriver].(string)
enabled, _ := block[mkResourceVirtualEnvironmentVMAudioDeviceEnabled].(bool)
list[i].Device = device
list[i].Driver = &driver
list[i].Enabled = enabled
}
return list, nil
}
func resourceVirtualEnvironmentVMGetAudioDeviceValidator() schema.SchemaValidateFunc {
return validation.StringInSlice([]string{
"AC97",
"ich9-intel-hda",
"intel-hda",
}, false)
}
func resourceVirtualEnvironmentVMGetAudioDriverValidator() schema.SchemaValidateFunc {
return validation.StringInSlice([]string{
"spice",
}, false)
}
func resourceVirtualEnvironmentVMGetCPUArchitectureValidator() schema.SchemaValidateFunc { func resourceVirtualEnvironmentVMGetCPUArchitectureValidator() schema.SchemaValidateFunc {
return validation.StringInSlice([]string{ return validation.StringInSlice([]string{
"aarch64", "aarch64",
@ -1630,6 +1691,39 @@ func resourceVirtualEnvironmentVMRead(d *schema.ResourceData, m interface{}) err
d.Set(mkResourceVirtualEnvironmentVMAgent, []interface{}{}) d.Set(mkResourceVirtualEnvironmentVMAgent, []interface{}{})
} }
// Compare the audio devices to those stored in the state.
audioDevices := make([]interface{}, 1)
audioDevicesArray := []*proxmox.CustomAudioDevice{
vmConfig.AudioDevice,
}
audioDevicesCount := 0
for adi, ad := range audioDevicesArray {
m := map[string]interface{}{}
if ad != nil {
m[mkResourceVirtualEnvironmentVMAudioDeviceDevice] = ad.Device
if ad.Driver != nil {
m[mkResourceVirtualEnvironmentVMAudioDeviceDriver] = *ad.Driver
} else {
m[mkResourceVirtualEnvironmentVMAudioDeviceDriver] = ""
}
m[mkResourceVirtualEnvironmentVMAudioDeviceEnabled] = true
audioDevicesCount = adi + 1
} else {
m[mkResourceVirtualEnvironmentVMAudioDeviceDevice] = ""
m[mkResourceVirtualEnvironmentVMAudioDeviceDriver] = ""
m[mkResourceVirtualEnvironmentVMAudioDeviceEnabled] = false
}
audioDevices[adi] = m
}
d.Set(mkResourceVirtualEnvironmentVMAudioDevice, audioDevices[:audioDevicesCount])
// Compare the IDE devices to the CDROM and cloud-init configurations stored in the state. // Compare the IDE devices to the CDROM and cloud-init configurations stored in the state.
if vmConfig.IDEDevice2 != nil { if vmConfig.IDEDevice2 != nil {
if *vmConfig.IDEDevice2.Media == "cdrom" { if *vmConfig.IDEDevice2.Media == "cdrom" {
@ -2307,6 +2401,27 @@ func resourceVirtualEnvironmentVMUpdate(d *schema.ResourceData, m interface{}) e
rebootRequired = true rebootRequired = true
} }
// Prepare the new audio devices.
if d.HasChange(mkResourceVirtualEnvironmentVMAudioDevice) {
body.AudioDevices, err = resourceVirtualEnvironmentVMGetAudioDeviceList(d, m)
if err != nil {
return err
}
for i := 0; i < len(body.AudioDevices); i++ {
if !body.AudioDevices[i].Enabled {
delete = append(delete, fmt.Sprintf("audio%d", i))
}
}
for i := len(body.AudioDevices); i < maxAudioDevices; i++ {
delete = append(delete, fmt.Sprintf("audio%d", i))
}
rebootRequired = true
}
// Prepare the new CDROM configuration. // Prepare the new CDROM configuration.
if d.HasChange(mkResourceVirtualEnvironmentVMCDROM) { if d.HasChange(mkResourceVirtualEnvironmentVMCDROM) {
cdromBlock, err := getSchemaBlock(resource, d, m, []string{mkResourceVirtualEnvironmentVMCDROM}, 0, true) cdromBlock, err := getSchemaBlock(resource, d, m, []string{mkResourceVirtualEnvironmentVMCDROM}, 0, true)
@ -2478,6 +2593,16 @@ func resourceVirtualEnvironmentVMUpdate(d *schema.ResourceData, m interface{}) e
return err return err
} }
for i := 0; i < len(body.NetworkDevices); i++ {
if !body.NetworkDevices[i].Enabled {
delete = append(delete, fmt.Sprintf("net%d", i))
}
}
for i := len(body.NetworkDevices); i < maxNetworkDevices; i++ {
delete = append(delete, fmt.Sprintf("net%d", i))
}
rebootRequired = true rebootRequired = true
} }
@ -2504,6 +2629,10 @@ func resourceVirtualEnvironmentVMUpdate(d *schema.ResourceData, m interface{}) e
return err return err
} }
for i := len(body.SerialDevices); i < maxSerialDevices; i++ {
delete = append(delete, fmt.Sprintf("serial%d", i))
}
rebootRequired = true rebootRequired = true
} }

View File

@ -29,6 +29,8 @@ func TestResourceVirtualEnvironmentVMSchema(t *testing.T) {
testOptionalArguments(t, s, []string{ testOptionalArguments(t, s, []string{
mkResourceVirtualEnvironmentVMACPI, mkResourceVirtualEnvironmentVMACPI,
mkResourceVirtualEnvironmentVMAgent,
mkResourceVirtualEnvironmentVMAudioDevice,
mkResourceVirtualEnvironmentVMBIOS, mkResourceVirtualEnvironmentVMBIOS,
mkResourceVirtualEnvironmentVMCDROM, mkResourceVirtualEnvironmentVMCDROM,
mkResourceVirtualEnvironmentVMInitialization, mkResourceVirtualEnvironmentVMInitialization,
@ -57,6 +59,7 @@ func TestResourceVirtualEnvironmentVMSchema(t *testing.T) {
testSchemaValueTypes(t, s, []string{ testSchemaValueTypes(t, s, []string{
mkResourceVirtualEnvironmentVMACPI, mkResourceVirtualEnvironmentVMACPI,
mkResourceVirtualEnvironmentVMAgent, mkResourceVirtualEnvironmentVMAgent,
mkResourceVirtualEnvironmentVMAudioDevice,
mkResourceVirtualEnvironmentVMBIOS, mkResourceVirtualEnvironmentVMBIOS,
mkResourceVirtualEnvironmentVMCDROM, mkResourceVirtualEnvironmentVMCDROM,
mkResourceVirtualEnvironmentVMInitialization, mkResourceVirtualEnvironmentVMInitialization,
@ -80,6 +83,7 @@ func TestResourceVirtualEnvironmentVMSchema(t *testing.T) {
}, []schema.ValueType{ }, []schema.ValueType{
schema.TypeBool, schema.TypeBool,
schema.TypeList, schema.TypeList,
schema.TypeList,
schema.TypeString, schema.TypeString,
schema.TypeList, schema.TypeList,
schema.TypeList, schema.TypeList,
@ -120,6 +124,21 @@ func TestResourceVirtualEnvironmentVMSchema(t *testing.T) {
schema.TypeString, schema.TypeString,
}) })
audioDeviceSchema := testNestedSchemaExistence(t, s, mkResourceVirtualEnvironmentVMAudioDevice)
testOptionalArguments(t, audioDeviceSchema, []string{
mkResourceVirtualEnvironmentVMAudioDeviceDevice,
mkResourceVirtualEnvironmentVMAudioDeviceDriver,
})
testSchemaValueTypes(t, audioDeviceSchema, []string{
mkResourceVirtualEnvironmentVMAudioDeviceDevice,
mkResourceVirtualEnvironmentVMAudioDeviceDriver,
}, []schema.ValueType{
schema.TypeString,
schema.TypeString,
})
cdromSchema := testNestedSchemaExistence(t, s, mkResourceVirtualEnvironmentVMCDROM) cdromSchema := testNestedSchemaExistence(t, s, mkResourceVirtualEnvironmentVMCDROM)
testOptionalArguments(t, cdromSchema, []string{ testOptionalArguments(t, cdromSchema, []string{