mirror of
https://github.com/bpg/terraform-provider-proxmox.git
synced 2025-08-22 19:38:35 +00:00
feat(vm): add support for disk aio
, backup
, iops*
attributes (#1124)
* feat(vm): add support for disk `aio`, `backup`, `iops*` attributes Signed-off-by: Pavel Boldyrev <627562+bpg@users.noreply.github.com>
This commit is contained in:
parent
732f0188d7
commit
014b59e04f
2
.vscode/settings.json
vendored
2
.vscode/settings.json
vendored
@ -63,6 +63,8 @@
|
|||||||
"tfvars",
|
"tfvars",
|
||||||
"tpmstate",
|
"tpmstate",
|
||||||
"unmanaged",
|
"unmanaged",
|
||||||
|
"unthrottled",
|
||||||
|
"uring",
|
||||||
"usbdisk",
|
"usbdisk",
|
||||||
"vcpus",
|
"vcpus",
|
||||||
"virtio",
|
"virtio",
|
||||||
|
@ -233,6 +233,12 @@ output "ubuntu_vm_public_key" {
|
|||||||
- `units` - (Optional) The CPU units (defaults to `1024`).
|
- `units` - (Optional) The CPU units (defaults to `1024`).
|
||||||
- `description` - (Optional) The description.
|
- `description` - (Optional) The description.
|
||||||
- `disk` - (Optional) A disk (multiple blocks supported).
|
- `disk` - (Optional) A disk (multiple blocks supported).
|
||||||
|
- `aio` - (Optional) The disk AIO mode (defaults to `io_uring`).
|
||||||
|
- `io_uring` - Use io_uring.
|
||||||
|
- `native` - Use native AIO. Should be used with to unbuffered, O_DIRECT, raw block storage only,
|
||||||
|
with the disk `cache` must be set to `none`. Raw block storage types include iSCSI, CEPH/RBD, and NVMe.
|
||||||
|
- `threads` - Use thread-based AIO.
|
||||||
|
- `backup` - (Optional) Whether the drive should be included when making backups (defaults to `true`).
|
||||||
- `cache` - (Optional) The cache type (defaults to `none`).
|
- `cache` - (Optional) The cache type (defaults to `none`).
|
||||||
- `none` - No cache.
|
- `none` - No cache.
|
||||||
- `directsync` - Write to the host cache and wait for completion.
|
- `directsync` - Write to the host cache and wait for completion.
|
||||||
@ -263,8 +269,13 @@ output "ubuntu_vm_public_key" {
|
|||||||
the second, etc.
|
the second, etc.
|
||||||
- `iothread` - (Optional) Whether to use iothreads for this disk (defaults
|
- `iothread` - (Optional) Whether to use iothreads for this disk (defaults
|
||||||
to `false`).
|
to `false`).
|
||||||
|
- `replicate` - (Optional) Whether the drive should be considered for replication jobs (defaults to `true`).
|
||||||
- `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.
|
- `speed` - (Optional) The speed limits.
|
||||||
|
- `iops_read` - (Optional) The maximum read I/O in operations per second.
|
||||||
|
- `iops_read_burstable` - (Optional) The maximum unthrottled read I/O pool in operations per second.
|
||||||
|
- `iops_write` - (Optional) The maximum write I/O in operations per second.
|
||||||
|
- `iops_write_burstable` - (Optional) The maximum unthrottled write I/O pool in operations per second.
|
||||||
- `read` - (Optional) The maximum read speed in megabytes per second.
|
- `read` - (Optional) The maximum read speed in megabytes per second.
|
||||||
- `read_burstable` - (Optional) The maximum burstable read speed in
|
- `read_burstable` - (Optional) The maximum burstable read speed in
|
||||||
megabytes per second.
|
megabytes per second.
|
||||||
|
@ -181,8 +181,9 @@ func TestAccResourceVMDisks(t *testing.T) {
|
|||||||
name string
|
name string
|
||||||
steps []resource.TestStep
|
steps []resource.TestStep
|
||||||
}{
|
}{
|
||||||
{"create disk with default parameters", []resource.TestStep{{
|
{"create disk with default parameters, then update it", []resource.TestStep{
|
||||||
Config: providerConfig + `
|
{
|
||||||
|
Config: providerConfig + `
|
||||||
resource "proxmox_virtual_environment_vm" "test_disk1" {
|
resource "proxmox_virtual_environment_vm" "test_disk1" {
|
||||||
node_name = "pve"
|
node_name = "pve"
|
||||||
started = false
|
started = false
|
||||||
@ -196,21 +197,70 @@ func TestAccResourceVMDisks(t *testing.T) {
|
|||||||
size = 8
|
size = 8
|
||||||
}
|
}
|
||||||
}`,
|
}`,
|
||||||
Check: resource.ComposeTestCheckFunc(
|
Check: resource.ComposeTestCheckFunc(
|
||||||
testResourceAttributes("proxmox_virtual_environment_vm.test_disk1", map[string]string{
|
testResourceAttributes("proxmox_virtual_environment_vm.test_disk1", map[string]string{
|
||||||
"disk.0.cache": "none",
|
"disk.0.aio": "io_uring",
|
||||||
"disk.0.discard": "ignore",
|
"disk.0.backup": "true",
|
||||||
"disk.0.file_id": "",
|
"disk.0.cache": "none",
|
||||||
"disk.0.datastore_id": "local-lvm",
|
"disk.0.discard": "ignore",
|
||||||
"disk.0.file_format": "raw",
|
"disk.0.file_id": "",
|
||||||
"disk.0.interface": "virtio0",
|
"disk.0.datastore_id": "local-lvm",
|
||||||
"disk.0.iothread": "false",
|
"disk.0.file_format": "raw",
|
||||||
"disk.0.path_in_datastore": `vm-\d+-disk-\d+`,
|
"disk.0.interface": "virtio0",
|
||||||
"disk.0.size": "8",
|
"disk.0.iothread": "false",
|
||||||
"disk.0.ssd": "false",
|
"disk.0.path_in_datastore": `vm-\d+-disk-\d+`,
|
||||||
}),
|
"disk.0.replicate": "true",
|
||||||
),
|
"disk.0.size": "8",
|
||||||
}}},
|
"disk.0.ssd": "false",
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Config: providerConfig + `
|
||||||
|
resource "proxmox_virtual_environment_vm" "test_disk1" {
|
||||||
|
node_name = "pve"
|
||||||
|
started = false
|
||||||
|
name = "test-disk1"
|
||||||
|
|
||||||
|
disk {
|
||||||
|
// note: default qcow2 is not supported by lvm (?)
|
||||||
|
file_format = "raw"
|
||||||
|
datastore_id = "local-lvm"
|
||||||
|
interface = "virtio0"
|
||||||
|
size = 8
|
||||||
|
replicate = false
|
||||||
|
aio = "native"
|
||||||
|
speed {
|
||||||
|
iops_read = 100
|
||||||
|
iops_read_burstable = 1000
|
||||||
|
iops_write = 400
|
||||||
|
iops_write_burstable = 800
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}`,
|
||||||
|
Check: resource.ComposeTestCheckFunc(
|
||||||
|
testResourceAttributes("proxmox_virtual_environment_vm.test_disk1", map[string]string{
|
||||||
|
"disk.0.aio": "native",
|
||||||
|
"disk.0.backup": "true",
|
||||||
|
"disk.0.cache": "none",
|
||||||
|
"disk.0.discard": "ignore",
|
||||||
|
"disk.0.file_id": "",
|
||||||
|
"disk.0.datastore_id": "local-lvm",
|
||||||
|
"disk.0.file_format": "raw",
|
||||||
|
"disk.0.interface": "virtio0",
|
||||||
|
"disk.0.iothread": "false",
|
||||||
|
"disk.0.path_in_datastore": `vm-\d+-disk-\d+`,
|
||||||
|
"disk.0.replicate": "false",
|
||||||
|
"disk.0.size": "8",
|
||||||
|
"disk.0.ssd": "false",
|
||||||
|
"disk.0.speed.0.iops_read": "100",
|
||||||
|
"disk.0.speed.0.iops_read_burstable": "1000",
|
||||||
|
"disk.0.speed.0.iops_write": "400",
|
||||||
|
"disk.0.speed.0.iops_write_burstable": "800",
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
}},
|
||||||
{"create disk from an image", []resource.TestStep{{
|
{"create disk from an image", []resource.TestStep{{
|
||||||
Config: providerConfig + `
|
Config: providerConfig + `
|
||||||
resource "proxmox_virtual_environment_download_file" "test_disk2_image" {
|
resource "proxmox_virtual_environment_download_file" "test_disk2_image" {
|
||||||
@ -282,59 +332,62 @@ func TestAccResourceVMDisks(t *testing.T) {
|
|||||||
RefreshState: true,
|
RefreshState: true,
|
||||||
},
|
},
|
||||||
}},
|
}},
|
||||||
// this test is failing because of https://github.com/bpg/terraform-provider-proxmox/issues/360
|
{"clone disk with overrides", []resource.TestStep{
|
||||||
// {"clone disk with new size", []resource.TestStep{
|
{
|
||||||
// {
|
SkipFunc: func() (bool, error) {
|
||||||
// Config: providerConfig + `
|
// this test is failing because of https://github.com/bpg/terraform-provider-proxmox/issues/873
|
||||||
// resource "proxmox_virtual_environment_vm" "test_disk3_template" {
|
return true, nil
|
||||||
// node_name = "pve"
|
},
|
||||||
// started = false
|
Config: providerConfig + `
|
||||||
// name = "test-disk3-template"
|
resource "proxmox_virtual_environment_vm" "test_disk3_template" {
|
||||||
// template = "true"
|
node_name = "pve"
|
||||||
//
|
started = false
|
||||||
// disk {
|
name = "test-disk3-template"
|
||||||
// file_format = "raw"
|
template = "true"
|
||||||
// datastore_id = "local-lvm"
|
|
||||||
// interface = "scsi0"
|
disk {
|
||||||
// size = 8
|
file_format = "raw"
|
||||||
// discard = "on"
|
datastore_id = "local-lvm"
|
||||||
// iothread = true
|
interface = "scsi0"
|
||||||
// }
|
size = 8
|
||||||
// }
|
discard = "on"
|
||||||
// resource "proxmox_virtual_environment_vm" "test_disk3" {
|
iothread = true
|
||||||
// node_name = "pve"
|
ssd = true
|
||||||
// started = false
|
}
|
||||||
// name = "test-disk3"
|
}
|
||||||
//
|
resource "proxmox_virtual_environment_vm" "test_disk3" {
|
||||||
// clone {
|
node_name = "pve"
|
||||||
// vm_id = proxmox_virtual_environment_vm.test_disk3_template.id
|
started = false
|
||||||
// }
|
name = "test-disk3"
|
||||||
//
|
|
||||||
// disk {
|
clone {
|
||||||
// interface = "scsi0"
|
vm_id = proxmox_virtual_environment_vm.test_disk3_template.id
|
||||||
// size = 10
|
}
|
||||||
// //ssd = true
|
|
||||||
// }
|
disk {
|
||||||
// }
|
interface = "scsi0"
|
||||||
// `,
|
//size = 10
|
||||||
// Check: resource.ComposeTestCheckFunc(
|
}
|
||||||
// testResourceAttributes("proxmox_virtual_environment_vm.test_disk3", map[string]string{
|
}
|
||||||
// "disk.0.datastore_id": "local-lvm",
|
`,
|
||||||
// "disk.0.discard": "on",
|
Check: resource.ComposeTestCheckFunc(
|
||||||
// "disk.0.file_format": "raw",
|
testResourceAttributes("proxmox_virtual_environment_vm.test_disk3", map[string]string{
|
||||||
// "disk.0.interface": "scsi0",
|
"disk.0.datastore_id": "local-lvm",
|
||||||
// "disk.0.iothread": "true",
|
"disk.0.discard": "on",
|
||||||
// "disk.0.path_in_datastore": `vm-\d+-disk-\d+`,
|
"disk.0.file_format": "raw",
|
||||||
// "disk.0.size": "10",
|
"disk.0.interface": "scsi0",
|
||||||
// "disk.0.ssd": "false",
|
"disk.0.iothread": "true",
|
||||||
// }),
|
"disk.0.path_in_datastore": `vm-\d+-disk-\d+`,
|
||||||
// ),
|
"disk.0.size": "8",
|
||||||
// },
|
"disk.0.ssd": "true",
|
||||||
//{
|
}),
|
||||||
// RefreshState: true,
|
),
|
||||||
// Destroy: false,
|
},
|
||||||
// },
|
{
|
||||||
// }},
|
RefreshState: true,
|
||||||
|
Destroy: false,
|
||||||
|
},
|
||||||
|
}},
|
||||||
}
|
}
|
||||||
|
|
||||||
accProviders := testAccMuxProviders(context.Background(), t)
|
accProviders := testAccMuxProviders(context.Background(), t)
|
||||||
|
@ -12,23 +12,28 @@ import (
|
|||||||
// 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 *types.CustomBool `json:"backup,omitempty" url:"backup,omitempty,int"`
|
Backup *types.CustomBool `json:"backup,omitempty" url:"backup,omitempty,int"`
|
||||||
BurstableReadSpeedMbps *int `json:"mbps_rd_max,omitempty" url:"mbps_rd_max,omitempty"`
|
BurstableReadSpeedMbps *int `json:"mbps_rd_max,omitempty" url:"mbps_rd_max,omitempty"`
|
||||||
Cache *string `json:"cache,omitempty" url:"cache,omitempty"`
|
|
||||||
BurstableWriteSpeedMbps *int `json:"mbps_wr_max,omitempty" url:"mbps_wr_max,omitempty"`
|
BurstableWriteSpeedMbps *int `json:"mbps_wr_max,omitempty" url:"mbps_wr_max,omitempty"`
|
||||||
|
Cache *string `json:"cache,omitempty" url:"cache,omitempty"`
|
||||||
Discard *string `json:"discard,omitempty" url:"discard,omitempty"`
|
Discard *string `json:"discard,omitempty" url:"discard,omitempty"`
|
||||||
Enabled bool `json:"-" url:"-"`
|
|
||||||
FileVolume string `json:"file" url:"file"`
|
FileVolume string `json:"file" url:"file"`
|
||||||
Format *string `json:"format,omitempty" url:"format,omitempty"`
|
Format *string `json:"format,omitempty" url:"format,omitempty"`
|
||||||
|
IopsRead *int `json:"iops_rd,omitempty" url:"iops_rd,omitempty"`
|
||||||
|
IopsWrite *int `json:"iops_wr,omitempty" url:"iops_wr,omitempty"`
|
||||||
IOThread *types.CustomBool `json:"iothread,omitempty" url:"iothread,omitempty,int"`
|
IOThread *types.CustomBool `json:"iothread,omitempty" url:"iothread,omitempty,int"`
|
||||||
SSD *types.CustomBool `json:"ssd,omitempty" url:"ssd,omitempty,int"`
|
MaxIopsRead *int `json:"iops_rd_max,omitempty" url:"iops_rd_max,omitempty"`
|
||||||
|
MaxIopsWrite *int `json:"iops_wr_max,omitempty" url:"iops_wr_max,omitempty"`
|
||||||
MaxReadSpeedMbps *int `json:"mbps_rd,omitempty" url:"mbps_rd,omitempty"`
|
MaxReadSpeedMbps *int `json:"mbps_rd,omitempty" url:"mbps_rd,omitempty"`
|
||||||
MaxWriteSpeedMbps *int `json:"mbps_wr,omitempty" url:"mbps_wr,omitempty"`
|
MaxWriteSpeedMbps *int `json:"mbps_wr,omitempty" url:"mbps_wr,omitempty"`
|
||||||
Media *string `json:"media,omitempty" url:"media,omitempty"`
|
Media *string `json:"media,omitempty" url:"media,omitempty"`
|
||||||
|
Replicate *types.CustomBool `json:"replicate,omitempty" url:"replicate,omitempty,int"`
|
||||||
Size *types.DiskSize `json:"size,omitempty" url:"size,omitempty"`
|
Size *types.DiskSize `json:"size,omitempty" url:"size,omitempty"`
|
||||||
Interface *string `json:"-" url:"-"`
|
SSD *types.CustomBool `json:"ssd,omitempty" url:"ssd,omitempty,int"`
|
||||||
DatastoreID *string `json:"-" url:"-"`
|
DatastoreID *string `json:"-" url:"-"`
|
||||||
|
Enabled bool `json:"-" url:"-"`
|
||||||
FileID *string `json:"-" url:"-"`
|
FileID *string `json:"-" url:"-"`
|
||||||
|
Interface *string `json:"-" url:"-"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// PathInDatastore returns path part of FileVolume or nil if it is not yet allocated.
|
// PathInDatastore returns path part of FileVolume or nil if it is not yet allocated.
|
||||||
@ -110,14 +115,30 @@ func (d CustomStorageDevice) EncodeOptions() string {
|
|||||||
values = append(values, fmt.Sprintf("aio=%s", *d.AIO))
|
values = append(values, fmt.Sprintf("aio=%s", *d.AIO))
|
||||||
}
|
}
|
||||||
|
|
||||||
if d.BackupEnabled != nil {
|
if d.Backup != nil {
|
||||||
if *d.BackupEnabled {
|
if *d.Backup {
|
||||||
values = append(values, "backup=1")
|
values = append(values, "backup=1")
|
||||||
} else {
|
} else {
|
||||||
values = append(values, "backup=0")
|
values = append(values, "backup=0")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if d.IopsRead != nil {
|
||||||
|
values = append(values, fmt.Sprintf("iops_rd=%d", *d.IopsRead))
|
||||||
|
}
|
||||||
|
|
||||||
|
if d.IopsWrite != nil {
|
||||||
|
values = append(values, fmt.Sprintf("iops_wr=%d", *d.IopsWrite))
|
||||||
|
}
|
||||||
|
|
||||||
|
if d.MaxIopsRead != nil {
|
||||||
|
values = append(values, fmt.Sprintf("iops_rd_max=%d", *d.MaxIopsRead))
|
||||||
|
}
|
||||||
|
|
||||||
|
if d.MaxIopsWrite != nil {
|
||||||
|
values = append(values, fmt.Sprintf("iops_wr_max=%d", *d.MaxIopsWrite))
|
||||||
|
}
|
||||||
|
|
||||||
if d.IOThread != nil {
|
if d.IOThread != nil {
|
||||||
if *d.IOThread {
|
if *d.IOThread {
|
||||||
values = append(values, "iothread=1")
|
values = append(values, "iothread=1")
|
||||||
@ -158,6 +179,14 @@ func (d CustomStorageDevice) EncodeOptions() string {
|
|||||||
values = append(values, fmt.Sprintf("mbps_wr=%d", *d.MaxWriteSpeedMbps))
|
values = append(values, fmt.Sprintf("mbps_wr=%d", *d.MaxWriteSpeedMbps))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if d.Replicate != nil {
|
||||||
|
if *d.Replicate {
|
||||||
|
values = append(values, "replicate=1")
|
||||||
|
} else {
|
||||||
|
values = append(values, "replicate=0")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return strings.Join(values, ",")
|
return strings.Join(values, ",")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -190,23 +219,28 @@ func (d CustomStorageDevice) EncodeValues(key string, v *url.Values) error {
|
|||||||
func (d CustomStorageDevice) Copy() *CustomStorageDevice {
|
func (d CustomStorageDevice) Copy() *CustomStorageDevice {
|
||||||
return &CustomStorageDevice{
|
return &CustomStorageDevice{
|
||||||
AIO: types.CopyString(d.AIO),
|
AIO: types.CopyString(d.AIO),
|
||||||
BackupEnabled: d.BackupEnabled.Copy(),
|
Backup: d.Backup.Copy(),
|
||||||
BurstableReadSpeedMbps: types.CopyInt(d.BurstableReadSpeedMbps),
|
BurstableReadSpeedMbps: types.CopyInt(d.BurstableReadSpeedMbps),
|
||||||
Cache: types.CopyString(d.Cache),
|
|
||||||
BurstableWriteSpeedMbps: types.CopyInt(d.BurstableWriteSpeedMbps),
|
BurstableWriteSpeedMbps: types.CopyInt(d.BurstableWriteSpeedMbps),
|
||||||
|
Cache: types.CopyString(d.Cache),
|
||||||
|
DatastoreID: types.CopyString(d.DatastoreID),
|
||||||
Discard: types.CopyString(d.Discard),
|
Discard: types.CopyString(d.Discard),
|
||||||
Enabled: d.Enabled,
|
Enabled: d.Enabled,
|
||||||
|
FileID: types.CopyString(d.FileID),
|
||||||
FileVolume: d.FileVolume,
|
FileVolume: d.FileVolume,
|
||||||
Format: types.CopyString(d.Format),
|
Format: types.CopyString(d.Format),
|
||||||
|
Interface: types.CopyString(d.Interface),
|
||||||
|
IopsRead: types.CopyInt(d.IopsRead),
|
||||||
|
IopsWrite: types.CopyInt(d.IopsWrite),
|
||||||
IOThread: d.IOThread.Copy(),
|
IOThread: d.IOThread.Copy(),
|
||||||
SSD: d.SSD.Copy(),
|
MaxIopsRead: types.CopyInt(d.MaxIopsRead),
|
||||||
|
MaxIopsWrite: types.CopyInt(d.MaxIopsWrite),
|
||||||
MaxReadSpeedMbps: types.CopyInt(d.MaxReadSpeedMbps),
|
MaxReadSpeedMbps: types.CopyInt(d.MaxReadSpeedMbps),
|
||||||
MaxWriteSpeedMbps: types.CopyInt(d.MaxWriteSpeedMbps),
|
MaxWriteSpeedMbps: types.CopyInt(d.MaxWriteSpeedMbps),
|
||||||
Media: types.CopyString(d.Media),
|
Media: types.CopyString(d.Media),
|
||||||
|
Replicate: d.Replicate.Copy(),
|
||||||
Size: d.Size.Copy(),
|
Size: d.Size.Copy(),
|
||||||
Interface: types.CopyString(d.Interface),
|
SSD: d.SSD.Copy(),
|
||||||
DatastoreID: types.CopyString(d.DatastoreID),
|
|
||||||
FileID: types.CopyString(d.FileID),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1827,11 +1827,56 @@ func (d *CustomStorageDevice) UnmarshalJSON(b []byte) error {
|
|||||||
|
|
||||||
case "backup":
|
case "backup":
|
||||||
bv := types.CustomBool(v[1] == "1")
|
bv := types.CustomBool(v[1] == "1")
|
||||||
d.BackupEnabled = &bv
|
d.Backup = &bv
|
||||||
|
|
||||||
|
case "cache":
|
||||||
|
d.Cache = &v[1]
|
||||||
|
|
||||||
|
case "discard":
|
||||||
|
d.Discard = &v[1]
|
||||||
|
|
||||||
case "file":
|
case "file":
|
||||||
d.FileVolume = v[1]
|
d.FileVolume = v[1]
|
||||||
|
|
||||||
|
case "format":
|
||||||
|
d.Format = &v[1]
|
||||||
|
|
||||||
|
case "iops_rd":
|
||||||
|
iv, err := strconv.Atoi(v[1])
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to convert iops_rd to int: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
d.IopsRead = &iv
|
||||||
|
|
||||||
|
case "iops_rd_max":
|
||||||
|
iv, err := strconv.Atoi(v[1])
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to convert iops_rd_max to int: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
d.MaxIopsRead = &iv
|
||||||
|
|
||||||
|
case "iops_wr":
|
||||||
|
iv, err := strconv.Atoi(v[1])
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to convert iops_wr to int: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
d.IopsWrite = &iv
|
||||||
|
|
||||||
|
case "iops_wr_max":
|
||||||
|
iv, err := strconv.Atoi(v[1])
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to convert iops_wr_max to int: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
d.MaxIopsWrite = &iv
|
||||||
|
|
||||||
|
case "iothread":
|
||||||
|
bv := types.CustomBool(v[1] == "1")
|
||||||
|
d.IOThread = &bv
|
||||||
|
|
||||||
case "mbps_rd":
|
case "mbps_rd":
|
||||||
iv, err := strconv.Atoi(v[1])
|
iv, err := strconv.Atoi(v[1])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -1839,6 +1884,7 @@ func (d *CustomStorageDevice) UnmarshalJSON(b []byte) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
d.MaxReadSpeedMbps = &iv
|
d.MaxReadSpeedMbps = &iv
|
||||||
|
|
||||||
case "mbps_rd_max":
|
case "mbps_rd_max":
|
||||||
iv, err := strconv.Atoi(v[1])
|
iv, err := strconv.Atoi(v[1])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -1846,6 +1892,7 @@ func (d *CustomStorageDevice) UnmarshalJSON(b []byte) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
d.BurstableReadSpeedMbps = &iv
|
d.BurstableReadSpeedMbps = &iv
|
||||||
|
|
||||||
case "mbps_wr":
|
case "mbps_wr":
|
||||||
iv, err := strconv.Atoi(v[1])
|
iv, err := strconv.Atoi(v[1])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -1853,6 +1900,7 @@ func (d *CustomStorageDevice) UnmarshalJSON(b []byte) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
d.MaxWriteSpeedMbps = &iv
|
d.MaxWriteSpeedMbps = &iv
|
||||||
|
|
||||||
case "mbps_wr_max":
|
case "mbps_wr_max":
|
||||||
iv, err := strconv.Atoi(v[1])
|
iv, err := strconv.Atoi(v[1])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -1860,9 +1908,14 @@ func (d *CustomStorageDevice) UnmarshalJSON(b []byte) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
d.BurstableWriteSpeedMbps = &iv
|
d.BurstableWriteSpeedMbps = &iv
|
||||||
|
|
||||||
case "media":
|
case "media":
|
||||||
d.Media = &v[1]
|
d.Media = &v[1]
|
||||||
|
|
||||||
|
case "replicate":
|
||||||
|
bv := types.CustomBool(v[1] == "1")
|
||||||
|
d.Replicate = &bv
|
||||||
|
|
||||||
case "size":
|
case "size":
|
||||||
d.Size = new(types.DiskSize)
|
d.Size = new(types.DiskSize)
|
||||||
|
|
||||||
@ -1871,22 +1924,9 @@ func (d *CustomStorageDevice) UnmarshalJSON(b []byte) error {
|
|||||||
return fmt.Errorf("failed to unmarshal disk size: %w", err)
|
return fmt.Errorf("failed to unmarshal disk size: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
case "format":
|
|
||||||
d.Format = &v[1]
|
|
||||||
|
|
||||||
case "iothread":
|
|
||||||
bv := types.CustomBool(v[1] == "1")
|
|
||||||
d.IOThread = &bv
|
|
||||||
|
|
||||||
case "ssd":
|
case "ssd":
|
||||||
bv := types.CustomBool(v[1] == "1")
|
bv := types.CustomBool(v[1] == "1")
|
||||||
d.SSD = &bv
|
d.SSD = &bv
|
||||||
|
|
||||||
case "discard":
|
|
||||||
d.Discard = &v[1]
|
|
||||||
|
|
||||||
case "cache":
|
|
||||||
d.Cache = &v[1]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -246,14 +246,17 @@ func GetDiskDeviceObjects(
|
|||||||
pathInDatastore = untyped.(string)
|
pathInDatastore = untyped.(string)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
aio := block[mkDiskAIO].(string)
|
||||||
|
backup := types.CustomBool(block[mkDiskBackup].(bool))
|
||||||
|
cache := block[mkDiskCache].(string)
|
||||||
|
discard := block[mkDiskDiscard].(string)
|
||||||
|
diskInterface, _ := block[mkDiskInterface].(string)
|
||||||
fileFormat, _ := block[mkDiskFileFormat].(string)
|
fileFormat, _ := block[mkDiskFileFormat].(string)
|
||||||
fileID, _ := block[mkDiskFileID].(string)
|
fileID, _ := block[mkDiskFileID].(string)
|
||||||
size, _ := block[mkDiskSize].(int)
|
|
||||||
diskInterface, _ := block[mkDiskInterface].(string)
|
|
||||||
ioThread := types.CustomBool(block[mkDiskIOThread].(bool))
|
ioThread := types.CustomBool(block[mkDiskIOThread].(bool))
|
||||||
|
replicate := types.CustomBool(block[mkDiskReplicate].(bool))
|
||||||
|
size, _ := block[mkDiskSize].(int)
|
||||||
ssd := types.CustomBool(block[mkDiskSSD].(bool))
|
ssd := types.CustomBool(block[mkDiskSSD].(bool))
|
||||||
discard := block[mkDiskDiscard].(string)
|
|
||||||
cache := block[mkDiskCache].(string)
|
|
||||||
|
|
||||||
speedBlock, err := structure.GetSchemaBlock(
|
speedBlock, err := structure.GetSchemaBlock(
|
||||||
resource,
|
resource,
|
||||||
@ -285,26 +288,51 @@ func GetDiskDeviceObjects(
|
|||||||
diskDevice.FileVolume = fmt.Sprintf("%s:%d", datastoreID, size)
|
diskDevice.FileVolume = fmt.Sprintf("%s:%d", datastoreID, size)
|
||||||
}
|
}
|
||||||
|
|
||||||
diskDevice.DatastoreID = &datastoreID
|
diskDevice.AIO = &aio
|
||||||
diskDevice.Interface = &diskInterface
|
diskDevice.Backup = &backup
|
||||||
diskDevice.Format = &fileFormat
|
|
||||||
diskDevice.FileID = &fileID
|
|
||||||
diskSize := types.DiskSizeFromGigabytes(int64(size))
|
|
||||||
diskDevice.Size = diskSize
|
|
||||||
diskDevice.IOThread = &ioThread
|
|
||||||
diskDevice.Discard = &discard
|
|
||||||
diskDevice.Cache = &cache
|
diskDevice.Cache = &cache
|
||||||
|
diskDevice.DatastoreID = &datastoreID
|
||||||
|
diskDevice.Discard = &discard
|
||||||
|
diskDevice.FileID = &fileID
|
||||||
|
diskDevice.Format = &fileFormat
|
||||||
|
diskDevice.Interface = &diskInterface
|
||||||
|
diskDevice.Replicate = &replicate
|
||||||
|
diskDevice.Size = types.DiskSizeFromGigabytes(int64(size))
|
||||||
|
|
||||||
if !strings.HasPrefix(diskInterface, "virtio") {
|
if !strings.HasPrefix(diskInterface, "virtio") {
|
||||||
diskDevice.SSD = &ssd
|
diskDevice.SSD = &ssd
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !strings.HasPrefix(diskInterface, "sata") {
|
||||||
|
diskDevice.IOThread = &ioThread
|
||||||
|
}
|
||||||
|
|
||||||
if len(speedBlock) > 0 {
|
if len(speedBlock) > 0 {
|
||||||
|
iopsRead := speedBlock[mkDiskIopsRead].(int)
|
||||||
|
iopsReadBurstable := speedBlock[mkDiskIopsReadBurstable].(int)
|
||||||
|
iopsWrite := speedBlock[mkDiskIopsWrite].(int)
|
||||||
|
iopsWriteBurstable := speedBlock[mkDiskIopsWriteBurstable].(int)
|
||||||
speedLimitRead := speedBlock[mkDiskSpeedRead].(int)
|
speedLimitRead := speedBlock[mkDiskSpeedRead].(int)
|
||||||
speedLimitReadBurstable := speedBlock[mkDiskSpeedReadBurstable].(int)
|
speedLimitReadBurstable := speedBlock[mkDiskSpeedReadBurstable].(int)
|
||||||
speedLimitWrite := speedBlock[mkDiskSpeedWrite].(int)
|
speedLimitWrite := speedBlock[mkDiskSpeedWrite].(int)
|
||||||
speedLimitWriteBurstable := speedBlock[mkDiskSpeedWriteBurstable].(int)
|
speedLimitWriteBurstable := speedBlock[mkDiskSpeedWriteBurstable].(int)
|
||||||
|
|
||||||
|
if iopsRead > 0 {
|
||||||
|
diskDevice.IopsRead = &iopsRead
|
||||||
|
}
|
||||||
|
|
||||||
|
if iopsReadBurstable > 0 {
|
||||||
|
diskDevice.MaxIopsRead = &iopsReadBurstable
|
||||||
|
}
|
||||||
|
|
||||||
|
if iopsWrite > 0 {
|
||||||
|
diskDevice.IopsWrite = &iopsWrite
|
||||||
|
}
|
||||||
|
|
||||||
|
if iopsWriteBurstable > 0 {
|
||||||
|
diskDevice.MaxIopsWrite = &iopsWriteBurstable
|
||||||
|
}
|
||||||
|
|
||||||
if speedLimitRead > 0 {
|
if speedLimitRead > 0 {
|
||||||
diskDevice.MaxReadSpeedMbps = &speedLimitRead
|
diskDevice.MaxReadSpeedMbps = &speedLimitRead
|
||||||
}
|
}
|
||||||
@ -391,15 +419,18 @@ func CreateCustomDisks(
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
aio, _ := block[mkDiskAIO].(string)
|
||||||
|
backup := types.CustomBool(block[mkDiskBackup].(bool))
|
||||||
|
cache, _ := block[mkDiskCache].(string)
|
||||||
datastoreID, _ := block[mkDiskDatastoreID].(string)
|
datastoreID, _ := block[mkDiskDatastoreID].(string)
|
||||||
|
discard, _ := block[mkDiskDiscard].(string)
|
||||||
|
diskInterface, _ := block[mkDiskInterface].(string)
|
||||||
fileFormat, _ := block[mkDiskFileFormat].(string)
|
fileFormat, _ := block[mkDiskFileFormat].(string)
|
||||||
|
ioThread := types.CustomBool(block[mkDiskIOThread].(bool))
|
||||||
|
replicate := types.CustomBool(block[mkDiskReplicate].(bool))
|
||||||
size, _ := block[mkDiskSize].(int)
|
size, _ := block[mkDiskSize].(int)
|
||||||
speed := block[mkDiskSpeed].([]interface{})
|
speed := block[mkDiskSpeed].([]interface{})
|
||||||
diskInterface, _ := block[mkDiskInterface].(string)
|
|
||||||
ioThread := types.CustomBool(block[mkDiskIOThread].(bool))
|
|
||||||
ssd := types.CustomBool(block[mkDiskSSD].(bool))
|
ssd := types.CustomBool(block[mkDiskSSD].(bool))
|
||||||
discard, _ := block[mkDiskDiscard].(string)
|
|
||||||
cache, _ := block[mkDiskCache].(string)
|
|
||||||
|
|
||||||
if fileFormat == "" {
|
if fileFormat == "" {
|
||||||
fileFormat = dvDiskFileFormat
|
fileFormat = dvDiskFileFormat
|
||||||
@ -415,6 +446,10 @@ func CreateCustomDisks(
|
|||||||
}
|
}
|
||||||
|
|
||||||
speedBlock := speed[0].(map[string]interface{})
|
speedBlock := speed[0].(map[string]interface{})
|
||||||
|
iopsRead := speedBlock[mkDiskIopsRead].(int)
|
||||||
|
iopsReadBurstable := speedBlock[mkDiskIopsReadBurstable].(int)
|
||||||
|
iopsWrite := speedBlock[mkDiskIopsWrite].(int)
|
||||||
|
iopsWriteBurstable := speedBlock[mkDiskIopsWriteBurstable].(int)
|
||||||
speedLimitRead := speedBlock[mkDiskSpeedRead].(int)
|
speedLimitRead := speedBlock[mkDiskSpeedRead].(int)
|
||||||
speedLimitReadBurstable := speedBlock[mkDiskSpeedReadBurstable].(int)
|
speedLimitReadBurstable := speedBlock[mkDiskSpeedReadBurstable].(int)
|
||||||
speedLimitWrite := speedBlock[mkDiskSpeedWrite].(int)
|
speedLimitWrite := speedBlock[mkDiskSpeedWrite].(int)
|
||||||
@ -422,10 +457,26 @@ func CreateCustomDisks(
|
|||||||
|
|
||||||
diskOptions := ""
|
diskOptions := ""
|
||||||
|
|
||||||
|
if aio != "" {
|
||||||
|
diskOptions += fmt.Sprintf(",aio=%s", aio)
|
||||||
|
}
|
||||||
|
|
||||||
|
if backup {
|
||||||
|
diskOptions += ",backup=1"
|
||||||
|
} else {
|
||||||
|
diskOptions += ",backup=0"
|
||||||
|
}
|
||||||
|
|
||||||
if ioThread {
|
if ioThread {
|
||||||
diskOptions += ",iothread=1"
|
diskOptions += ",iothread=1"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if replicate {
|
||||||
|
diskOptions += ",replicate=1"
|
||||||
|
} else {
|
||||||
|
diskOptions += ",replicate=0"
|
||||||
|
}
|
||||||
|
|
||||||
if ssd {
|
if ssd {
|
||||||
diskOptions += ",ssd=1"
|
diskOptions += ",ssd=1"
|
||||||
}
|
}
|
||||||
@ -438,6 +489,22 @@ func CreateCustomDisks(
|
|||||||
diskOptions += fmt.Sprintf(",cache=%s", cache)
|
diskOptions += fmt.Sprintf(",cache=%s", cache)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if iopsRead > 0 {
|
||||||
|
diskOptions += fmt.Sprintf(",iops_rd=%d", iopsRead)
|
||||||
|
}
|
||||||
|
|
||||||
|
if iopsReadBurstable > 0 {
|
||||||
|
diskOptions += fmt.Sprintf(",iops_rd_max=%d", iopsReadBurstable)
|
||||||
|
}
|
||||||
|
|
||||||
|
if iopsWrite > 0 {
|
||||||
|
diskOptions += fmt.Sprintf(",iops_wr=%d", iopsWrite)
|
||||||
|
}
|
||||||
|
|
||||||
|
if iopsWriteBurstable > 0 {
|
||||||
|
diskOptions += fmt.Sprintf(",iops_wr_max=%d", iopsWriteBurstable)
|
||||||
|
}
|
||||||
|
|
||||||
if speedLimitRead > 0 {
|
if speedLimitRead > 0 {
|
||||||
diskOptions += fmt.Sprintf(",mbps_rd=%d", speedLimitRead)
|
diskOptions += fmt.Sprintf(",mbps_rd=%d", speedLimitRead)
|
||||||
}
|
}
|
||||||
@ -573,12 +640,82 @@ func Read(
|
|||||||
disk[mkDiskInterface] = di
|
disk[mkDiskInterface] = di
|
||||||
disk[mkDiskSize] = dd.Size.InGigabytes()
|
disk[mkDiskSize] = dd.Size.InGigabytes()
|
||||||
|
|
||||||
if dd.BurstableReadSpeedMbps != nil ||
|
if dd.AIO != nil {
|
||||||
|
disk[mkDiskAIO] = *dd.AIO
|
||||||
|
} else {
|
||||||
|
disk[mkDiskAIO] = dvDiskAIO
|
||||||
|
}
|
||||||
|
|
||||||
|
if dd.Backup != nil {
|
||||||
|
disk[mkDiskBackup] = *dd.Backup
|
||||||
|
} else {
|
||||||
|
disk[mkDiskBackup] = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if dd.IOThread != nil {
|
||||||
|
disk[mkDiskIOThread] = *dd.IOThread
|
||||||
|
} else {
|
||||||
|
disk[mkDiskIOThread] = false
|
||||||
|
}
|
||||||
|
|
||||||
|
if dd.Replicate != nil {
|
||||||
|
disk[mkDiskReplicate] = *dd.Replicate
|
||||||
|
} else {
|
||||||
|
disk[mkDiskReplicate] = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if dd.SSD != nil {
|
||||||
|
disk[mkDiskSSD] = *dd.SSD
|
||||||
|
} else {
|
||||||
|
disk[mkDiskSSD] = false
|
||||||
|
}
|
||||||
|
|
||||||
|
if dd.Discard != nil {
|
||||||
|
disk[mkDiskDiscard] = *dd.Discard
|
||||||
|
} else {
|
||||||
|
disk[mkDiskDiscard] = dvDiskDiscard
|
||||||
|
}
|
||||||
|
|
||||||
|
if dd.Cache != nil {
|
||||||
|
disk[mkDiskCache] = *dd.Cache
|
||||||
|
} else {
|
||||||
|
disk[mkDiskCache] = dvDiskCache
|
||||||
|
}
|
||||||
|
|
||||||
|
if dd.IopsRead != nil ||
|
||||||
|
dd.MaxIopsRead != nil ||
|
||||||
|
dd.IopsWrite != nil ||
|
||||||
|
dd.MaxIopsWrite != nil ||
|
||||||
|
dd.BurstableReadSpeedMbps != nil ||
|
||||||
dd.BurstableWriteSpeedMbps != nil ||
|
dd.BurstableWriteSpeedMbps != nil ||
|
||||||
dd.MaxReadSpeedMbps != nil ||
|
dd.MaxReadSpeedMbps != nil ||
|
||||||
dd.MaxWriteSpeedMbps != nil {
|
dd.MaxWriteSpeedMbps != nil {
|
||||||
speed := map[string]interface{}{}
|
speed := map[string]interface{}{}
|
||||||
|
|
||||||
|
if dd.IopsRead != nil {
|
||||||
|
speed[mkDiskIopsRead] = *dd.IopsRead
|
||||||
|
} else {
|
||||||
|
speed[mkDiskIopsRead] = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
if dd.MaxIopsRead != nil {
|
||||||
|
speed[mkDiskIopsReadBurstable] = *dd.MaxIopsRead
|
||||||
|
} else {
|
||||||
|
speed[mkDiskIopsReadBurstable] = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
if dd.IopsWrite != nil {
|
||||||
|
speed[mkDiskIopsWrite] = *dd.IopsWrite
|
||||||
|
} else {
|
||||||
|
speed[mkDiskIopsWrite] = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
if dd.MaxIopsWrite != nil {
|
||||||
|
speed[mkDiskIopsWriteBurstable] = *dd.MaxIopsWrite
|
||||||
|
} else {
|
||||||
|
speed[mkDiskIopsWriteBurstable] = 0
|
||||||
|
}
|
||||||
|
|
||||||
if dd.MaxReadSpeedMbps != nil {
|
if dd.MaxReadSpeedMbps != nil {
|
||||||
speed[mkDiskSpeedRead] = *dd.MaxReadSpeedMbps
|
speed[mkDiskSpeedRead] = *dd.MaxReadSpeedMbps
|
||||||
} else {
|
} else {
|
||||||
@ -608,30 +745,6 @@ func Read(
|
|||||||
disk[mkDiskSpeed] = []interface{}{}
|
disk[mkDiskSpeed] = []interface{}{}
|
||||||
}
|
}
|
||||||
|
|
||||||
if dd.IOThread != nil {
|
|
||||||
disk[mkDiskIOThread] = *dd.IOThread
|
|
||||||
} else {
|
|
||||||
disk[mkDiskIOThread] = false
|
|
||||||
}
|
|
||||||
|
|
||||||
if dd.SSD != nil {
|
|
||||||
disk[mkDiskSSD] = *dd.SSD
|
|
||||||
} else {
|
|
||||||
disk[mkDiskSSD] = false
|
|
||||||
}
|
|
||||||
|
|
||||||
if dd.Discard != nil {
|
|
||||||
disk[mkDiskDiscard] = *dd.Discard
|
|
||||||
} else {
|
|
||||||
disk[mkDiskDiscard] = dvDiskDiscard
|
|
||||||
}
|
|
||||||
|
|
||||||
if dd.Cache != nil {
|
|
||||||
disk[mkDiskCache] = *dd.Cache
|
|
||||||
} else {
|
|
||||||
disk[mkDiskCache] = dvDiskCache
|
|
||||||
}
|
|
||||||
|
|
||||||
diskMap[di] = disk
|
diskMap[di] = disk
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -650,7 +763,9 @@ func Update(
|
|||||||
planDisks map[string]vms.CustomStorageDevices,
|
planDisks map[string]vms.CustomStorageDevices,
|
||||||
allDiskInfo vms.CustomStorageDevices,
|
allDiskInfo vms.CustomStorageDevices,
|
||||||
updateBody *vms.UpdateRequestBody,
|
updateBody *vms.UpdateRequestBody,
|
||||||
) error {
|
) (bool, error) {
|
||||||
|
rebootRequired := false
|
||||||
|
|
||||||
if d.HasChange(MkDisk) {
|
if d.HasChange(MkDisk) {
|
||||||
for prefix, diskMap := range planDisks {
|
for prefix, diskMap := range planDisks {
|
||||||
if diskMap == nil {
|
if diskMap == nil {
|
||||||
@ -659,15 +774,30 @@ func Update(
|
|||||||
|
|
||||||
for key, value := range diskMap {
|
for key, value := range diskMap {
|
||||||
if allDiskInfo[key] == nil {
|
if allDiskInfo[key] == nil {
|
||||||
return fmt.Errorf("missing %s device %s", prefix, key)
|
return false, fmt.Errorf("missing %s device %s", prefix, key)
|
||||||
}
|
}
|
||||||
|
|
||||||
tmp := allDiskInfo[key]
|
tmp := allDiskInfo[key]
|
||||||
|
|
||||||
|
if tmp.AIO != value.AIO {
|
||||||
|
rebootRequired = true
|
||||||
|
tmp.AIO = value.AIO
|
||||||
|
}
|
||||||
|
|
||||||
|
tmp.Backup = value.Backup
|
||||||
tmp.BurstableReadSpeedMbps = value.BurstableReadSpeedMbps
|
tmp.BurstableReadSpeedMbps = value.BurstableReadSpeedMbps
|
||||||
tmp.BurstableWriteSpeedMbps = value.BurstableWriteSpeedMbps
|
tmp.BurstableWriteSpeedMbps = value.BurstableWriteSpeedMbps
|
||||||
|
tmp.Cache = value.Cache
|
||||||
|
tmp.Discard = value.Discard
|
||||||
|
tmp.IOThread = value.IOThread
|
||||||
|
tmp.IopsRead = value.IopsRead
|
||||||
|
tmp.IopsWrite = value.IopsWrite
|
||||||
|
tmp.MaxIopsRead = value.MaxIopsRead
|
||||||
|
tmp.MaxIopsWrite = value.MaxIopsWrite
|
||||||
tmp.MaxReadSpeedMbps = value.MaxReadSpeedMbps
|
tmp.MaxReadSpeedMbps = value.MaxReadSpeedMbps
|
||||||
tmp.MaxWriteSpeedMbps = value.MaxWriteSpeedMbps
|
tmp.MaxWriteSpeedMbps = value.MaxWriteSpeedMbps
|
||||||
tmp.Cache = value.Cache
|
tmp.Replicate = value.Replicate
|
||||||
|
tmp.SSD = value.SSD
|
||||||
|
|
||||||
switch prefix {
|
switch prefix {
|
||||||
case "virtio":
|
case "virtio":
|
||||||
@ -700,11 +830,11 @@ func Update(
|
|||||||
// Investigate whether to support IDE mapping.
|
// Investigate whether to support IDE mapping.
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("device prefix %s not supported", prefix)
|
return false, fmt.Errorf("device prefix %s not supported", prefix)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return rebootRequired, nil
|
||||||
}
|
}
|
||||||
|
@ -8,37 +8,38 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
dvDiskInterface = "scsi0"
|
dvDiskInterface = "scsi0"
|
||||||
dvDiskDatastoreID = "local-lvm"
|
dvDiskDatastoreID = "local-lvm"
|
||||||
dvDiskFileFormat = "qcow2"
|
dvDiskFileFormat = "qcow2"
|
||||||
dvDiskFileID = ""
|
dvDiskSize = 8
|
||||||
dvDiskSize = 8
|
dvDiskAIO = "io_uring"
|
||||||
dvDiskIOThread = false
|
dvDiskDiscard = "ignore"
|
||||||
dvDiskSSD = false
|
dvDiskCache = "none"
|
||||||
dvDiskDiscard = "ignore"
|
|
||||||
dvDiskCache = "none"
|
|
||||||
dvDiskSpeedRead = 0
|
|
||||||
dvDiskSpeedReadBurstable = 0
|
|
||||||
dvDiskSpeedWrite = 0
|
|
||||||
dvDiskSpeedWriteBurstable = 0
|
|
||||||
|
|
||||||
// MkDisk is the name of the disk resource.
|
// MkDisk is the name of the disk resource.
|
||||||
MkDisk = "disk"
|
MkDisk = "disk"
|
||||||
mkDiskInterface = "interface"
|
mkDiskAIO = "aio"
|
||||||
|
mkDiskBackup = "backup"
|
||||||
|
mkDiskCache = "cache"
|
||||||
mkDiskDatastoreID = "datastore_id"
|
mkDiskDatastoreID = "datastore_id"
|
||||||
mkDiskPathInDatastore = "path_in_datastore"
|
mkDiskDiscard = "discard"
|
||||||
mkDiskFileFormat = "file_format"
|
mkDiskFileFormat = "file_format"
|
||||||
mkDiskFileID = "file_id"
|
mkDiskFileID = "file_id"
|
||||||
mkDiskSize = "size"
|
mkDiskInterface = "interface"
|
||||||
|
mkDiskIopsRead = "iops_read"
|
||||||
|
mkDiskIopsReadBurstable = "iops_read_burstable"
|
||||||
|
mkDiskIopsWrite = "iops_write"
|
||||||
|
mkDiskIopsWriteBurstable = "iops_write_burstable"
|
||||||
mkDiskIOThread = "iothread"
|
mkDiskIOThread = "iothread"
|
||||||
mkDiskSSD = "ssd"
|
mkDiskPathInDatastore = "path_in_datastore"
|
||||||
mkDiskDiscard = "discard"
|
mkDiskReplicate = "replicate"
|
||||||
mkDiskCache = "cache"
|
mkDiskSize = "size"
|
||||||
mkDiskSpeed = "speed"
|
mkDiskSpeed = "speed"
|
||||||
mkDiskSpeedRead = "read"
|
mkDiskSpeedRead = "read"
|
||||||
mkDiskSpeedReadBurstable = "read_burstable"
|
mkDiskSpeedReadBurstable = "read_burstable"
|
||||||
mkDiskSpeedWrite = "write"
|
mkDiskSpeedWrite = "write"
|
||||||
mkDiskSpeedWriteBurstable = "write_burstable"
|
mkDiskSpeedWriteBurstable = "write_burstable"
|
||||||
|
mkDiskSSD = "ssd"
|
||||||
|
|
||||||
// MkTimeoutMoveDisk is the name of the timeout_move_disk attribute.
|
// MkTimeoutMoveDisk is the name of the timeout_move_disk attribute.
|
||||||
MkTimeoutMoveDisk = "timeout_move_disk"
|
MkTimeoutMoveDisk = "timeout_move_disk"
|
||||||
@ -55,15 +56,18 @@ func Schema() map[string]*schema.Schema {
|
|||||||
DefaultFunc: func() (interface{}, error) {
|
DefaultFunc: func() (interface{}, error) {
|
||||||
return []interface{}{
|
return []interface{}{
|
||||||
map[string]interface{}{
|
map[string]interface{}{
|
||||||
mkDiskDatastoreID: dvDiskDatastoreID,
|
mkDiskAIO: dvDiskAIO,
|
||||||
mkDiskPathInDatastore: nil,
|
mkDiskBackup: true,
|
||||||
mkDiskFileID: dvDiskFileID,
|
|
||||||
mkDiskInterface: dvDiskInterface,
|
|
||||||
mkDiskSize: dvDiskSize,
|
|
||||||
mkDiskIOThread: dvDiskIOThread,
|
|
||||||
mkDiskSSD: dvDiskSSD,
|
|
||||||
mkDiskDiscard: dvDiskDiscard,
|
|
||||||
mkDiskCache: dvDiskCache,
|
mkDiskCache: dvDiskCache,
|
||||||
|
mkDiskDatastoreID: dvDiskDatastoreID,
|
||||||
|
mkDiskDiscard: dvDiskDiscard,
|
||||||
|
mkDiskFileID: "",
|
||||||
|
mkDiskInterface: dvDiskInterface,
|
||||||
|
mkDiskIOThread: false,
|
||||||
|
mkDiskPathInDatastore: nil,
|
||||||
|
mkDiskReplicate: true,
|
||||||
|
mkDiskSize: dvDiskSize,
|
||||||
|
mkDiskSSD: false,
|
||||||
},
|
},
|
||||||
}, nil
|
}, nil
|
||||||
},
|
},
|
||||||
@ -95,12 +99,31 @@ func Schema() map[string]*schema.Schema {
|
|||||||
Computed: true,
|
Computed: true,
|
||||||
ValidateDiagFunc: validators.FileFormat(),
|
ValidateDiagFunc: validators.FileFormat(),
|
||||||
},
|
},
|
||||||
|
mkDiskAIO: {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Description: "The disk AIO mode",
|
||||||
|
Optional: true,
|
||||||
|
Default: dvDiskAIO,
|
||||||
|
ValidateDiagFunc: validation.ToDiagFunc(
|
||||||
|
validation.StringInSlice([]string{
|
||||||
|
"io_uring",
|
||||||
|
"native",
|
||||||
|
"threads",
|
||||||
|
}, false),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
mkDiskBackup: {
|
||||||
|
Type: schema.TypeBool,
|
||||||
|
Description: "Whether the drive should be included when making backups",
|
||||||
|
Optional: true,
|
||||||
|
Default: true,
|
||||||
|
},
|
||||||
mkDiskFileID: {
|
mkDiskFileID: {
|
||||||
Type: schema.TypeString,
|
Type: schema.TypeString,
|
||||||
Description: "The file id for a disk image",
|
Description: "The file id for a disk image",
|
||||||
Optional: true,
|
Optional: true,
|
||||||
ForceNew: true,
|
ForceNew: true,
|
||||||
Default: dvDiskFileID,
|
Default: "",
|
||||||
ValidateDiagFunc: validators.FileID(),
|
ValidateDiagFunc: validators.FileID(),
|
||||||
},
|
},
|
||||||
mkDiskSize: {
|
mkDiskSize: {
|
||||||
@ -114,13 +137,19 @@ func Schema() map[string]*schema.Schema {
|
|||||||
Type: schema.TypeBool,
|
Type: schema.TypeBool,
|
||||||
Description: "Whether to use iothreads for this disk drive",
|
Description: "Whether to use iothreads for this disk drive",
|
||||||
Optional: true,
|
Optional: true,
|
||||||
Default: dvDiskIOThread,
|
Default: false,
|
||||||
|
},
|
||||||
|
mkDiskReplicate: {
|
||||||
|
Type: schema.TypeBool,
|
||||||
|
Description: "Whether the drive should be considered for replication jobs",
|
||||||
|
Optional: true,
|
||||||
|
Default: true,
|
||||||
},
|
},
|
||||||
mkDiskSSD: {
|
mkDiskSSD: {
|
||||||
Type: schema.TypeBool,
|
Type: schema.TypeBool,
|
||||||
Description: "Whether to use ssd for this disk drive",
|
Description: "Whether to use ssd for this disk drive",
|
||||||
Optional: true,
|
Optional: true,
|
||||||
Default: dvDiskSSD,
|
Default: false,
|
||||||
},
|
},
|
||||||
mkDiskDiscard: {
|
mkDiskDiscard: {
|
||||||
Type: schema.TypeString,
|
Type: schema.TypeString,
|
||||||
@ -150,38 +179,66 @@ func Schema() map[string]*schema.Schema {
|
|||||||
DefaultFunc: func() (interface{}, error) {
|
DefaultFunc: func() (interface{}, error) {
|
||||||
return []interface{}{
|
return []interface{}{
|
||||||
map[string]interface{}{
|
map[string]interface{}{
|
||||||
mkDiskSpeedRead: dvDiskSpeedRead,
|
mkDiskIopsRead: 0,
|
||||||
mkDiskSpeedReadBurstable: dvDiskSpeedReadBurstable,
|
mkDiskIopsWrite: 0,
|
||||||
mkDiskSpeedWrite: dvDiskSpeedWrite,
|
mkDiskIopsReadBurstable: 0,
|
||||||
mkDiskSpeedWriteBurstable: dvDiskSpeedWriteBurstable,
|
mkDiskIopsWriteBurstable: 0,
|
||||||
|
mkDiskSpeedRead: 0,
|
||||||
|
mkDiskSpeedReadBurstable: 0,
|
||||||
|
mkDiskSpeedWrite: 0,
|
||||||
|
mkDiskSpeedWriteBurstable: 0,
|
||||||
},
|
},
|
||||||
}, nil
|
}, nil
|
||||||
},
|
},
|
||||||
Elem: &schema.Resource{
|
Elem: &schema.Resource{
|
||||||
Schema: map[string]*schema.Schema{
|
Schema: map[string]*schema.Schema{
|
||||||
|
mkDiskIopsRead: {
|
||||||
|
Type: schema.TypeInt,
|
||||||
|
Description: "The maximum read I/O in operations per second",
|
||||||
|
Optional: true,
|
||||||
|
Default: 0,
|
||||||
|
},
|
||||||
|
mkDiskIopsWrite: {
|
||||||
|
Type: schema.TypeInt,
|
||||||
|
Description: "The maximum write I/O in operations per second",
|
||||||
|
Optional: true,
|
||||||
|
Default: 0,
|
||||||
|
},
|
||||||
|
mkDiskIopsReadBurstable: {
|
||||||
|
Type: schema.TypeInt,
|
||||||
|
Description: "The maximum unthrottled read I/O pool in operations per second",
|
||||||
|
Optional: true,
|
||||||
|
Default: 0,
|
||||||
|
},
|
||||||
|
mkDiskIopsWriteBurstable: {
|
||||||
|
Type: schema.TypeInt,
|
||||||
|
Description: "The maximum unthrottled write I/O pool in operations per second",
|
||||||
|
Optional: true,
|
||||||
|
Default: 0,
|
||||||
|
},
|
||||||
mkDiskSpeedRead: {
|
mkDiskSpeedRead: {
|
||||||
Type: schema.TypeInt,
|
Type: schema.TypeInt,
|
||||||
Description: "The maximum read speed in megabytes per second",
|
Description: "The maximum read speed in megabytes per second",
|
||||||
Optional: true,
|
Optional: true,
|
||||||
Default: dvDiskSpeedRead,
|
Default: 0,
|
||||||
},
|
},
|
||||||
mkDiskSpeedReadBurstable: {
|
mkDiskSpeedReadBurstable: {
|
||||||
Type: schema.TypeInt,
|
Type: schema.TypeInt,
|
||||||
Description: "The maximum burstable read speed in megabytes per second",
|
Description: "The maximum burstable read speed in megabytes per second",
|
||||||
Optional: true,
|
Optional: true,
|
||||||
Default: dvDiskSpeedReadBurstable,
|
Default: 0,
|
||||||
},
|
},
|
||||||
mkDiskSpeedWrite: {
|
mkDiskSpeedWrite: {
|
||||||
Type: schema.TypeInt,
|
Type: schema.TypeInt,
|
||||||
Description: "The maximum write speed in megabytes per second",
|
Description: "The maximum write speed in megabytes per second",
|
||||||
Optional: true,
|
Optional: true,
|
||||||
Default: dvDiskSpeedWrite,
|
Default: 0,
|
||||||
},
|
},
|
||||||
mkDiskSpeedWriteBurstable: {
|
mkDiskSpeedWriteBurstable: {
|
||||||
Type: schema.TypeInt,
|
Type: schema.TypeInt,
|
||||||
Description: "The maximum burstable write speed in megabytes per second",
|
Description: "The maximum burstable write speed in megabytes per second",
|
||||||
Optional: true,
|
Optional: true,
|
||||||
Default: dvDiskSpeedWriteBurstable,
|
Default: 0,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -5072,11 +5072,13 @@ func vmUpdate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.D
|
|||||||
return diag.FromErr(err)
|
return diag.FromErr(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = disk.Update(d, planDisks, allDiskInfo, updateBody)
|
rr, err := disk.Update(d, planDisks, allDiskInfo, updateBody)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return diag.FromErr(err)
|
return diag.FromErr(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rebootRequired = rebootRequired || rr
|
||||||
|
|
||||||
// Prepare the new efi disk configuration.
|
// Prepare the new efi disk configuration.
|
||||||
if d.HasChange(mkEFIDisk) {
|
if d.HasChange(mkEFIDisk) {
|
||||||
efiDisk := vmGetEfiDisk(d, nil)
|
efiDisk := vmGetEfiDisk(d, nil)
|
||||||
|
Loading…
Reference in New Issue
Block a user