Skip to content

Commit

Permalink
Merge pull request #929 from Tinyblargon/Fix#912
Browse files Browse the repository at this point in the history
[3.0.1-rc1] Feature: KMGT disk size
  • Loading branch information
Tinyblargon authored Feb 5, 2024
2 parents 86e9508 + 9843909 commit 77eb1f6
Show file tree
Hide file tree
Showing 6 changed files with 114 additions and 62 deletions.
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
}
}

0 comments on commit 77eb1f6

Please sign in to comment.