0
0
mirror of https://github.com/bpg/terraform-provider-proxmox.git synced 2025-07-01 11:02:59 +00:00

Initial speed limit support for disk devices

This commit is contained in:
Dan Petersen 2019-12-27 23:13:37 +01:00
parent f69339966a
commit 40084fa433
4 changed files with 142 additions and 14 deletions

View File

@ -347,6 +347,9 @@ This resource doesn't expose any additional attributes.
* `file_format` - (Optional) The file format (defaults to `qcow2`)
* `file_id` - (Optional) The file ID for a disk image
* `size` - (Optional) The disk size in gigabytes (defaults to `8`)
* `speed` - (Optional) The speed limits
* `read` - (Optional) The maximum read speed in megabytes per second
* `write` - (Optional) The maximum write speed in megabytes per second
* `keyboard_layout` - (Optional) The keyboard layout (defaults to `en-us`)
* `memory` - (Optional) The memory configuration
* `dedicated` - (Optional) The dedicated memory in megabytes (defaults to `512`)

View File

@ -138,11 +138,13 @@ type CustomStartupOrder struct {
// CustomStorageDevice handles QEMU SATA device parameters.
type CustomStorageDevice struct {
AIO *string `json:"aio,omitempty" url:"aio,omitempty"`
BackupEnabled *CustomBool `json:"backup,omitempty" url:"backup,omitempty,int"`
Enabled bool `json:"-" url:"-"`
FileVolume string `json:"file" url:"file"`
Media *string `json:"media,omitempty" url:"media,omitempty"`
AIO *string `json:"aio,omitempty" url:"aio,omitempty"`
BackupEnabled *CustomBool `json:"backup,omitempty" url:"backup,omitempty,int"`
Enabled bool `json:"-" url:"-"`
FileVolume string `json:"file" url:"file"`
MaxReadSpeedMbps *int `json:"mbps_rd,omitempty" url:"mbps_rd,omitempty"`
MaxWriteSpeedMbps *int `json:"mbps_wr,omitempty" url:"mbps_wr,omitempty"`
Media *string `json:"media,omitempty" url:"media,omitempty"`
}
// CustomStorageDevices handles QEMU SATA device parameters.
@ -787,6 +789,14 @@ func (r CustomStorageDevice) EncodeValues(key string, v *url.Values) error {
}
}
if r.MaxReadSpeedMbps != nil {
values = append(values, fmt.Sprintf("mbps_rd=%d", *r.MaxReadSpeedMbps))
}
if r.MaxWriteSpeedMbps != nil {
values = append(values, fmt.Sprintf("mbps_wr=%d", *r.MaxWriteSpeedMbps))
}
if r.Media != nil {
values = append(values, fmt.Sprintf("media=%s", *r.Media))
}

View File

@ -32,6 +32,8 @@ const (
dvResourceVirtualEnvironmentVMDiskFileFormat = "qcow2"
dvResourceVirtualEnvironmentVMDiskFileID = ""
dvResourceVirtualEnvironmentVMDiskSize = 8
dvResourceVirtualEnvironmentVMDiskSpeedRead = 0
dvResourceVirtualEnvironmentVMDiskSpeedWrite = 0
dvResourceVirtualEnvironmentVMKeyboardLayout = "en-us"
dvResourceVirtualEnvironmentVMMemoryDedicated = 512
dvResourceVirtualEnvironmentVMMemoryFloating = 0
@ -79,6 +81,9 @@ const (
mkResourceVirtualEnvironmentVMDiskFileFormat = "file_format"
mkResourceVirtualEnvironmentVMDiskFileID = "file_id"
mkResourceVirtualEnvironmentVMDiskSize = "size"
mkResourceVirtualEnvironmentVMDiskSpeed = "speed"
mkResourceVirtualEnvironmentVMDiskSpeedRead = "read"
mkResourceVirtualEnvironmentVMDiskSpeedWrite = "write"
mkResourceVirtualEnvironmentVMKeyboardLayout = "keyboard_layout"
mkResourceVirtualEnvironmentVMMemory = "memory"
mkResourceVirtualEnvironmentVMMemoryDedicated = "dedicated"
@ -416,6 +421,40 @@ func resourceVirtualEnvironmentVM() *schema.Resource {
Default: dvResourceVirtualEnvironmentVMDiskSize,
ValidateFunc: validation.IntBetween(1, 8192),
},
mkResourceVirtualEnvironmentVMDiskSpeed: {
Type: schema.TypeList,
Description: "The speed limits",
Optional: true,
DefaultFunc: func() (interface{}, error) {
defaultList := make([]interface{}, 1)
defaultMap := make(map[string]interface{})
defaultMap[mkResourceVirtualEnvironmentVMDiskSpeedRead] = dvResourceVirtualEnvironmentVMDiskSpeedRead
defaultMap[mkResourceVirtualEnvironmentVMDiskSpeedWrite] = dvResourceVirtualEnvironmentVMDiskSpeedWrite
defaultList[0] = defaultMap
return defaultList, nil
},
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
mkResourceVirtualEnvironmentVMDiskSpeedRead: {
Type: schema.TypeInt,
Optional: true,
Description: "The maximum read speed in megabytes per second",
Default: dvResourceVirtualEnvironmentVMDiskSpeedRead,
},
mkResourceVirtualEnvironmentVMDiskSpeedWrite: {
Type: schema.TypeInt,
Optional: true,
Description: "The maximum write speed in megabytes per second",
Default: dvResourceVirtualEnvironmentVMDiskSpeedRead,
},
},
},
MaxItems: 1,
MinItems: 0,
},
},
},
MaxItems: 14,
@ -567,11 +606,11 @@ func resourceVirtualEnvironmentVMCreate(d *schema.ResourceData, m interface{}) e
return err
}
schema := resourceVirtualEnvironmentVM().Schema
resourceSchema := resourceVirtualEnvironmentVM().Schema
agent := d.Get(mkResourceVirtualEnvironmentVMAgent).([]interface{})
if len(agent) == 0 {
agentDefault, err := schema[mkResourceVirtualEnvironmentVMAgent].DefaultValue()
agentDefault, err := resourceSchema[mkResourceVirtualEnvironmentVMAgent].DefaultValue()
if err != nil {
return err
@ -588,7 +627,7 @@ func resourceVirtualEnvironmentVMCreate(d *schema.ResourceData, m interface{}) e
cdrom := d.Get(mkResourceVirtualEnvironmentVMCDROM).([]interface{})
if len(cdrom) == 0 {
cdromDefault, err := schema[mkResourceVirtualEnvironmentVMCDROM].DefaultValue()
cdromDefault, err := resourceSchema[mkResourceVirtualEnvironmentVMCDROM].DefaultValue()
if err != nil {
return err
@ -703,7 +742,7 @@ func resourceVirtualEnvironmentVMCreate(d *schema.ResourceData, m interface{}) e
cpu := d.Get(mkResourceVirtualEnvironmentVMCPU).([]interface{})
if len(cpu) == 0 {
cpuDefault, err := schema[mkResourceVirtualEnvironmentVMCPU].DefaultValue()
cpuDefault, err := resourceSchema[mkResourceVirtualEnvironmentVMCPU].DefaultValue()
if err != nil {
return err
@ -721,6 +760,10 @@ func resourceVirtualEnvironmentVMCreate(d *schema.ResourceData, m interface{}) e
disk := d.Get(mkResourceVirtualEnvironmentVMDisk).([]interface{})
scsiDevices := make(proxmox.CustomStorageDevices, len(disk))
diskSchemaElem := resourceSchema[mkResourceVirtualEnvironmentVMDisk].Elem
diskSchemaResource := diskSchemaElem.(*schema.Resource)
diskSpeedResource := diskSchemaResource.Schema[mkResourceVirtualEnvironmentVMDiskSpeed]
for i, d := range disk {
block := d.(map[string]interface{})
@ -728,11 +771,34 @@ func resourceVirtualEnvironmentVMCreate(d *schema.ResourceData, m interface{}) e
enabled, _ := block[mkResourceVirtualEnvironmentVMDiskEnabled].(bool)
fileID, _ := block[mkResourceVirtualEnvironmentVMDiskFileID].(string)
size, _ := block[mkResourceVirtualEnvironmentVMDiskSize].(int)
speed := block[mkResourceVirtualEnvironmentVMDiskSpeed].([]interface{})
if len(speed) == 0 {
diskSpeedDefault, err := diskSpeedResource.DefaultValue()
if err != nil {
return err
}
speed = diskSpeedDefault.([]interface{})
}
speedBlock := speed[0].(map[string]interface{})
speedLimitRead := speedBlock[mkResourceVirtualEnvironmentVMDiskSpeedRead].(int)
speedLimitWrite := speedBlock[mkResourceVirtualEnvironmentVMDiskSpeedWrite].(int)
diskDevice := proxmox.CustomStorageDevice{
Enabled: enabled,
}
if speedLimitRead > 0 {
diskDevice.MaxReadSpeedMbps = &speedLimitRead
}
if speedLimitWrite > 0 {
diskDevice.MaxWriteSpeedMbps = &speedLimitWrite
}
if fileID != "" {
diskDevice.Enabled = false
} else {
@ -746,7 +812,7 @@ func resourceVirtualEnvironmentVMCreate(d *schema.ResourceData, m interface{}) e
memory := d.Get(mkResourceVirtualEnvironmentVMMemory).([]interface{})
if len(memory) == 0 {
memoryDefault, err := schema[mkResourceVirtualEnvironmentVMMemory].DefaultValue()
memoryDefault, err := resourceSchema[mkResourceVirtualEnvironmentVMMemory].DefaultValue()
if err != nil {
return err
@ -842,6 +908,7 @@ func resourceVirtualEnvironmentVMCreate(d *schema.ResourceData, m interface{}) e
}
scsiHardware := "virtio-scsi-pci"
startOnBoot := proxmox.CustomBool(true)
tabletDeviceEnabled := proxmox.CustomBool(true)
body := &proxmox.VirtualEnvironmentVMCreateRequestBody{
@ -865,6 +932,7 @@ func resourceVirtualEnvironmentVMCreate(d *schema.ResourceData, m interface{}) e
SCSIHardware: &scsiHardware,
SerialDevices: []string{"socket"},
SharedMemory: memorySharedObject,
StartOnBoot: &startOnBoot,
TabletDeviceEnabled: &tabletDeviceEnabled,
VMID: &vmID,
}
@ -926,22 +994,54 @@ func resourceVirtualEnvironmentVMCreateImportedDisks(d *schema.ResourceData, m i
}
}
// Retrieve some information about the disk schema.
resourceSchema := resourceVirtualEnvironmentVM().Schema
diskSchemaElem := resourceSchema[mkResourceVirtualEnvironmentVMDisk].Elem
diskSchemaResource := diskSchemaElem.(*schema.Resource)
diskSpeedResource := diskSchemaResource.Schema[mkResourceVirtualEnvironmentVMDiskSpeed]
// Generate the commands required to import the specified disks.
importedDiskCount := 0
for i, d := range disk {
block := d.(map[string]interface{})
datastoreID, _ := block[mkResourceVirtualEnvironmentVMDiskDatastoreID].(string)
enabled, _ := block[mkResourceVirtualEnvironmentVMDiskEnabled].(bool)
fileFormat, _ := block[mkResourceVirtualEnvironmentVMDiskFileFormat].(string)
fileID, _ := block[mkResourceVirtualEnvironmentVMDiskFileID].(string)
size, _ := block[mkResourceVirtualEnvironmentVMDiskSize].(int)
if !enabled || fileID == "" {
continue
}
datastoreID, _ := block[mkResourceVirtualEnvironmentVMDiskDatastoreID].(string)
fileFormat, _ := block[mkResourceVirtualEnvironmentVMDiskFileFormat].(string)
size, _ := block[mkResourceVirtualEnvironmentVMDiskSize].(int)
speed := block[mkResourceVirtualEnvironmentVMDiskSpeed].([]interface{})
if len(speed) == 0 {
diskSpeedDefault, err := diskSpeedResource.DefaultValue()
if err != nil {
return err
}
speed = diskSpeedDefault.([]interface{})
}
speedBlock := speed[0].(map[string]interface{})
speedLimitRead := speedBlock[mkResourceVirtualEnvironmentVMDiskSpeedRead].(int)
speedLimitWrite := speedBlock[mkResourceVirtualEnvironmentVMDiskSpeedWrite].(int)
diskOptions := ""
if speedLimitRead > 0 {
diskOptions += fmt.Sprintf(",mbps_rd=%d", speedLimitRead)
}
if speedLimitWrite > 0 {
diskOptions += fmt.Sprintf(",mbps_wr=%d", speedLimitWrite)
}
fileIDParts := strings.Split(fileID, ":")
filePath := fmt.Sprintf("/var/lib/vz/template/%s", fileIDParts[1])
filePathTmp := fmt.Sprintf("/tmp/vm-%d-disk-%d.%s", vmID, diskCount+importedDiskCount, fileFormat)
@ -951,7 +1051,7 @@ func resourceVirtualEnvironmentVMCreateImportedDisks(d *schema.ResourceData, m i
fmt.Sprintf("cp %s %s", filePath, filePathTmp),
fmt.Sprintf("qemu-img resize %s %dG", filePathTmp, size),
fmt.Sprintf("qm importdisk %d %s %s -format qcow2", vmID, filePathTmp, datastoreID),
fmt.Sprintf("qm set %d --scsi%d %s:vm-%d-disk-%d", vmID, i, datastoreID, vmID, diskCount+importedDiskCount),
fmt.Sprintf("qm set %d -scsi%d %s:vm-%d-disk-%d%s", vmID, i, datastoreID, vmID, diskCount+importedDiskCount, diskOptions),
fmt.Sprintf("rm -f %s", filePathTmp),
)

View File

@ -247,6 +247,21 @@ func TestResourceVirtualEnvironmentVMSchema(t *testing.T) {
schema.TypeInt,
})
diskSpeedSchema := testNestedSchemaExistence(t, diskSchema, mkResourceVirtualEnvironmentVMDiskSpeed)
testOptionalArguments(t, diskSpeedSchema, []string{
mkResourceVirtualEnvironmentVMDiskSpeedRead,
mkResourceVirtualEnvironmentVMDiskSpeedWrite,
})
testSchemaValueTypes(t, diskSpeedSchema, []string{
mkResourceVirtualEnvironmentVMDiskSpeedRead,
mkResourceVirtualEnvironmentVMDiskSpeedWrite,
}, []schema.ValueType{
schema.TypeInt,
schema.TypeInt,
})
memorySchema := testNestedSchemaExistence(t, s, mkResourceVirtualEnvironmentVMMemory)
testOptionalArguments(t, memorySchema, []string{