From 3cbd3ce37417c602a921fce6b0ecd142ad589f8b Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Mon, 26 Aug 2024 07:15:26 +0200 Subject: [PATCH 1/6] reimplement serial interfaces --- proxmox/resource_vm_qemu.go | 54 ++++++++++++++++++++++++++++--------- 1 file changed, 42 insertions(+), 12 deletions(-) diff --git a/proxmox/resource_vm_qemu.go b/proxmox/resource_vm_qemu.go index de87ed12..671e2349 100755 --- a/proxmox/resource_vm_qemu.go +++ b/proxmox/resource_vm_qemu.go @@ -869,9 +869,6 @@ func resourceVmQemuCreate(ctx context.Context, d *schema.ResourceData, meta inte qemuNetworks, _ := ExpandDevicesList(d.Get("network").([]interface{})) qemuEfiDisks, _ := ExpandDevicesList(d.Get("efidisk").([]interface{})) - serials := d.Get("serial").(*schema.Set) - qemuSerials, _ := DevicesSetToMap(serials) - qemuPCIDevices, _ := ExpandDevicesList(d.Get("hostpci").([]interface{})) qemuUsbs, _ := ExpandDevicesList(d.Get("usb").([]interface{})) @@ -900,7 +897,7 @@ func resourceVmQemuCreate(ctx context.Context, d *schema.ResourceData, meta inte Tags: tags.RemoveDuplicates(tags.Split(d.Get("tags").(string))), Args: d.Get("args").(string), QemuNetworks: qemuNetworks, - QemuSerials: qemuSerials, + Serials: mapToSDK_Serials(d), QemuPCIDevices: qemuPCIDevices, QemuUsbs: qemuUsbs, Smbios1: BuildSmbiosArgs(d.Get("smbios").([]interface{})), @@ -1113,9 +1110,6 @@ func resourceVmQemuUpdate(ctx context.Context, d *schema.ResourceData, meta inte } logger.Debug().Int("vmid", vmID).Msgf("Processed NetworkSet into qemuNetworks as %+v", qemuNetworks) - serials := d.Get("serial").(*schema.Set) - qemuSerials, _ := DevicesSetToMap(serials) - qemuPCIDevices, err := ExpandDevicesList(d.Get("hostpci").([]interface{})) if err != nil { return diag.FromErr(fmt.Errorf("error while processing HostPCI configuration: %v", err)) @@ -1157,7 +1151,7 @@ func resourceVmQemuUpdate(ctx context.Context, d *schema.ResourceData, meta inte Tags: tags.RemoveDuplicates(tags.Split(d.Get("tags").(string))), Args: d.Get("args").(string), QemuNetworks: qemuNetworks, - QemuSerials: qemuSerials, + Serials: mapToSDK_Serials(d), QemuPCIDevices: qemuPCIDevices, QemuUsbs: qemuUsbs, Smbios1: BuildSmbiosArgs(d.Get("smbios").([]interface{})), @@ -1442,6 +1436,9 @@ func resourceVmQemuRead(ctx context.Context, d *schema.ResourceData, meta interf mapToTerraform_CPU(config.CPU, d) mapToTerraform_CloudInit(config.CloudInit, d) mapToTerraform_Memory(config.Memory, d) + if len(config.Serials) != 0 { + d.Set("serials", mapToTerraform_Serials(config.Serials)) + } // Some dirty hacks to populate undefined keys with default values. checkedKeys := []string{"force_create", "define_connection_info"} @@ -1517,10 +1514,6 @@ func resourceVmQemuRead(ctx context.Context, d *schema.ResourceData, meta interf } d.Set("pool", vmr.Pool()) - // Serials - configSerialsSet := d.Get("serial").(*schema.Set) - activeSerialSet := UpdateDevicesSet(configSerialsSet, config.QemuSerials, "id") - d.Set("serial", activeSerialSet) // Reset reboot_required variable. It should change only during updates. d.Set("reboot_required", false) @@ -2384,6 +2377,22 @@ func mapFromStruct_QemuVirtIOStorage(config *pxapi.QemuVirtIOStorage) []interfac return mapFormStruct_QemuCdRom(config.CdRom) } +func mapToTerraform_Serials(config pxapi.SerialInterfaces) []interface{} { + var index int + serials := make([]interface{}, len(config)) + for i, e := range config { + localMap := map[string]interface{}{"id": int(i)} + if e.Socket { + localMap["type"] = "socket" + } else { + localMap["type"] = string(e.Path) + } + serials[index] = localMap + index++ + } + return serials +} + // Map the terraform schema to sdk struct func mapToStruct_IsoFile(iso string) *pxapi.IsoFile { if iso == "" { @@ -2912,6 +2921,27 @@ func mapToStruct_QemuVirtIODisks(virtio *pxapi.QemuVirtIODisks, schema map[strin mapToStruct_VirtIOStorage(virtio.Disk_15, "virtio15", disks) } +func mapToSDK_Serials(d *schema.ResourceData) pxapi.SerialInterfaces { + serials := pxapi.SerialInterfaces{ + pxapi.SerialID0: pxapi.SerialInterface{Delete: true}, + pxapi.SerialID1: pxapi.SerialInterface{Delete: true}, + pxapi.SerialID2: pxapi.SerialInterface{Delete: true}, + pxapi.SerialID3: pxapi.SerialInterface{Delete: true}} + serialsMap := d.Get("serials").([]interface{}) + for _, serial := range serialsMap { + serialMap := serial.(map[string]interface{}) + newSerial := pxapi.SerialInterface{Delete: false} + serialType := serialMap["type"].(string) + if serialType == "socket" { + newSerial.Socket = true + } else { + newSerial.Path = pxapi.SerialPath(serialType) + } + serials[pxapi.SerialID(serialMap["id"].(int))] = newSerial + } + return nil +} + func mapToStruct_VirtIOStorage(virtio *pxapi.QemuVirtIOStorage, key string, schema map[string]interface{}) { schemaItem, ok := schema[key].([]interface{}) if !ok || len(schemaItem) != 1 || schemaItem[0] == nil { From 1b3681e3a2afa6753f2117958e3ab30ab30e1a27 Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Mon, 26 Aug 2024 08:01:58 +0200 Subject: [PATCH 2/6] feat: add serial schema validation --- proxmox/resource_vm_qemu.go | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/proxmox/resource_vm_qemu.go b/proxmox/resource_vm_qemu.go index 671e2349..5a5f7dd4 100755 --- a/proxmox/resource_vm_qemu.go +++ b/proxmox/resource_vm_qemu.go @@ -592,10 +592,27 @@ func resourceVmQemu() *schema.Resource { "id": { Type: schema.TypeInt, Required: true, + ValidateDiagFunc: func(i interface{}, k cty.Path) diag.Diagnostics { + v := i.(int) + if err := pxapi.SerialID(v).Validate(); err != nil { + return diag.Errorf("serial id must be between 0 and 3, got: %d", v) + } + return nil + }, }, "type": { Type: schema.TypeString, Required: true, + ValidateDiagFunc: func(i interface{}, k cty.Path) diag.Diagnostics { + v := i.(string) + if v == "socket" { + return nil + } + if err := pxapi.SerialPath(v).Validate(); err != nil { + return diag.Errorf("serial type must be 'socket' or match the following regex `/dev/.+`, got: %s", v) + } + return nil + }, }, }, }, From ed55780eec1bd9dfdd6455947d046036243eb3c0 Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Mon, 26 Aug 2024 08:34:44 +0200 Subject: [PATCH 3/6] fix: panic do tue incorrect key and type --- proxmox/resource_vm_qemu.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/proxmox/resource_vm_qemu.go b/proxmox/resource_vm_qemu.go index 5a5f7dd4..29cab2c5 100755 --- a/proxmox/resource_vm_qemu.go +++ b/proxmox/resource_vm_qemu.go @@ -1454,7 +1454,7 @@ func resourceVmQemuRead(ctx context.Context, d *schema.ResourceData, meta interf mapToTerraform_CloudInit(config.CloudInit, d) mapToTerraform_Memory(config.Memory, d) if len(config.Serials) != 0 { - d.Set("serials", mapToTerraform_Serials(config.Serials)) + d.Set("serial", mapToTerraform_Serials(config.Serials)) } // Some dirty hacks to populate undefined keys with default values. @@ -2944,8 +2944,8 @@ func mapToSDK_Serials(d *schema.ResourceData) pxapi.SerialInterfaces { pxapi.SerialID1: pxapi.SerialInterface{Delete: true}, pxapi.SerialID2: pxapi.SerialInterface{Delete: true}, pxapi.SerialID3: pxapi.SerialInterface{Delete: true}} - serialsMap := d.Get("serials").([]interface{}) - for _, serial := range serialsMap { + serialsMap := d.Get("serial").(*schema.Set) + for _, serial := range serialsMap.List() { serialMap := serial.(map[string]interface{}) newSerial := pxapi.SerialInterface{Delete: false} serialType := serialMap["type"].(string) From fd18d88188755139475b7729353d995b12b16b2a Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Mon, 26 Aug 2024 08:35:21 +0200 Subject: [PATCH 4/6] fix: `serial` never updated --- proxmox/resource_vm_qemu.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proxmox/resource_vm_qemu.go b/proxmox/resource_vm_qemu.go index 29cab2c5..eed65a65 100755 --- a/proxmox/resource_vm_qemu.go +++ b/proxmox/resource_vm_qemu.go @@ -2956,7 +2956,7 @@ func mapToSDK_Serials(d *schema.ResourceData) pxapi.SerialInterfaces { } serials[pxapi.SerialID(serialMap["id"].(int))] = newSerial } - return nil + return serials } func mapToStruct_VirtIOStorage(virtio *pxapi.QemuVirtIOStorage, key string, schema map[string]interface{}) { From faaa6920a4273df403e84436c33850f40f2a4304 Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Mon, 26 Aug 2024 17:27:45 +0200 Subject: [PATCH 5/6] feat: `serial.type` defaults to `socket` --- docs/resources/vm_qemu.md | 6 ++---- proxmox/resource_vm_qemu.go | 3 ++- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/docs/resources/vm_qemu.md b/docs/resources/vm_qemu.md index a2a56656..3a81c29c 100644 --- a/docs/resources/vm_qemu.md +++ b/docs/resources/vm_qemu.md @@ -467,9 +467,7 @@ See the [docs about EFI disks](https://pve.proxmox.com/pve-docs/chapter-qm.html# ### Serial Block -Create a serial device inside the VM (up to a maximum of 4 can be specified), and either pass through a host serial -device (i.e. /dev/ttyS0), or create a unix socket on the host side. The order in which `serial` blocks are declared does -not matter. +Create a serial device inside the VM (up to a maximum of 4 can be specified), and either pass through a host serial device (i.e. /dev/ttyS0), or create a unix socket on the host side. The order in which `serial` blocks are declared does not matter. **WARNING**: Use with caution, as the docs indicate this device is experimental and users have reported issues with it. @@ -479,7 +477,7 @@ details. | Argument | Type | Default Value | Description | | -------- | ----- | ------------- | ---------------------------------------------------------------------------------------------------------------------- | | `id` | `int` | | **Required** The ID of the serial device. Must be unique, and between `0-3`. | -| `type` | `str` | | **Required** The type of serial device to create. Options: `socket`, or the path to a serial device like `/dev/ttyS0`. | +| `type` | `str` | `socket` | The type of serial device to create. Options: `socket`, or the path to a serial device like `/dev/ttyS0`. | ### USB Block diff --git a/proxmox/resource_vm_qemu.go b/proxmox/resource_vm_qemu.go index eed65a65..0230440a 100755 --- a/proxmox/resource_vm_qemu.go +++ b/proxmox/resource_vm_qemu.go @@ -602,7 +602,8 @@ func resourceVmQemu() *schema.Resource { }, "type": { Type: schema.TypeString, - Required: true, + Optional: true, + Default: "socket", ValidateDiagFunc: func(i interface{}, k cty.Path) diag.Diagnostics { v := i.(string) if v == "socket" { From 797c30ba2d6a0e0fb33f9b4294885b499c39d737 Mon Sep 17 00:00:00 2001 From: Tinyblargon <76069640+Tinyblargon@users.noreply.github.com> Date: Tue, 27 Aug 2024 18:33:48 +0200 Subject: [PATCH 6/6] chore: update proxmox-api-go --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 90550283..a219b18c 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.21 toolchain go1.21.0 require ( - github.com/Telmate/proxmox-api-go v0.0.0-20240815210158-602cfe748bba + github.com/Telmate/proxmox-api-go v0.0.0-20240827160542-0d787afdba05 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.34.0 diff --git a/go.sum b/go.sum index c5d78277..eab09510 100644 --- a/go.sum +++ b/go.sum @@ -4,8 +4,8 @@ github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migc github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= github.com/ProtonMail/go-crypto v1.1.0-alpha.2-proton h1:HKz85FwoXx86kVtTvFke7rgHvq/HoloSUvW5semjFWs= github.com/ProtonMail/go-crypto v1.1.0-alpha.2-proton/go.mod h1:rA3QumHc/FZ8pAHreoekgiAbzpNsfQAosU5td4SnOrE= -github.com/Telmate/proxmox-api-go v0.0.0-20240815210158-602cfe748bba h1:rbztGEr4+G00B0Thkq8QGhgyFcgvlOoCNhgu+8Pq+is= -github.com/Telmate/proxmox-api-go v0.0.0-20240815210158-602cfe748bba/go.mod h1:Gu6n6vEn1hlyFUkjrvU+X1fdgaSXLoM9HKYYJqy1fsY= +github.com/Telmate/proxmox-api-go v0.0.0-20240827160542-0d787afdba05 h1:yYVjf1Bp6qYHFuOlV8eNwUh1kpYMnUFrop4iLvY+/ZY= +github.com/Telmate/proxmox-api-go v0.0.0-20240827160542-0d787afdba05/go.mod h1:Gu6n6vEn1hlyFUkjrvU+X1fdgaSXLoM9HKYYJqy1fsY= 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=