Skip to content

Commit

Permalink
Merge pull request #1079 from Tinyblargon/#1034
Browse files Browse the repository at this point in the history
Reimplement Serials
  • Loading branch information
Tinyblargon committed Sep 1, 2024
2 parents 21388e7 + 797c30b commit a994d14
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 20 deletions.
6 changes: 2 additions & 4 deletions docs/resources/vm_qemu.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.

Expand All @@ -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

Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -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=
Expand Down
74 changes: 61 additions & 13 deletions proxmox/resource_vm_qemu.go
Original file line number Diff line number Diff line change
Expand Up @@ -592,10 +592,28 @@ 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,
Optional: true,
Default: "socket",
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
},
},
},
},
Expand Down Expand Up @@ -869,9 +887,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{}))
Expand Down Expand Up @@ -900,7 +915,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{})),
Expand Down Expand Up @@ -1113,9 +1128,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))
Expand Down Expand Up @@ -1157,7 +1169,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{})),
Expand Down Expand Up @@ -1441,6 +1453,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("serial", mapToTerraform_Serials(config.Serials))
}

// Some dirty hacks to populate undefined keys with default values.
checkedKeys := []string{"force_create", "define_connection_info"}
Expand Down Expand Up @@ -1516,10 +1531,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)
Expand Down Expand Up @@ -2390,6 +2401,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 == "" {
Expand Down Expand Up @@ -2918,6 +2945,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("serial").(*schema.Set)
for _, serial := range serialsMap.List() {
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 serials
}

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 {
Expand Down

0 comments on commit a994d14

Please sign in to comment.