Skip to content

Commit

Permalink
Merge branch 'master' into #986
Browse files Browse the repository at this point in the history
  • Loading branch information
Tinyblargon authored Sep 1, 2024
2 parents 97cb971 + f93526b commit c885a40
Show file tree
Hide file tree
Showing 5 changed files with 145 additions and 58 deletions.
92 changes: 63 additions & 29 deletions .github/workflows/go.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,39 +15,73 @@ on:
- 'docs/**'
- 'examples/**'

jobs:
env:
GO_VERSION: '1.21'

audit:
jobs:
verify-dependencies:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: '1.21'
check-latest: true

- name: Verify dependencies
run: go mod verify
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: ${{ env.GO_VERSION }}
check-latest: true
- name: Verify dependencies
run: go mod verify

- name: Build
run: go build -v ./...

- name: Run go vet
run: go vet ./...

- name: Install staticcheck
run: go install honnef.co/go/tools/cmd/staticcheck@latest

- name: Run staticcheck
run: staticcheck ./...
build:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: ${{ env.GO_VERSION }}
check-latest: true
- name: Build
run: go build -v ./...

- name: Install golint
run: go install golang.org/x/lint/golint@latest
vet:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: ${{ env.GO_VERSION }}
check-latest: true
- name: Run go vet
run: go vet ./...

- name: Run golint
run: golint ./...
staticcheck:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: ${{ env.GO_VERSION }}
check-latest: true
- name: Install staticcheck
run: go install honnef.co/go/tools/cmd/staticcheck@latest
- name: Run staticcheck
run: staticcheck ./...

- name: Run tests
run: go test -race -vet=off ./...
test:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: ${{ env.GO_VERSION }}
check-latest: true
- name: Run tests
run: go test -race -vet=off ./...
6 changes: 2 additions & 4 deletions docs/resources/vm_qemu.md
Original file line number Diff line number Diff line change
Expand Up @@ -543,9 +543,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 @@ -555,7 +553,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
99 changes: 77 additions & 22 deletions proxmox/resource_vm_qemu.go
Original file line number Diff line number Diff line change
Expand Up @@ -659,10 +659,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 @@ -936,9 +954,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 @@ -967,7 +982,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 @@ -1184,9 +1199,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 @@ -1228,7 +1240,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 @@ -1466,12 +1478,14 @@ func resourceVmQemuRead(ctx context.Context, d *schema.ResourceData, meta interf
}

vmState, err := client.GetVmState(vmr)
log.Printf("[DEBUG] VM status: %s", vmState["status"])
if err == nil {
d.Set("vm_state", vmState["status"])
if err != nil {
return diag.FromErr(err)
}
if err == nil && vmState["status"] == "running" {
log.Printf("[DEBUG] VM status: %s", vmState["status"])
d.Set("vm_state", vmState["status"])
if vmState["status"] == "running" {
log.Printf("[DEBUG] VM is running, checking the IP")
// TODO when network interfaces are reimplemented check if we have an interface before getting the connection info
diags = append(diags, initConnInfo(d, client, vmr, config)...)
} else {
// Optional convenience attributes for provisioners
Expand All @@ -1482,9 +1496,6 @@ func resourceVmQemuRead(ctx context.Context, d *schema.ResourceData, meta interf
err = d.Set("ssh_port", nil)
diags = append(diags, diag.FromErr(err)...)
}
if err != nil {
return diag.FromErr(err)
}

logger.Debug().Int("vmid", vmID).Msgf("[READ] Received Config from Proxmox API: %+v", config)

Expand Down Expand Up @@ -1516,6 +1527,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 @@ -1545,6 +1559,7 @@ func resourceVmQemuRead(ctx context.Context, d *schema.ResourceData, meta interf

// read in the qemu hostpci
qemuUsbsDevices, _ := FlattenDevicesList(config.QemuUsbs)
qemuUsbsDevices, _ = DropElementsFromMap([]string{"id"}, qemuUsbsDevices)
logger.Debug().Int("vmid", vmID).Msgf("Usb Block Processed '%v'", config.QemuUsbs)
if err = d.Set("usb", qemuUsbsDevices); err != nil {
return diag.FromErr(err)
Expand Down Expand Up @@ -1591,10 +1606,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 @@ -1944,11 +1955,18 @@ func getPrimaryIP(config *pxapi.ConfigQemu, vmr *pxapi.VmRef, client *pxapi.Clie
// get all information we can from qemu agent until the timer runs out
if ciAgentEnabled {
var waitedTime int
// TODO rework this logic when network interfaces are properly handled in the SDK
vmConfig, err := client.GetVmConfig(vmr)
if err != nil {
return primaryIPs{}, diag.FromErr(err)
}
net0MacAddress := macAddressRegex.FindString(vmConfig["net0"].(string))
var primaryMacAddress string
for i := 0; i < 16; i++ {
if _, ok := vmConfig["net"+strconv.Itoa(i)]; ok {
primaryMacAddress = macAddressRegex.FindString(vmConfig["net"+strconv.Itoa(i)].(string))
break
}
}
for time.Now().Before(endTime) {
var interfaces []pxapi.AgentNetworkInterface
interfaces, err = vmr.GetAgentInformation(client, false)
Expand All @@ -1962,7 +1980,7 @@ func getPrimaryIP(config *pxapi.ConfigQemu, vmr *pxapi.VmRef, client *pxapi.Clie
if len(interfaces) > 0 { // agent returned some information
log.Printf("[INFO][getPrimaryIP] QEMU Agent interfaces found: %v", interfaces)
logger.Debug().Int("vmid", vmr.VmId()).Msgf("QEMU Agent interfaces found: %v", interfaces)
conn = conn.parsePrimaryIPs(interfaces, net0MacAddress)
conn = conn.parsePrimaryIPs(interfaces, primaryMacAddress)
if conn.hasRequiredIP() {
return conn.IPs, diag.Diagnostics{}
}
Expand Down Expand Up @@ -2906,6 +2924,22 @@ func mapToTerraform_QemuVirtIOStorage_Disks(config *pxapi.QemuVirtIOStorage) []i
return mapToTerraform_QemuCdRom_Disks(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 {
Expand Down Expand Up @@ -3931,6 +3965,27 @@ func mapToSDK_QemuVirtIOStorage_Disks(virtio *pxapi.QemuVirtIOStorage, key strin
virtio.CdRom = mapToSDK_QemuCdRom_Disks(storageSchema)
}

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 mapToSDK_Size_Disk(slot string, schema map[string]interface{}) (pxapi.QemuDiskSize, diag.Diagnostics) {
size := convert_SizeStringToKibibytes_Unsafe(schema["size"].(string))
if size == 0 {
Expand Down

0 comments on commit c885a40

Please sign in to comment.