mirror of
https://github.com/bpg/terraform-provider-proxmox.git
synced 2025-07-04 12:32:59 +00:00
Initial speed limit support for disk devices
This commit is contained in:
parent
f69339966a
commit
40084fa433
@ -347,6 +347,9 @@ This resource doesn't expose any additional attributes.
|
|||||||
* `file_format` - (Optional) The file format (defaults to `qcow2`)
|
* `file_format` - (Optional) The file format (defaults to `qcow2`)
|
||||||
* `file_id` - (Optional) The file ID for a disk image
|
* `file_id` - (Optional) The file ID for a disk image
|
||||||
* `size` - (Optional) The disk size in gigabytes (defaults to `8`)
|
* `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`)
|
* `keyboard_layout` - (Optional) The keyboard layout (defaults to `en-us`)
|
||||||
* `memory` - (Optional) The memory configuration
|
* `memory` - (Optional) The memory configuration
|
||||||
* `dedicated` - (Optional) The dedicated memory in megabytes (defaults to `512`)
|
* `dedicated` - (Optional) The dedicated memory in megabytes (defaults to `512`)
|
||||||
|
@ -138,11 +138,13 @@ type CustomStartupOrder struct {
|
|||||||
|
|
||||||
// CustomStorageDevice handles QEMU SATA device parameters.
|
// CustomStorageDevice handles QEMU SATA device parameters.
|
||||||
type CustomStorageDevice struct {
|
type CustomStorageDevice struct {
|
||||||
AIO *string `json:"aio,omitempty" url:"aio,omitempty"`
|
AIO *string `json:"aio,omitempty" url:"aio,omitempty"`
|
||||||
BackupEnabled *CustomBool `json:"backup,omitempty" url:"backup,omitempty,int"`
|
BackupEnabled *CustomBool `json:"backup,omitempty" url:"backup,omitempty,int"`
|
||||||
Enabled bool `json:"-" url:"-"`
|
Enabled bool `json:"-" url:"-"`
|
||||||
FileVolume string `json:"file" url:"file"`
|
FileVolume string `json:"file" url:"file"`
|
||||||
Media *string `json:"media,omitempty" url:"media,omitempty"`
|
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.
|
// 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 {
|
if r.Media != nil {
|
||||||
values = append(values, fmt.Sprintf("media=%s", *r.Media))
|
values = append(values, fmt.Sprintf("media=%s", *r.Media))
|
||||||
}
|
}
|
||||||
|
@ -32,6 +32,8 @@ const (
|
|||||||
dvResourceVirtualEnvironmentVMDiskFileFormat = "qcow2"
|
dvResourceVirtualEnvironmentVMDiskFileFormat = "qcow2"
|
||||||
dvResourceVirtualEnvironmentVMDiskFileID = ""
|
dvResourceVirtualEnvironmentVMDiskFileID = ""
|
||||||
dvResourceVirtualEnvironmentVMDiskSize = 8
|
dvResourceVirtualEnvironmentVMDiskSize = 8
|
||||||
|
dvResourceVirtualEnvironmentVMDiskSpeedRead = 0
|
||||||
|
dvResourceVirtualEnvironmentVMDiskSpeedWrite = 0
|
||||||
dvResourceVirtualEnvironmentVMKeyboardLayout = "en-us"
|
dvResourceVirtualEnvironmentVMKeyboardLayout = "en-us"
|
||||||
dvResourceVirtualEnvironmentVMMemoryDedicated = 512
|
dvResourceVirtualEnvironmentVMMemoryDedicated = 512
|
||||||
dvResourceVirtualEnvironmentVMMemoryFloating = 0
|
dvResourceVirtualEnvironmentVMMemoryFloating = 0
|
||||||
@ -79,6 +81,9 @@ const (
|
|||||||
mkResourceVirtualEnvironmentVMDiskFileFormat = "file_format"
|
mkResourceVirtualEnvironmentVMDiskFileFormat = "file_format"
|
||||||
mkResourceVirtualEnvironmentVMDiskFileID = "file_id"
|
mkResourceVirtualEnvironmentVMDiskFileID = "file_id"
|
||||||
mkResourceVirtualEnvironmentVMDiskSize = "size"
|
mkResourceVirtualEnvironmentVMDiskSize = "size"
|
||||||
|
mkResourceVirtualEnvironmentVMDiskSpeed = "speed"
|
||||||
|
mkResourceVirtualEnvironmentVMDiskSpeedRead = "read"
|
||||||
|
mkResourceVirtualEnvironmentVMDiskSpeedWrite = "write"
|
||||||
mkResourceVirtualEnvironmentVMKeyboardLayout = "keyboard_layout"
|
mkResourceVirtualEnvironmentVMKeyboardLayout = "keyboard_layout"
|
||||||
mkResourceVirtualEnvironmentVMMemory = "memory"
|
mkResourceVirtualEnvironmentVMMemory = "memory"
|
||||||
mkResourceVirtualEnvironmentVMMemoryDedicated = "dedicated"
|
mkResourceVirtualEnvironmentVMMemoryDedicated = "dedicated"
|
||||||
@ -416,6 +421,40 @@ func resourceVirtualEnvironmentVM() *schema.Resource {
|
|||||||
Default: dvResourceVirtualEnvironmentVMDiskSize,
|
Default: dvResourceVirtualEnvironmentVMDiskSize,
|
||||||
ValidateFunc: validation.IntBetween(1, 8192),
|
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,
|
MaxItems: 14,
|
||||||
@ -567,11 +606,11 @@ func resourceVirtualEnvironmentVMCreate(d *schema.ResourceData, m interface{}) e
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
schema := resourceVirtualEnvironmentVM().Schema
|
resourceSchema := resourceVirtualEnvironmentVM().Schema
|
||||||
agent := d.Get(mkResourceVirtualEnvironmentVMAgent).([]interface{})
|
agent := d.Get(mkResourceVirtualEnvironmentVMAgent).([]interface{})
|
||||||
|
|
||||||
if len(agent) == 0 {
|
if len(agent) == 0 {
|
||||||
agentDefault, err := schema[mkResourceVirtualEnvironmentVMAgent].DefaultValue()
|
agentDefault, err := resourceSchema[mkResourceVirtualEnvironmentVMAgent].DefaultValue()
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -588,7 +627,7 @@ func resourceVirtualEnvironmentVMCreate(d *schema.ResourceData, m interface{}) e
|
|||||||
cdrom := d.Get(mkResourceVirtualEnvironmentVMCDROM).([]interface{})
|
cdrom := d.Get(mkResourceVirtualEnvironmentVMCDROM).([]interface{})
|
||||||
|
|
||||||
if len(cdrom) == 0 {
|
if len(cdrom) == 0 {
|
||||||
cdromDefault, err := schema[mkResourceVirtualEnvironmentVMCDROM].DefaultValue()
|
cdromDefault, err := resourceSchema[mkResourceVirtualEnvironmentVMCDROM].DefaultValue()
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -703,7 +742,7 @@ func resourceVirtualEnvironmentVMCreate(d *schema.ResourceData, m interface{}) e
|
|||||||
cpu := d.Get(mkResourceVirtualEnvironmentVMCPU).([]interface{})
|
cpu := d.Get(mkResourceVirtualEnvironmentVMCPU).([]interface{})
|
||||||
|
|
||||||
if len(cpu) == 0 {
|
if len(cpu) == 0 {
|
||||||
cpuDefault, err := schema[mkResourceVirtualEnvironmentVMCPU].DefaultValue()
|
cpuDefault, err := resourceSchema[mkResourceVirtualEnvironmentVMCPU].DefaultValue()
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -721,6 +760,10 @@ func resourceVirtualEnvironmentVMCreate(d *schema.ResourceData, m interface{}) e
|
|||||||
disk := d.Get(mkResourceVirtualEnvironmentVMDisk).([]interface{})
|
disk := d.Get(mkResourceVirtualEnvironmentVMDisk).([]interface{})
|
||||||
scsiDevices := make(proxmox.CustomStorageDevices, len(disk))
|
scsiDevices := make(proxmox.CustomStorageDevices, len(disk))
|
||||||
|
|
||||||
|
diskSchemaElem := resourceSchema[mkResourceVirtualEnvironmentVMDisk].Elem
|
||||||
|
diskSchemaResource := diskSchemaElem.(*schema.Resource)
|
||||||
|
diskSpeedResource := diskSchemaResource.Schema[mkResourceVirtualEnvironmentVMDiskSpeed]
|
||||||
|
|
||||||
for i, d := range disk {
|
for i, d := range disk {
|
||||||
block := d.(map[string]interface{})
|
block := d.(map[string]interface{})
|
||||||
|
|
||||||
@ -728,11 +771,34 @@ func resourceVirtualEnvironmentVMCreate(d *schema.ResourceData, m interface{}) e
|
|||||||
enabled, _ := block[mkResourceVirtualEnvironmentVMDiskEnabled].(bool)
|
enabled, _ := block[mkResourceVirtualEnvironmentVMDiskEnabled].(bool)
|
||||||
fileID, _ := block[mkResourceVirtualEnvironmentVMDiskFileID].(string)
|
fileID, _ := block[mkResourceVirtualEnvironmentVMDiskFileID].(string)
|
||||||
size, _ := block[mkResourceVirtualEnvironmentVMDiskSize].(int)
|
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{
|
diskDevice := proxmox.CustomStorageDevice{
|
||||||
Enabled: enabled,
|
Enabled: enabled,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if speedLimitRead > 0 {
|
||||||
|
diskDevice.MaxReadSpeedMbps = &speedLimitRead
|
||||||
|
}
|
||||||
|
|
||||||
|
if speedLimitWrite > 0 {
|
||||||
|
diskDevice.MaxWriteSpeedMbps = &speedLimitWrite
|
||||||
|
}
|
||||||
|
|
||||||
if fileID != "" {
|
if fileID != "" {
|
||||||
diskDevice.Enabled = false
|
diskDevice.Enabled = false
|
||||||
} else {
|
} else {
|
||||||
@ -746,7 +812,7 @@ func resourceVirtualEnvironmentVMCreate(d *schema.ResourceData, m interface{}) e
|
|||||||
memory := d.Get(mkResourceVirtualEnvironmentVMMemory).([]interface{})
|
memory := d.Get(mkResourceVirtualEnvironmentVMMemory).([]interface{})
|
||||||
|
|
||||||
if len(memory) == 0 {
|
if len(memory) == 0 {
|
||||||
memoryDefault, err := schema[mkResourceVirtualEnvironmentVMMemory].DefaultValue()
|
memoryDefault, err := resourceSchema[mkResourceVirtualEnvironmentVMMemory].DefaultValue()
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -842,6 +908,7 @@ func resourceVirtualEnvironmentVMCreate(d *schema.ResourceData, m interface{}) e
|
|||||||
}
|
}
|
||||||
|
|
||||||
scsiHardware := "virtio-scsi-pci"
|
scsiHardware := "virtio-scsi-pci"
|
||||||
|
startOnBoot := proxmox.CustomBool(true)
|
||||||
tabletDeviceEnabled := proxmox.CustomBool(true)
|
tabletDeviceEnabled := proxmox.CustomBool(true)
|
||||||
|
|
||||||
body := &proxmox.VirtualEnvironmentVMCreateRequestBody{
|
body := &proxmox.VirtualEnvironmentVMCreateRequestBody{
|
||||||
@ -865,6 +932,7 @@ func resourceVirtualEnvironmentVMCreate(d *schema.ResourceData, m interface{}) e
|
|||||||
SCSIHardware: &scsiHardware,
|
SCSIHardware: &scsiHardware,
|
||||||
SerialDevices: []string{"socket"},
|
SerialDevices: []string{"socket"},
|
||||||
SharedMemory: memorySharedObject,
|
SharedMemory: memorySharedObject,
|
||||||
|
StartOnBoot: &startOnBoot,
|
||||||
TabletDeviceEnabled: &tabletDeviceEnabled,
|
TabletDeviceEnabled: &tabletDeviceEnabled,
|
||||||
VMID: &vmID,
|
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.
|
// Generate the commands required to import the specified disks.
|
||||||
importedDiskCount := 0
|
importedDiskCount := 0
|
||||||
|
|
||||||
for i, d := range disk {
|
for i, d := range disk {
|
||||||
block := d.(map[string]interface{})
|
block := d.(map[string]interface{})
|
||||||
|
|
||||||
datastoreID, _ := block[mkResourceVirtualEnvironmentVMDiskDatastoreID].(string)
|
|
||||||
enabled, _ := block[mkResourceVirtualEnvironmentVMDiskEnabled].(bool)
|
enabled, _ := block[mkResourceVirtualEnvironmentVMDiskEnabled].(bool)
|
||||||
fileFormat, _ := block[mkResourceVirtualEnvironmentVMDiskFileFormat].(string)
|
|
||||||
fileID, _ := block[mkResourceVirtualEnvironmentVMDiskFileID].(string)
|
fileID, _ := block[mkResourceVirtualEnvironmentVMDiskFileID].(string)
|
||||||
size, _ := block[mkResourceVirtualEnvironmentVMDiskSize].(int)
|
|
||||||
|
|
||||||
if !enabled || fileID == "" {
|
if !enabled || fileID == "" {
|
||||||
continue
|
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, ":")
|
fileIDParts := strings.Split(fileID, ":")
|
||||||
filePath := fmt.Sprintf("/var/lib/vz/template/%s", fileIDParts[1])
|
filePath := fmt.Sprintf("/var/lib/vz/template/%s", fileIDParts[1])
|
||||||
filePathTmp := fmt.Sprintf("/tmp/vm-%d-disk-%d.%s", vmID, diskCount+importedDiskCount, fileFormat)
|
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("cp %s %s", filePath, filePathTmp),
|
||||||
fmt.Sprintf("qemu-img resize %s %dG", filePathTmp, size),
|
fmt.Sprintf("qemu-img resize %s %dG", filePathTmp, size),
|
||||||
fmt.Sprintf("qm importdisk %d %s %s -format qcow2", vmID, filePathTmp, datastoreID),
|
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),
|
fmt.Sprintf("rm -f %s", filePathTmp),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -247,6 +247,21 @@ func TestResourceVirtualEnvironmentVMSchema(t *testing.T) {
|
|||||||
schema.TypeInt,
|
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)
|
memorySchema := testNestedSchemaExistence(t, s, mkResourceVirtualEnvironmentVMMemory)
|
||||||
|
|
||||||
testOptionalArguments(t, memorySchema, []string{
|
testOptionalArguments(t, memorySchema, []string{
|
||||||
|
Loading…
Reference in New Issue
Block a user