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

feat(vm,lxc): Improved support for different disk size units (#326)

This commit is contained in:
Jordan Keith 2023-05-10 21:46:16 +10:00 committed by GitHub
parent d94a4ce7cf
commit 4be9914757
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 278 additions and 138 deletions

View File

@ -1,6 +1,8 @@
/* This Source Code Form is subject to the terms of the Mozilla Public /*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */ * file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package types package types
@ -151,7 +153,7 @@ func (r *CustomPrivileges) UnmarshalJSON(b []byte) error {
return nil return nil
} }
// MarshalJSON converts a boolean to a JSON value. // MarshalJSON converts a timestamp to a JSON value.
func (r CustomTimestamp) MarshalJSON() ([]byte, error) { func (r CustomTimestamp) MarshalJSON() ([]byte, error) {
timestamp := time.Time(r) timestamp := time.Time(r)
buffer := bytes.NewBufferString(strconv.FormatInt(timestamp.Unix(), 10)) buffer := bytes.NewBufferString(strconv.FormatInt(timestamp.Unix(), 10))
@ -159,7 +161,7 @@ func (r CustomTimestamp) MarshalJSON() ([]byte, error) {
return buffer.Bytes(), nil return buffer.Bytes(), nil
} }
// UnmarshalJSON converts a JSON value to a boolean. // UnmarshalJSON converts a JSON value to a timestamp.
func (r *CustomTimestamp) UnmarshalJSON(b []byte) error { func (r *CustomTimestamp) UnmarshalJSON(b []byte) error {
s := string(b) s := string(b)
i, err := strconv.ParseInt(s, 10, 64) i, err := strconv.ParseInt(s, 10, 64)

113
proxmox/types/disk_size.go Normal file
View File

@ -0,0 +1,113 @@
/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package types
import (
"encoding/json"
"fmt"
"math"
"regexp"
"strconv"
"strings"
)
// Regex used to identify size strings. Case-insensitive. Covers megabytes, gigabytes and terabytes.
var sizeRegex = regexp.MustCompile(`(?i)^(\d+(\.\d+)?)(k|kb|kib|m|mb|mib|g|gb|gib|t|tb|tib)?$`)
// DiskSize allows a JSON integer value to also be a string. This is mapped to `<DiskSize>` data type in Proxmox API.
// Represents a disk size in bytes.
type DiskSize int64
// String returns the string representation of the disk size.
func (r DiskSize) String() string {
return formatDiskSize(int64(r))
}
// InGigabytes returns the disk size in gigabytes.
func (r DiskSize) InGigabytes() int {
return int(int64(r) / 1024 / 1024 / 1024)
}
// DiskSizeFromGigabytes creates a DiskSize from gigabytes.
func DiskSizeFromGigabytes(size int) DiskSize {
return DiskSize(size * 1024 * 1024 * 1024)
}
// MarshalJSON marshals a disk size into a Proxmox API `<DiskSize>` string.
func (r DiskSize) MarshalJSON() ([]byte, error) {
bytes, err := json.Marshal(formatDiskSize(int64(r)))
if err != nil {
return nil, fmt.Errorf("cannot marshal disk size: %w", err)
}
return bytes, nil
}
// UnmarshalJSON unmarshals a disk size from a Proxmox API `<DiskSize>` string.
func (r *DiskSize) UnmarshalJSON(b []byte) error {
s := string(b)
size, err := parseDiskSize(&s)
if err != nil {
return err
}
*r = DiskSize(size)
return nil
}
// parseDiskSize parses a disk size string into a number of bytes
func parseDiskSize(size *string) (int64, error) {
if size == nil {
return 0, nil
}
matches := sizeRegex.FindStringSubmatch(*size)
if len(matches) > 0 {
fsize, err := strconv.ParseFloat(matches[1], 64)
if err != nil {
return -1, fmt.Errorf("cannot parse disk size \"%s\": %w", *size, err)
}
switch strings.ToLower(matches[3]) {
case "k", "kb", "kib":
fsize *= 1024
case "m", "mb", "mib":
fsize = fsize * 1024 * 1024
case "g", "gb", "gib":
fsize = fsize * 1024 * 1024 * 1024
case "t", "tb", "tib":
fsize = fsize * 1024 * 1024 * 1024 * 1024
}
return int64(math.Ceil(fsize)), nil
}
return -1, fmt.Errorf("cannot parse disk size \"%s\"", *size)
}
func formatDiskSize(size int64) string {
if size < 0 {
return ""
}
if size < 1024 {
return fmt.Sprintf("%d", size)
}
if size < 1024*1024 {
return fmt.Sprintf("%.2gK", float64(size)/1024)
}
if size < 1024*1024*1024 {
return fmt.Sprintf("%.2gM", float64(size)/1024/1024)
}
if size < 1024*1024*1024*1024 {
return fmt.Sprintf("%.2gG", float64(size)/1024/1024/1024)
}
return fmt.Sprintf("%.2gT", float64(size)/1024/1024/1024/1024)
}

View File

@ -0,0 +1,77 @@
/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package types
import "testing"
func TestParseDiskSize(t *testing.T) {
t.Parallel()
tests := []struct {
name string
size *string
want int64
wantErr bool
}{
{"handle null size", nil, 0, false},
{"parse TB", StrPtr("2TB"), 2199023255552, false},
{"parse T", StrPtr("2T"), 2199023255552, false},
{"parse fraction T", StrPtr("2.2T"), 2418925581108, false},
{"parse GB", StrPtr("2GB"), 2147483648, false},
{"parse G", StrPtr("2G"), 2147483648, false},
{"parse M", StrPtr("2048M"), 2147483648, false},
{"parse MB", StrPtr("2048MB"), 2147483648, false},
{"parse MiB", StrPtr("2048MiB"), 2147483648, false},
{"parse K", StrPtr("1K"), 1024, false},
{"parse KB", StrPtr("2KB"), 2048, false},
{"parse KiB", StrPtr("4KiB"), 4096, false},
{"parse no units as bytes", StrPtr("12345"), 12345, false},
{"error on bad format string", StrPtr("20l8G"), -1, true},
{"error on unknown unit string", StrPtr("2048W"), -1, true},
{"error on arbitrary string", StrPtr("something"), -1, true},
}
for _, test := range tests {
tt := test
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
got, err := parseDiskSize(tt.size)
if (err != nil) != tt.wantErr {
t.Errorf("parseDiskSize() error = %v, wantErr %v", err, tt.wantErr)
return
}
if got != tt.want {
t.Errorf("parseDiskSize() got = %v, want %v", got, tt.want)
}
})
}
}
func TestFormatDiskSize(t *testing.T) {
t.Parallel()
tests := []struct {
name string
size int64
want string
}{
{"handle 0 size", 0, "0"},
{"handle bytes", 1001, "1001"},
{"handle kilobytes", 1234, "1.2K"},
{"handle megabytes", 2097152, "2M"},
{"handle gigabytes", 2147483648, "2G"},
{"handle terabytes", 2199023255552, "2T"},
}
for _, test := range tests {
tt := test
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
if got := formatDiskSize(tt.size); got != tt.want {
t.Errorf("formatDiskSize() = %v, want %v", got, tt.want)
}
})
}
}

18
proxmox/types/helpers.go Normal file
View File

@ -0,0 +1,18 @@
/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package types
// StrPtr returns a pointer to a string.
func StrPtr(s string) *string {
return &s
}
// BoolPtr returns a pointer to a bool.
func BoolPtr(s bool) *CustomBool {
customBool := CustomBool(s)
return &customBool
}

View File

@ -1,16 +1,14 @@
/* This Source Code Form is subject to the terms of the Mozilla Public /*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */ * file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package proxmox package proxmox
import ( import (
"context" "context"
"fmt"
"io" "io"
"math"
"strconv"
"strings"
"github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-plugin-log/tflog"
) )
@ -24,35 +22,3 @@ func CloseOrLogError(ctx context.Context) func(io.Closer) {
} }
} }
} }
func ParseDiskSize(size *string) (int, error) {
if size == nil {
return 0, nil
}
if strings.HasSuffix(*size, "T") {
diskSize, err := strconv.Atoi(strings.TrimSuffix(*size, "T"))
if err != nil {
return -1, fmt.Errorf("failed to parse disk size: %w", err)
}
return int(math.Ceil(float64(diskSize) * 1024)), nil
}
if strings.HasSuffix(*size, "G") {
diskSize, err := strconv.Atoi(strings.TrimSuffix(*size, "G"))
if err != nil {
return -1, fmt.Errorf("failed to parse disk size: %w", err)
}
return diskSize, nil
}
if strings.HasSuffix(*size, "M") {
diskSize, err := strconv.Atoi(strings.TrimSuffix(*size, "M"))
if err != nil {
return -1, fmt.Errorf("failed to parse disk size: %w", err)
}
return int(math.Ceil(float64(diskSize) / 1024)), nil
}
return -1, fmt.Errorf("cannot parse disk size \"%s\"", *size)
}

View File

@ -1,3 +1,9 @@
/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package proxmox package proxmox
import ( import (
@ -8,38 +14,6 @@ import (
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )
func TestParseDiskSize(t *testing.T) {
t.Parallel()
tests := []struct {
name string
size *string
want int
wantErr bool
}{
{"handle null size", nil, 0, false},
{"parse terabytes", strPtr("2T"), 2048, false},
{"parse gigabytes", strPtr("2G"), 2, false},
{"parse megabytes", strPtr("2048M"), 2, false},
{"error on arbitrary string", strPtr("something"), -1, true},
{"error on missing unit", strPtr("12345"), -1, true},
}
for _, test := range tests {
tt := test
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
got, err := ParseDiskSize(tt.size)
if (err != nil) != tt.wantErr {
t.Errorf("ParseDiskSize() error = %v, wantErr %v", err, tt.wantErr)
return
}
if got != tt.want {
t.Errorf("ParseDiskSize() got = %v, want %v", got, tt.want)
}
})
}
}
func TestCloseOrLogError(t *testing.T) { func TestCloseOrLogError(t *testing.T) {
t.Parallel() t.Parallel()
f := CloseOrLogError(context.Background()) f := CloseOrLogError(context.Background())

View File

@ -1,6 +1,8 @@
/* This Source Code Form is subject to the terms of the Mozilla Public /*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */ * file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package proxmox package proxmox
@ -120,7 +122,7 @@ type VirtualEnvironmentContainerCustomNetworkInterfaceArray []VirtualEnvironment
// VirtualEnvironmentContainerCustomRootFS contains the values for the "rootfs" property. // VirtualEnvironmentContainerCustomRootFS contains the values for the "rootfs" property.
type VirtualEnvironmentContainerCustomRootFS struct { type VirtualEnvironmentContainerCustomRootFS struct {
ACL *types.CustomBool `json:"acl,omitempty" url:"acl,omitempty,int"` ACL *types.CustomBool `json:"acl,omitempty" url:"acl,omitempty,int"`
DiskSize *string `json:"size,omitempty" url:"size,omitempty"` Size *types.DiskSize `json:"size,omitempty" url:"size,omitempty"`
MountOptions *[]string `json:"mountoptions,omitempty" url:"mountoptions,omitempty"` MountOptions *[]string `json:"mountoptions,omitempty" url:"mountoptions,omitempty"`
Quota *types.CustomBool `json:"quota,omitempty" url:"quota,omitempty,int"` Quota *types.CustomBool `json:"quota,omitempty" url:"quota,omitempty,int"`
ReadOnly *types.CustomBool `json:"ro,omitempty" url:"ro,omitempty,int"` ReadOnly *types.CustomBool `json:"ro,omitempty" url:"ro,omitempty,int"`
@ -449,8 +451,8 @@ func (r VirtualEnvironmentContainerCustomRootFS) EncodeValues(key string, v *url
} }
} }
if r.DiskSize != nil { if r.Size != nil {
values = append(values, fmt.Sprintf("size=%s", *r.DiskSize)) values = append(values, fmt.Sprintf("size=%s", *r.Size))
} }
if r.MountOptions != nil { if r.MountOptions != nil {
@ -753,7 +755,11 @@ func (r *VirtualEnvironmentContainerCustomRootFS) UnmarshalJSON(b []byte) error
bv := types.CustomBool(v[1] == "1") bv := types.CustomBool(v[1] == "1")
r.Shared = &bv r.Shared = &bv
case "size": case "size":
r.DiskSize = &v[1] 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)
}
} }
} }
} }

View File

@ -1,6 +1,8 @@
/* This Source Code Form is subject to the terms of the Mozilla Public /*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */ * file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package proxmox package proxmox
@ -78,9 +80,9 @@ type CustomCPUEmulation struct {
// CustomEFIDisk handles QEMU EFI disk parameters. // CustomEFIDisk handles QEMU EFI disk parameters.
type CustomEFIDisk struct { type CustomEFIDisk struct {
DiskSize *int `json:"size,omitempty" url:"size,omitempty"` Size *types.DiskSize `json:"size,omitempty" url:"size,omitempty"`
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"`
} }
// CustomNetworkDevice handles QEMU network device parameters. // CustomNetworkDevice handles QEMU network device parameters.
@ -174,7 +176,7 @@ type CustomStorageDevice struct {
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"`
Size *string `json:"size,omitempty" url:"size,omitempty"` Size *types.DiskSize `json:"size,omitempty" url:"size,omitempty"`
Interface *string Interface *string
ID *string ID *string
FileID *string FileID *string
@ -560,7 +562,7 @@ type VirtualEnvironmentVMRebootResponseBody struct {
type VirtualEnvironmentVMResizeDiskRequestBody struct { type VirtualEnvironmentVMResizeDiskRequestBody struct {
Digest *string `json:"digest,omitempty" url:"digest,omitempty"` Digest *string `json:"digest,omitempty" url:"digest,omitempty"`
Disk string `json:"disk" url:"disk"` Disk string `json:"disk" url:"disk"`
Size string `json:"size" url:"size"` Size types.DiskSize `json:"size" url:"size"`
SkipLock *types.CustomBool `json:"skiplock,omitempty" url:"skiplock,omitempty,int"` SkipLock *types.CustomBool `json:"skiplock,omitempty" url:"skiplock,omitempty,int"`
} }
@ -778,8 +780,8 @@ func (r CustomEFIDisk) EncodeValues(key string, v *url.Values) error {
values = append(values, fmt.Sprintf("format=%s", *r.Format)) values = append(values, fmt.Sprintf("format=%s", *r.Format))
} }
if r.DiskSize != nil { if r.Size != nil {
values = append(values, fmt.Sprintf("size=%d", *r.DiskSize)) values = append(values, fmt.Sprintf("size=%s", *r.Size))
} }
v.Add(key, strings.Join(values, ",")) v.Add(key, strings.Join(values, ","))
@ -1490,12 +1492,11 @@ func (r *CustomEFIDisk) UnmarshalJSON(b []byte) error {
case "file": case "file":
r.FileVolume = v[1] r.FileVolume = v[1]
case "size": case "size":
iv, err := ParseDiskSize(&v[1]) r.Size = new(types.DiskSize)
err := r.Size.UnmarshalJSON([]byte(v[1]))
if err != nil { if err != nil {
return err return fmt.Errorf("failed to unmarshal disk size: %w", err)
} }
r.DiskSize = &iv
} }
} }
} }
@ -1754,7 +1755,11 @@ func (r *CustomStorageDevice) UnmarshalJSON(b []byte) error {
case "media": case "media":
r.Media = &v[1] r.Media = &v[1]
case "size": case "size":
r.Size = &v[1] 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": case "format":
r.Format = &v[1] r.Format = &v[1]
case "iothread": case "iothread":

View File

@ -1,3 +1,9 @@
/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package proxmox package proxmox
import ( import (
@ -9,6 +15,7 @@ import (
) )
func TestCustomStorageDevice_UnmarshalJSON(t *testing.T) { func TestCustomStorageDevice_UnmarshalJSON(t *testing.T) {
ds8gig := types.DiskSizeFromGigabytes(8)
tests := []struct { tests := []struct {
name string name string
line string line string
@ -19,25 +26,25 @@ func TestCustomStorageDevice_UnmarshalJSON(t *testing.T) {
name: "simple volume", 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"`,
want: &CustomStorageDevice{ want: &CustomStorageDevice{
Discard: strPtr("on"), Discard: types.StrPtr("on"),
Enabled: true, Enabled: true,
FileVolume: "local-lvm:vm-2041-disk-0", FileVolume: "local-lvm:vm-2041-disk-0",
IOThread: boolPtr(true), IOThread: types.BoolPtr(true),
Size: strPtr("8G"), Size: &ds8gig,
SSD: boolPtr(true), SSD: types.BoolPtr(true),
}, },
}, },
{ {
name: "raw volume type", name: "raw volume type",
line: `"nfs:2041/vm-2041-disk-0.raw,discard=ignore,ssd=1,iothread=1,size=8G"`, line: `"nfs:2041/vm-2041-disk-0.raw,discard=ignore,ssd=1,iothread=1,size=8G"`,
want: &CustomStorageDevice{ want: &CustomStorageDevice{
Discard: strPtr("ignore"), Discard: types.StrPtr("ignore"),
Enabled: true, Enabled: true,
FileVolume: "nfs:2041/vm-2041-disk-0.raw", FileVolume: "nfs:2041/vm-2041-disk-0.raw",
Format: strPtr("raw"), Format: types.StrPtr("raw"),
IOThread: boolPtr(true), IOThread: types.BoolPtr(true),
Size: strPtr("8G"), Size: &ds8gig,
SSD: boolPtr(true), SSD: types.BoolPtr(true),
}, },
}, },
} }
@ -51,12 +58,3 @@ func TestCustomStorageDevice_UnmarshalJSON(t *testing.T) {
}) })
} }
} }
func strPtr(s string) *string {
return &s
}
func boolPtr(s bool) *types.CustomBool {
customBool := types.CustomBool(s)
return &customBool
}

View File

@ -1626,12 +1626,7 @@ func containerRead(ctx context.Context, d *schema.ResourceData, m interface{}) d
if containerConfig.RootFS != nil { if containerConfig.RootFS != nil {
volumeParts := strings.Split(containerConfig.RootFS.Volume, ":") volumeParts := strings.Split(containerConfig.RootFS.Volume, ":")
disk[mkResourceVirtualEnvironmentContainerDiskDatastoreID] = volumeParts[0] disk[mkResourceVirtualEnvironmentContainerDiskDatastoreID] = volumeParts[0]
disk[mkResourceVirtualEnvironmentContainerDiskSize] = containerConfig.RootFS.Size.InGigabytes()
diskSize, err := proxmox.ParseDiskSize(containerConfig.RootFS.DiskSize)
if err != nil {
return diag.FromErr(err)
}
disk[mkResourceVirtualEnvironmentContainerDiskSize] = diskSize
} else { } else {
// Default value of "storage" is "local" according to the API documentation. // Default value of "storage" is "local" according to the API documentation.
disk[mkResourceVirtualEnvironmentContainerDiskDatastoreID] = "local" disk[mkResourceVirtualEnvironmentContainerDiskDatastoreID] = "local"

View File

@ -1720,12 +1720,7 @@ func vmCreateClone(ctx context.Context, d *schema.ResourceData, m interface{}) d
continue continue
} }
compareNumber, err := proxmox.ParseDiskSize(currentDiskInfo.Size) if diskSize < currentDiskInfo.Size.InGigabytes() {
if err != nil {
return diag.FromErr(err)
}
if diskSize < compareNumber {
return diag.Errorf( return diag.Errorf(
"disk resize fails requests size (%dG) is lower than current size (%s)", "disk resize fails requests size (%dG) is lower than current size (%s)",
diskSize, diskSize,
@ -1743,7 +1738,7 @@ func vmCreateClone(ctx context.Context, d *schema.ResourceData, m interface{}) d
diskResizeBody := &proxmox.VirtualEnvironmentVMResizeDiskRequestBody{ diskResizeBody := &proxmox.VirtualEnvironmentVMResizeDiskRequestBody{
Disk: diskInterface, Disk: diskInterface,
Size: fmt.Sprintf("%dG", diskSize), Size: types.DiskSizeFromGigabytes(diskSize),
} }
moveDisk := false moveDisk := false
@ -1765,7 +1760,7 @@ func vmCreateClone(ctx context.Context, d *schema.ResourceData, m interface{}) d
} }
} }
if diskSize > compareNumber { if diskSize > currentDiskInfo.Size.InGigabytes() {
err = veClient.ResizeVMDisk(ctx, nodeName, vmID, diskResizeBody) err = veClient.ResizeVMDisk(ctx, nodeName, vmID, diskResizeBody)
if err != nil { if err != nil {
return diag.FromErr(err) return diag.FromErr(err)
@ -2505,8 +2500,8 @@ func vmGetDiskDeviceObjects(
diskDevice.Interface = &diskInterface diskDevice.Interface = &diskInterface
diskDevice.Format = &fileFormat diskDevice.Format = &fileFormat
diskDevice.FileID = &fileID diskDevice.FileID = &fileID
sizeString := fmt.Sprintf("%dG", size) diskSize := types.DiskSizeFromGigabytes(size)
diskDevice.Size = &sizeString diskDevice.Size = &diskSize
diskDevice.SizeInt = &size diskDevice.SizeInt = &size
diskDevice.IOThread = &ioThread diskDevice.IOThread = &ioThread
diskDevice.Discard = &discard diskDevice.Discard = &discard
@ -3060,16 +3055,7 @@ func vmReadCustom(
} }
disk[mkResourceVirtualEnvironmentVMDiskInterface] = di disk[mkResourceVirtualEnvironmentVMDiskInterface] = di
disk[mkResourceVirtualEnvironmentVMDiskSize] = dd.Size.InGigabytes()
diskSize := 0
var err error
diskSize, err = proxmox.ParseDiskSize(dd.Size)
if err != nil {
return diag.FromErr(err)
}
disk[mkResourceVirtualEnvironmentVMDiskSize] = diskSize
if dd.BurstableReadSpeedMbps != nil || if dd.BurstableReadSpeedMbps != nil ||
dd.BurstableWriteSpeedMbps != nil || dd.BurstableWriteSpeedMbps != nil ||