Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[3.0.1-rc1] Feature: KMGT disk size #929

Merged
merged 6 commits into from
Feb 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions docs/resources/vm_qemu.md
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,7 @@ details.
| `rate` | `int` | `0` | Network device rate limit in mbps (megabytes per second) as floating point number. Set to `0` to disable rate limiting. |
| `queues` | `int` | `1` | Number of packet queues to be used on the device. Requires `virtio` model to have an effect. |
| `link_down` | `bool` | `false` | Whether this interface should be disconnected (like pulling the plug). |

### Disks Block

The `disks` block is used to configure the disk devices. It may be specified once. There are four types of disk `ide`,`sata`,`scsi` and `virtio`. Configuration for these sub types can be found in their respective chapters:
Expand Down Expand Up @@ -367,7 +368,7 @@ See the [docs about disks](https://pve.proxmox.com/pve-docs/chapter-qm.html#qm_h
| `readonly` | `bool` | `false` | `scsi`, `virtio` | Whether the drive should be readonly. |
| `replicate` | `bool` | `false` | `all` | Whether the drive should considered for replication jobs. |
| `serial` | `str` | | `all` | The serial number of the disk. |
| `size` | `int` | | `all` | **Required** The size of the created disk in Gigabytes. |
| `size` | `string`| | `all` | **Required** The size of the created disk. Accepts `K` for kibibytes, `M` for mebibytes, `G` for gibibytes, `T` for tibibytes. When only a number is provided gibibytes is assumed.|
| `storage` | `str` | | `all` | **Required** The name of the storage pool on which to store the disk. |

### Disks.x.Passthrough Block
Expand Down Expand Up @@ -396,7 +397,7 @@ See the [docs about disks](https://pve.proxmox.com/pve-docs/chapter-qm.html#qm_h
| `readonly` | `bool` | `false` | `scsi`, `virtio` | Whether the drive should be readonly. |
| `replicate` | `bool` | `false` | `all` | Whether the drive should considered for replication jobs. |
| `serial` | `str` | | `all` | The serial number of the disk. |
| `size` | `int` | | `all` | **Computed** Size of the disk. |
| `size` | `string`| | `all` | **Computed** Size of the disk, `K` for kibibytes, `M` for mebibytes, `G` for gibibytes, `T` for tibibytes.|

### EFI Disk Block

Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ module github.com/Telmate/terraform-provider-proxmox/v2
go 1.20

require (
github.com/Telmate/proxmox-api-go v0.0.0-20240131155550-58f6bb52981b
github.com/Telmate/proxmox-api-go v0.0.0-20240205124300-ede76bab601e
github.com/google/uuid v1.6.0
github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320
github.com/hashicorp/terraform-plugin-sdk/v2 v2.32.0
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk=
github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow=
github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371 h1:kkhsdkhsCvIsutKu5zLMgWtgh9YxGCNAw8Ad8hjwfYg=
github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371/go.mod h1:EjAoLdwvbIOoOQr3ihjnSoLZRtE8azugULFRteWMNc0=
github.com/Telmate/proxmox-api-go v0.0.0-20240131155550-58f6bb52981b h1:PdwcMpUQ1tLfUhW2f3QKi4ZxObZSZ2ShBfM1vjJ8+Zw=
github.com/Telmate/proxmox-api-go v0.0.0-20240131155550-58f6bb52981b/go.mod h1:xOwyTd8uC2IiYfmjwCVU2fTTVToFCm9yxJzn4cd7rPw=
github.com/Telmate/proxmox-api-go v0.0.0-20240205124300-ede76bab601e h1:ojWFe4idcU9W/0GzBjoZQBaTp0ugRfG4XC7mfWHV0Xk=
github.com/Telmate/proxmox-api-go v0.0.0-20240205124300-ede76bab601e/go.mod h1:xOwyTd8uC2IiYfmjwCVU2fTTVToFCm9yxJzn4cd7rPw=
github.com/agext/levenshtein v1.2.3 h1:YB2fHEn0UJagG8T1rrWknE3ZQzWM06O8AMAatNn7lmo=
github.com/agext/levenshtein v1.2.3/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558=
github.com/apparentlymart/go-textseg/v12 v12.0.0/go.mod h1:S/4uRK2UtaQttw1GenVJEynmyUenKwP++x/+DdGV/Ec=
Expand Down
49 changes: 49 additions & 0 deletions proxmox/converters.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package proxmox

import (
"strconv"
)

const (
kibibyte int64 = 1
mebibyte int64 = 1024
gibibyte int64 = 1048576
tebibyte int64 = 1073741824
)

func convert_KibibytesToString(kibibytes int64) string {

Check failure on line 14 in proxmox/converters.go

View workflow job for this annotation

GitHub Actions / audit

don't use underscores in Go names; func convert_KibibytesToString should be convertKibibytesToString
if kibibytes%tebibyte == 0 {
return strconv.FormatInt(kibibytes/tebibyte, 10) + "T"
}
if kibibytes%gibibyte == 0 {
return strconv.FormatInt(kibibytes/gibibyte, 10) + "G"
}
if kibibytes%mebibyte == 0 {
return strconv.FormatInt(kibibytes/mebibyte, 10) + "M"
}
return strconv.FormatInt(kibibytes, 10) + "K"
}

// Relies on the input being validated
func convert_SizeStringToKibibytes_Unsafe(size string) int {

Check failure on line 28 in proxmox/converters.go

View workflow job for this annotation

GitHub Actions / audit

don't use underscores in Go names; func convert_SizeStringToKibibytes_Unsafe should be convertSizeStringToKibibytesUnsafe
if len(size) > 1 {
switch size[len(size)-1:] {
case "T":
return parseSize_Unsafe(size, tebibyte)
case "G":
return parseSize_Unsafe(size, gibibyte)
case "M":
return parseSize_Unsafe(size, mebibyte)
case "K":
return parseSize_Unsafe(size, kibibyte)
}
}
tmpSize, _ := strconv.ParseInt(size, 10, 0)
return int(tmpSize * gibibyte)
}

// Relies on the input being validated
func parseSize_Unsafe(size string, multiplier int64) int {

Check failure on line 46 in proxmox/converters.go

View workflow job for this annotation

GitHub Actions / audit

don't use underscores in Go names; func parseSize_Unsafe should be parseSizeUnsafe
tmpSize, _ := strconv.ParseInt(size[:len(size)-1], 10, 0)
return int(tmpSize * multiplier)
}
106 changes: 59 additions & 47 deletions proxmox/resource_vm_qemu.go
Original file line number Diff line number Diff line change
Expand Up @@ -2121,7 +2121,7 @@ func mapFromStruct_QemuIdeStorage(config *pxapi.QemuIdeStorage, setting string)
"linked_disk_id": mapFromStruct_LinkedCloneId(config.Disk.LinkedDiskId),
"replicate": config.Disk.Replicate,
"serial": string(config.Disk.Serial),
"size": int(config.Disk.Size),
"size": convert_KibibytesToString(int64(config.Disk.SizeInKibibytes)),
"storage": string(config.Disk.Storage),
}
mapFormStruct_QemuDiskBandwidth(mapParams, config.Disk.Bandwidth)
Expand All @@ -2141,7 +2141,7 @@ func mapFromStruct_QemuIdeStorage(config *pxapi.QemuIdeStorage, setting string)
"file": config.Passthrough.File,
"replicate": config.Passthrough.Replicate,
"serial": string(config.Passthrough.Serial),
"size": int(config.Passthrough.Size),
"size": convert_KibibytesToString(int64(config.Passthrough.SizeInKibibytes)),
}
mapFormStruct_QemuDiskBandwidth(mapParams, config.Passthrough.Bandwidth)
return []interface{}{
Expand Down Expand Up @@ -2185,7 +2185,7 @@ func mapFromStruct_QemuSataStorage(config *pxapi.QemuSataStorage, setting string
"linked_disk_id": mapFromStruct_LinkedCloneId(config.Disk.LinkedDiskId),
"replicate": config.Disk.Replicate,
"serial": string(config.Disk.Serial),
"size": int(config.Disk.Size),
"size": convert_KibibytesToString(int64(config.Disk.SizeInKibibytes)),
"storage": string(config.Disk.Storage),
}
mapFormStruct_QemuDiskBandwidth(mapParams, config.Disk.Bandwidth)
Expand All @@ -2205,7 +2205,7 @@ func mapFromStruct_QemuSataStorage(config *pxapi.QemuSataStorage, setting string
"file": config.Passthrough.File,
"replicate": config.Passthrough.Replicate,
"serial": string(config.Passthrough.Serial),
"size": int(config.Passthrough.Size),
"size": convert_KibibytesToString(int64(config.Disk.SizeInKibibytes)),
}
mapFormStruct_QemuDiskBandwidth(mapParams, config.Passthrough.Bandwidth)
return []interface{}{
Expand Down Expand Up @@ -2276,7 +2276,7 @@ func mapFromStruct_QemuScsiStorage(config *pxapi.QemuScsiStorage, setting string
"readonly": config.Disk.ReadOnly,
"replicate": config.Disk.Replicate,
"serial": string(config.Disk.Serial),
"size": int(config.Disk.Size),
"size": convert_KibibytesToString(int64(config.Disk.SizeInKibibytes)),
"storage": string(config.Disk.Storage),
}
mapFormStruct_QemuDiskBandwidth(mapParams, config.Disk.Bandwidth)
Expand All @@ -2298,7 +2298,7 @@ func mapFromStruct_QemuScsiStorage(config *pxapi.QemuScsiStorage, setting string
"readonly": config.Passthrough.ReadOnly,
"replicate": config.Passthrough.Replicate,
"serial": string(config.Passthrough.Serial),
"size": int(config.Passthrough.Size),
"size": convert_KibibytesToString(int64(config.Passthrough.SizeInKibibytes)),
}
mapFormStruct_QemuDiskBandwidth(mapParams, config.Passthrough.Bandwidth)
return []interface{}{
Expand Down Expand Up @@ -2354,7 +2354,7 @@ func mapFromStruct_QemuVirtIOStorage(config *pxapi.QemuVirtIOStorage, setting st
"readonly": config.Disk.ReadOnly,
"replicate": config.Disk.Replicate,
"serial": string(config.Disk.Serial),
"size": int(config.Disk.Size),
"size": convert_KibibytesToString(int64(config.Disk.SizeInKibibytes)),
"storage": string(config.Disk.Storage),
}
mapFormStruct_QemuDiskBandwidth(mapParams, config.Disk.Bandwidth)
Expand All @@ -2375,7 +2375,7 @@ func mapFromStruct_QemuVirtIOStorage(config *pxapi.QemuVirtIOStorage, setting st
"readonly": config.Passthrough.ReadOnly,
"replicate": config.Passthrough.Replicate,
"serial": string(config.Passthrough.Serial),
"size": int(config.Passthrough.Size),
"size": convert_KibibytesToString(int64(config.Passthrough.SizeInKibibytes)),
}
mapFormStruct_QemuDiskBandwidth(mapParams, config.Passthrough.Bandwidth)
return []interface{}{
Expand Down Expand Up @@ -2465,14 +2465,14 @@ func mapToStruct_QemuIdeStorage(ide *pxapi.QemuIdeStorage, key string, schema ma
if ok && len(tmpDisk) == 1 && tmpDisk[0] != nil {
disk := tmpDisk[0].(map[string]interface{})
ide.Disk = &pxapi.QemuIdeDisk{
Backup: disk["backup"].(bool),
Bandwidth: mapToStruct_QemuDiskBandwidth(disk),
Discard: disk["discard"].(bool),
EmulateSSD: disk["emulatessd"].(bool),
Format: pxapi.QemuDiskFormat(disk["format"].(string)),
Replicate: disk["replicate"].(bool),
Size: uint(disk["size"].(int)),
Storage: disk["storage"].(string),
Backup: disk["backup"].(bool),
Bandwidth: mapToStruct_QemuDiskBandwidth(disk),
Discard: disk["discard"].(bool),
EmulateSSD: disk["emulatessd"].(bool),
Format: pxapi.QemuDiskFormat(disk["format"].(string)),
Replicate: disk["replicate"].(bool),
SizeInKibibytes: pxapi.QemuDiskSize(convert_SizeStringToKibibytes_Unsafe(disk["size"].(string))),
Storage: disk["storage"].(string),
}
if asyncIO, ok := disk["asyncio"].(string); ok {
ide.Disk.AsyncIO = pxapi.QemuDiskAsyncIO(asyncIO)
Expand Down Expand Up @@ -2534,14 +2534,14 @@ func mapToStruct_QemuSataStorage(sata *pxapi.QemuSataStorage, key string, schema
if ok && len(tmpDisk) == 1 && tmpDisk[0] != nil {
disk := tmpDisk[0].(map[string]interface{})
sata.Disk = &pxapi.QemuSataDisk{
Backup: disk["backup"].(bool),
Bandwidth: mapToStruct_QemuDiskBandwidth(disk),
Discard: disk["discard"].(bool),
EmulateSSD: disk["emulatessd"].(bool),
Format: pxapi.QemuDiskFormat(disk["format"].(string)),
Replicate: disk["replicate"].(bool),
Size: uint(disk["size"].(int)),
Storage: disk["storage"].(string),
Backup: disk["backup"].(bool),
Bandwidth: mapToStruct_QemuDiskBandwidth(disk),
Discard: disk["discard"].(bool),
EmulateSSD: disk["emulatessd"].(bool),
Format: pxapi.QemuDiskFormat(disk["format"].(string)),
Replicate: disk["replicate"].(bool),
SizeInKibibytes: pxapi.QemuDiskSize(convert_SizeStringToKibibytes_Unsafe(disk["size"].(string))),
Storage: disk["storage"].(string),
}
if asyncIO, ok := disk["asyncio"].(string); ok {
sata.Disk.AsyncIO = pxapi.QemuDiskAsyncIO(asyncIO)
Expand Down Expand Up @@ -2628,16 +2628,16 @@ func mapToStruct_QemuScsiStorage(scsi *pxapi.QemuScsiStorage, key string, schema
if ok && len(tmpDisk) == 1 && tmpDisk[0] != nil {
disk := tmpDisk[0].(map[string]interface{})
scsi.Disk = &pxapi.QemuScsiDisk{
Backup: disk["backup"].(bool),
Bandwidth: mapToStruct_QemuDiskBandwidth(disk),
Discard: disk["discard"].(bool),
EmulateSSD: disk["emulatessd"].(bool),
Format: pxapi.QemuDiskFormat(disk["format"].(string)),
IOThread: disk["iothread"].(bool),
ReadOnly: disk["readonly"].(bool),
Replicate: disk["replicate"].(bool),
Size: uint(disk["size"].(int)),
Storage: disk["storage"].(string),
Backup: disk["backup"].(bool),
Bandwidth: mapToStruct_QemuDiskBandwidth(disk),
Discard: disk["discard"].(bool),
EmulateSSD: disk["emulatessd"].(bool),
Format: pxapi.QemuDiskFormat(disk["format"].(string)),
IOThread: disk["iothread"].(bool),
ReadOnly: disk["readonly"].(bool),
Replicate: disk["replicate"].(bool),
SizeInKibibytes: pxapi.QemuDiskSize(convert_SizeStringToKibibytes_Unsafe(disk["size"].(string))),
Storage: disk["storage"].(string),
}
if asyncIO, ok := disk["asyncio"].(string); ok {
scsi.Disk.AsyncIO = pxapi.QemuDiskAsyncIO(asyncIO)
Expand Down Expand Up @@ -2792,15 +2792,15 @@ func mapToStruct_VirtIOStorage(virtio *pxapi.QemuVirtIOStorage, key string, sche
if ok && len(tmpDisk) == 1 && tmpDisk[0] != nil {
disk := tmpDisk[0].(map[string]interface{})
virtio.Disk = &pxapi.QemuVirtIODisk{
Backup: disk["backup"].(bool),
Bandwidth: mapToStruct_QemuDiskBandwidth(disk),
Discard: disk["discard"].(bool),
Format: pxapi.QemuDiskFormat(disk["format"].(string)),
IOThread: disk["iothread"].(bool),
ReadOnly: disk["readonly"].(bool),
Replicate: disk["replicate"].(bool),
Size: uint(disk["size"].(int)),
Storage: disk["storage"].(string),
Backup: disk["backup"].(bool),
Bandwidth: mapToStruct_QemuDiskBandwidth(disk),
Discard: disk["discard"].(bool),
Format: pxapi.QemuDiskFormat(disk["format"].(string)),
IOThread: disk["iothread"].(bool),
ReadOnly: disk["readonly"].(bool),
Replicate: disk["replicate"].(bool),
SizeInKibibytes: pxapi.QemuDiskSize(convert_SizeStringToKibibytes_Unsafe(disk["size"].(string))),
Storage: disk["storage"].(string),
}
if asyncIO, ok := disk["asyncio"].(string); ok {
virtio.Disk.AsyncIO = pxapi.QemuDiskAsyncIO(asyncIO)
Expand Down Expand Up @@ -3279,9 +3279,21 @@ func schema_DiskSerial() *schema.Schema {

func schema_DiskSize() *schema.Schema {
return &schema.Schema{
Type: schema.TypeInt,
Required: true,
ValidateDiagFunc: uintValidator(),
Type: schema.TypeString,
Required: true,
ValidateDiagFunc: func(i interface{}, k cty.Path) diag.Diagnostics {
v, ok := i.(string)
if !ok {
return diag.Errorf(errorString, k)
}
if !regexp.MustCompile(`^[123456789]\d*[KMGT]?$`).MatchString(v) {
return diag.Errorf("%s must match the following regex ^[123456789]\\d*[KMGT]?$", k)
}
return nil
},
DiffSuppressFunc: func(k, old, new string, d *schema.ResourceData) bool {
return convert_SizeStringToKibibytes_Unsafe(old) == convert_SizeStringToKibibytes_Unsafe(new)
},
}
}

Expand Down Expand Up @@ -3325,7 +3337,7 @@ func schema_PassthroughFile() *schema.Schema {

func schema_PassthroughSize() *schema.Schema {
return &schema.Schema{
Type: schema.TypeInt,
Type: schema.TypeString,
Computed: true,
}
}
10 changes: 0 additions & 10 deletions proxmox/validators.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,13 +93,3 @@ func VMStateValidator() schema.SchemaValidateDiagFunc {
"stopped",
}, false))
}

func uintValidator() schema.SchemaValidateDiagFunc {
return func(i interface{}, k cty.Path) diag.Diagnostics {
v, ok := i.(int)
if !ok || v < 0 {
return diag.Errorf(errorUint, k)
}
return nil
}
}
Loading