0
0
mirror of https://github.com/bpg/terraform-provider-proxmox.git synced 2025-08-23 03:48:35 +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:
* resource/virtual_environment_vm: Add `audio_device` argument
* resource/virtual_environment_vm: Add `serial_device` argument
BUG FIXES:
* resource/virtual_environment_vm: Fix `network_device` deletion issue
## 0.2.0
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`)
* `isa` - ISA Serial Port
* `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`)
* `ovmf` - OVMF (UEFI)
* `seabios` - SeaBIOS

View File

@ -22,10 +22,14 @@ type CustomAgent struct {
// CustomAudioDevice handles QEMU audio parameters.
type CustomAudioDevice struct {
Device string `json:"device" url:"device"`
Driver string `json:"driver" url:"driver"`
Device string `json:"device" url:"device"`
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.
type CustomCloudInitConfig struct {
Files *CustomCloudInitFiles `json:"cicustom,omitempty" url:"cicustom,omitempty"`
@ -200,7 +204,7 @@ type VirtualEnvironmentVMCreateRequestBody struct {
ACPI *CustomBool `json:"acpi,omitempty" url:"acpi,omitempty,int"`
Agent *CustomAgent `json:"agent,omitempty" url:"agent,omitempty"`
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"`
BackupFile *string `json:"archive,omitempty" url:"archive,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.
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
}
@ -1088,6 +1109,34 @@ func (r *CustomAgent) UnmarshalJSON(b []byte) error {
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.
func (r *CustomCloudInitFiles) UnmarshalJSON(b []byte) error {
var s string

View File

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

View File

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

View File

@ -29,6 +29,8 @@ func TestResourceVirtualEnvironmentVMSchema(t *testing.T) {
testOptionalArguments(t, s, []string{
mkResourceVirtualEnvironmentVMACPI,
mkResourceVirtualEnvironmentVMAgent,
mkResourceVirtualEnvironmentVMAudioDevice,
mkResourceVirtualEnvironmentVMBIOS,
mkResourceVirtualEnvironmentVMCDROM,
mkResourceVirtualEnvironmentVMInitialization,
@ -57,6 +59,7 @@ func TestResourceVirtualEnvironmentVMSchema(t *testing.T) {
testSchemaValueTypes(t, s, []string{
mkResourceVirtualEnvironmentVMACPI,
mkResourceVirtualEnvironmentVMAgent,
mkResourceVirtualEnvironmentVMAudioDevice,
mkResourceVirtualEnvironmentVMBIOS,
mkResourceVirtualEnvironmentVMCDROM,
mkResourceVirtualEnvironmentVMInitialization,
@ -80,6 +83,7 @@ func TestResourceVirtualEnvironmentVMSchema(t *testing.T) {
}, []schema.ValueType{
schema.TypeBool,
schema.TypeList,
schema.TypeList,
schema.TypeString,
schema.TypeList,
schema.TypeList,
@ -120,6 +124,21 @@ func TestResourceVirtualEnvironmentVMSchema(t *testing.T) {
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)
testOptionalArguments(t, cdromSchema, []string{