From cfe3d96576b521cb294f217fb3f7caf45347e58e Mon Sep 17 00:00:00 2001 From: Pavel Boldyrev <627562+bpg@users.noreply.github.com> Date: Sat, 29 Jul 2023 13:29:14 -0400 Subject: [PATCH] feat(vm): add support for disk `cache` option (#443) --- docs/resources/virtual_environment_vm.md | 8 ++++++ example/resource_virtual_environment_vm.tf | 1 + proxmox/nodes/vms/vms_types.go | 16 +++++++++++ proxmox/nodes/vms/vms_types_test.go | 3 ++- proxmoxtf/resource/vm.go | 31 ++++++++++++++++++++++ 5 files changed, 58 insertions(+), 1 deletion(-) diff --git a/docs/resources/virtual_environment_vm.md b/docs/resources/virtual_environment_vm.md index ab1778a5..9f81522d 100644 --- a/docs/resources/virtual_environment_vm.md +++ b/docs/resources/virtual_environment_vm.md @@ -224,6 +224,14 @@ output "ubuntu_vm_public_key" { - `units` - (Optional) The CPU units (defaults to `1024`). - `description` - (Optional) The description. - `disk` - (Optional) A disk (multiple blocks supported). + - `cache` - (Optional) The cache type (defaults to `none`). + - `none` - No cache. + - `directsync` - Write to the host cache and wait for completion. + - `writethrough` - Write to the host cache, but write through to + the guest. + - `writeback` - Write to the host cache, but write back to the + guest when possible. + - `unsafe` - Write directly to the disk bypassing the host cache. - `datastore_id` - (Optional) The identifier for the datastore to create the disk in (defaults to `local-lvm`). - `discard` - (Optional) Whether to pass discard/trim requests to the diff --git a/example/resource_virtual_environment_vm.tf b/example/resource_virtual_environment_vm.tf index de25ad7d..31cfdb33 100644 --- a/example/resource_virtual_environment_vm.tf +++ b/example/resource_virtual_environment_vm.tf @@ -31,6 +31,7 @@ resource "proxmox_virtual_environment_vm" "example_template" { file_id = proxmox_virtual_environment_file.ubuntu_cloud_image.id interface = "scsi0" discard = "on" + cache = "writeback" ssd = true } diff --git a/proxmox/nodes/vms/vms_types.go b/proxmox/nodes/vms/vms_types.go index cfe1a13f..7a902fb1 100644 --- a/proxmox/nodes/vms/vms_types.go +++ b/proxmox/nodes/vms/vms_types.go @@ -168,6 +168,7 @@ type CustomStorageDevice struct { AIO *string `json:"aio,omitempty" url:"aio,omitempty"` BackupEnabled *types.CustomBool `json:"backup,omitempty" url:"backup,omitempty,int"` 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"` Discard *string `json:"discard,omitempty" url:"discard,omitempty"` Enabled bool `json:"-" url:"-"` @@ -1146,6 +1147,10 @@ func (r CustomStorageDevice) EncodeValues(key string, v *url.Values) error { values = append(values, fmt.Sprintf("discard=%s", *r.Discard)) } + if r.Cache != nil && *r.Cache != "" { + values = append(values, fmt.Sprintf("cache=%s", *r.Cache)) + } + v.Add(key, strings.Join(values, ",")) return nil @@ -1765,11 +1770,14 @@ func (r *CustomStorageDevice) UnmarshalJSON(b []byte) error { switch v[0] { case "aio": r.AIO = &v[1] + case "backup": bv := types.CustomBool(v[1] == "1") r.BackupEnabled = &bv + case "file": r.FileVolume = v[1] + case "mbps_rd": iv, err := strconv.Atoi(v[1]) if err != nil { @@ -1800,22 +1808,30 @@ func (r *CustomStorageDevice) UnmarshalJSON(b []byte) error { r.BurstableWriteSpeedMbps = &iv case "media": r.Media = &v[1] + case "size": r.Size = new(types.DiskSize) err := r.Size.UnmarshalJSON([]byte(v[1])) if err != nil { return fmt.Errorf("failed to unmarshal disk size: %w", err) } + case "format": r.Format = &v[1] + case "iothread": bv := types.CustomBool(v[1] == "1") r.IOThread = &bv + case "ssd": bv := types.CustomBool(v[1] == "1") r.SSD = &bv + case "discard": r.Discard = &v[1] + + case "cache": + r.Cache = &v[1] } } } diff --git a/proxmox/nodes/vms/vms_types_test.go b/proxmox/nodes/vms/vms_types_test.go index a5a04c4e..72fd923c 100644 --- a/proxmox/nodes/vms/vms_types_test.go +++ b/proxmox/nodes/vms/vms_types_test.go @@ -24,8 +24,9 @@ func TestCustomStorageDevice_UnmarshalJSON(t *testing.T) { }{ { name: "simple volume", - line: `"local-lvm:vm-2041-disk-0,discard=on,ssd=1,iothread=1,size=8G"`, + line: `"local-lvm:vm-2041-disk-0,discard=on,ssd=1,iothread=1,size=8G,cache=writeback"`, want: &CustomStorageDevice{ + Cache: types.StrPtr("writeback"), Discard: types.StrPtr("on"), Enabled: true, FileVolume: "local-lvm:vm-2041-disk-0", diff --git a/proxmoxtf/resource/vm.go b/proxmoxtf/resource/vm.go index 155aad49..168338ff 100644 --- a/proxmoxtf/resource/vm.go +++ b/proxmoxtf/resource/vm.go @@ -64,6 +64,7 @@ const ( dvResourceVirtualEnvironmentVMDiskIOThread = false dvResourceVirtualEnvironmentVMDiskSSD = false dvResourceVirtualEnvironmentVMDiskDiscard = "" + dvResourceVirtualEnvironmentVMDiskCache = "" dvResourceVirtualEnvironmentVMDiskSpeedRead = 0 dvResourceVirtualEnvironmentVMDiskSpeedReadBurstable = 0 dvResourceVirtualEnvironmentVMDiskSpeedWrite = 0 @@ -163,6 +164,7 @@ const ( mkResourceVirtualEnvironmentVMDiskIOThread = "iothread" mkResourceVirtualEnvironmentVMDiskSSD = "ssd" mkResourceVirtualEnvironmentVMDiskDiscard = "discard" + mkResourceVirtualEnvironmentVMDiskCache = "cache" mkResourceVirtualEnvironmentVMDiskSpeed = "speed" mkResourceVirtualEnvironmentVMDiskSpeedRead = "read" mkResourceVirtualEnvironmentVMDiskSpeedReadBurstable = "read_burstable" @@ -568,6 +570,7 @@ func VM() *schema.Resource { mkResourceVirtualEnvironmentVMDiskIOThread: dvResourceVirtualEnvironmentVMDiskIOThread, mkResourceVirtualEnvironmentVMDiskSSD: dvResourceVirtualEnvironmentVMDiskSSD, mkResourceVirtualEnvironmentVMDiskDiscard: dvResourceVirtualEnvironmentVMDiskDiscard, + mkResourceVirtualEnvironmentVMDiskCache: dvResourceVirtualEnvironmentVMDiskCache, }, }, nil }, @@ -625,6 +628,21 @@ func VM() *schema.Resource { Optional: true, Default: dvResourceVirtualEnvironmentVMDiskDiscard, }, + mkResourceVirtualEnvironmentVMDiskCache: { + Type: schema.TypeString, + Description: "The drive’s cache mode", + Optional: true, + Default: dvResourceVirtualEnvironmentVMDiskCache, + ValidateDiagFunc: validation.ToDiagFunc( + validation.StringInSlice([]string{ + "none", + "writethrough", + "writeback", + "unsafe", + "directsync", + }, false), + ), + }, mkResourceVirtualEnvironmentVMDiskSpeed: { Type: schema.TypeList, Description: "The speed limits", @@ -2360,6 +2378,7 @@ func vmCreateCustomDisks(ctx context.Context, d *schema.ResourceData, m interfac ioThread := types.CustomBool(block[mkResourceVirtualEnvironmentVMDiskIOThread].(bool)) ssd := types.CustomBool(block[mkResourceVirtualEnvironmentVMDiskSSD].(bool)) discard, _ := block[mkResourceVirtualEnvironmentVMDiskDiscard].(string) + cache, _ := block[mkResourceVirtualEnvironmentVMDiskCache].(string) if fileFormat == "" { fileFormat = dvResourceVirtualEnvironmentVMDiskFileFormat @@ -2393,6 +2412,10 @@ func vmCreateCustomDisks(ctx context.Context, d *schema.ResourceData, m interfac diskOptions += fmt.Sprintf(",discard=%s", discard) } + if cache != "" { + diskOptions += fmt.Sprintf(",cache=%s", cache) + } + if speedLimitRead > 0 { diskOptions += fmt.Sprintf(",mbps_rd=%d", speedLimitRead) } @@ -2722,6 +2745,7 @@ func vmGetDiskDeviceObjects( ioThread := types.CustomBool(block[mkResourceVirtualEnvironmentVMDiskIOThread].(bool)) ssd := types.CustomBool(block[mkResourceVirtualEnvironmentVMDiskSSD].(bool)) discard := block[mkResourceVirtualEnvironmentVMDiskDiscard].(string) + cache := block[mkResourceVirtualEnvironmentVMDiskCache].(string) speedBlock, err := structure.GetSchemaBlock( resource, @@ -2752,6 +2776,7 @@ func vmGetDiskDeviceObjects( diskDevice.SizeInt = &size diskDevice.IOThread = &ioThread diskDevice.Discard = &discard + diskDevice.Cache = &cache if !strings.HasPrefix(diskInterface, "virtio") { diskDevice.SSD = &ssd @@ -3480,6 +3505,12 @@ func vmReadCustom( disk[mkResourceVirtualEnvironmentVMDiskDiscard] = "" } + if dd.Cache != nil { + disk[mkResourceVirtualEnvironmentVMDiskCache] = *dd.Cache + } else { + disk[mkResourceVirtualEnvironmentVMDiskCache] = "" + } + diskMap[di] = disk }