From f72ea5adda25d818622824ba1c9f7eab32e6ff47 Mon Sep 17 00:00:00 2001 From: Martin Pywell Date: Fri, 4 Oct 2024 23:18:18 +1000 Subject: [PATCH 1/3] common: add qemu agent settings block - Extend QEMU agent handling by introducing qemu_quest_agent block, deprecating qemu_agent bool - Enable setting the agent type - Enable toggling freeze/thaw filesystems on backup - Enable toggling fstrim after disk move or VM migration - Each added setting defaults to Proxmox's backend defaults when not configured. --- .web-docs/components/builder/clone/README.md | 56 +++++++++- .web-docs/components/builder/iso/README.md | 56 +++++++++- builder/proxmox/clone/config.hcl2spec.go | 2 + builder/proxmox/common/config.go | 66 +++++++++++- builder/proxmox/common/config.hcl2spec.go | 31 ++++++ builder/proxmox/common/config_test.go | 16 +++ builder/proxmox/common/step_start_vm.go | 21 ++-- builder/proxmox/common/step_start_vm_test.go | 102 ++++++++++++++++++ builder/proxmox/iso/config.hcl2spec.go | 2 + builder/proxmox/iso/config_test.go | 4 +- .../proxmox/common/Config-not-required.mdx | 5 +- .../common/agentConfig-not-required.mdx | 13 +++ .../builder/proxmox/common/agentConfig.mdx | 30 ++++++ docs/builders/clone.mdx | 8 ++ docs/builders/iso.mdx | 8 ++ 15 files changed, 403 insertions(+), 17 deletions(-) create mode 100644 docs-partials/builder/proxmox/common/agentConfig-not-required.mdx create mode 100644 docs-partials/builder/proxmox/common/agentConfig.mdx diff --git a/.web-docs/components/builder/clone/README.md b/.web-docs/components/builder/clone/README.md index d4552350..9aaacad3 100644 --- a/.web-docs/components/builder/clone/README.md +++ b/.web-docs/components/builder/clone/README.md @@ -243,10 +243,13 @@ boot time. ] ``` -- `qemu_agent` (boolean) - Enables QEMU Agent option for this VM. When enabled, +- `qemu_agent` (boolean) - DEPRECATED. Define QEMU Guest Agent settings in a `qemu_guest_agent` block instead. + Enables QEMU Agent option for this VM. When enabled, then `qemu-guest-agent` must be installed on the guest. When disabled, then `ssh_host` should be used. Defaults to `true`. +- `qemu_guest_agent` (agentConfig) - QEMU Guest Agent configuration. See [QEMU Guest Agent](#qemu-guest-agent) + - `scsi_controller` (string) - The SCSI controller model to emulate. Can be `lsi`, `lsi53c810`, `virtio-scsi-pci`, `virtio-scsi-single`, `megasas`, or `pvscsi`. Defaults to `lsi`. @@ -826,6 +829,57 @@ Usage example (JSON): +### QEMU Guest Agent + + + +Set the QEMU Guest Agent options. + +JSON Example: + +```json + + "qemu_guest_agent": { + "enabled": true, + "type": "isa", + "freeze": false, + "fstrim": false + } + +``` +HCL2 example: + +```hcl + + qemu_guest_agent { + enabled = true + type = "isa" + freeze = false + fstrim = false + } + +``` + + + + +#### Optional: + + + +- `enabled` (boolean) - Enable QEMU Agent option for this VM. When enabled + `qemu-guest-agent` must be installed on the guest. When disabled + `ssh_host` should be used. Defaults to `true`. + +- `type` (string) - Sets the Agent Type. Must be `isa` or `virtio`. Defaults to `virtio` + +- `freeze` (boolean) - Enable freeze/thaw of guest filesystem on backup. Defaults to `true` + +- `fstrim` (bool) - Run guest-trim after a disk move or VM migration. Defaults to `false` + + + + ### VirtIO RNG device diff --git a/.web-docs/components/builder/iso/README.md b/.web-docs/components/builder/iso/README.md index f9750c7b..8144cd65 100644 --- a/.web-docs/components/builder/iso/README.md +++ b/.web-docs/components/builder/iso/README.md @@ -178,10 +178,13 @@ in the image's Cloud-Init settings for provisioning. ] ``` -- `qemu_agent` (boolean) - Enables QEMU Agent option for this VM. When enabled, +- `qemu_agent` (boolean) - DEPRECATED. Define QEMU Guest Agent settings in a `qemu_guest_agent` block instead. + Enables QEMU Agent option for this VM. When enabled, then `qemu-guest-agent` must be installed on the guest. When disabled, then `ssh_host` should be used. Defaults to `true`. +- `qemu_guest_agent` (agentConfig) - QEMU Guest Agent configuration. See [QEMU Guest Agent](#qemu-guest-agent) + - `scsi_controller` (string) - The SCSI controller model to emulate. Can be `lsi`, `lsi53c810`, `virtio-scsi-pci`, `virtio-scsi-single`, `megasas`, or `pvscsi`. Defaults to `lsi`. @@ -667,6 +670,57 @@ Usage example (JSON): +### QEMU Guest Agent + + + +Set the QEMU Guest Agent options. + +JSON Example: + +```json + + "qemu_guest_agent": { + "enabled": true, + "type": "isa", + "freeze": false, + "fstrim": false + } + +``` +HCL2 example: + +```hcl + + qemu_guest_agent { + enabled = true + type = "isa" + freeze = false + fstrim = false + } + +``` + + + + +#### Optional: + + + +- `enabled` (boolean) - Enable QEMU Agent option for this VM. When enabled + `qemu-guest-agent` must be installed on the guest. When disabled + `ssh_host` should be used. Defaults to `true`. + +- `type` (string) - Sets the Agent Type. Must be `isa` or `virtio`. Defaults to `virtio` + +- `freeze` (boolean) - Enable freeze/thaw of guest filesystem on backup. Defaults to `true` + +- `fstrim` (bool) - Run guest-trim after a disk move or VM migration. Defaults to `false` + + + + ### VirtIO RNG device diff --git a/builder/proxmox/clone/config.hcl2spec.go b/builder/proxmox/clone/config.hcl2spec.go index 0de5951f..4db2771f 100644 --- a/builder/proxmox/clone/config.hcl2spec.go +++ b/builder/proxmox/clone/config.hcl2spec.go @@ -109,6 +109,7 @@ type FlatConfig struct { PCIDevices []proxmox.FlatpciDeviceConfig `mapstructure:"pci_devices" cty:"pci_devices" hcl:"pci_devices"` Serials []string `mapstructure:"serials" cty:"serials" hcl:"serials"` Agent *bool `mapstructure:"qemu_agent" cty:"qemu_agent" hcl:"qemu_agent"` + GuestAgent *proxmox.FlatagentConfig `mapstructure:"qemu_guest_agent" cty:"qemu_guest_agent" hcl:"qemu_guest_agent"` SCSIController *string `mapstructure:"scsi_controller" cty:"scsi_controller" hcl:"scsi_controller"` Onboot *bool `mapstructure:"onboot" cty:"onboot" hcl:"onboot"` DisableKVM *bool `mapstructure:"disable_kvm" cty:"disable_kvm" hcl:"disable_kvm"` @@ -238,6 +239,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec { "pci_devices": &hcldec.BlockListSpec{TypeName: "pci_devices", Nested: hcldec.ObjectSpec((*proxmox.FlatpciDeviceConfig)(nil).HCL2Spec())}, "serials": &hcldec.AttrSpec{Name: "serials", Type: cty.List(cty.String), Required: false}, "qemu_agent": &hcldec.AttrSpec{Name: "qemu_agent", Type: cty.Bool, Required: false}, + "qemu_guest_agent": &hcldec.BlockSpec{TypeName: "qemu_guest_agent", Nested: hcldec.ObjectSpec((*proxmox.FlatagentConfig)(nil).HCL2Spec())}, "scsi_controller": &hcldec.AttrSpec{Name: "scsi_controller", Type: cty.String, Required: false}, "onboot": &hcldec.AttrSpec{Name: "onboot", Type: cty.Bool, Required: false}, "disable_kvm": &hcldec.AttrSpec{Name: "disable_kvm", Type: cty.Bool, Required: false}, diff --git a/builder/proxmox/common/config.go b/builder/proxmox/common/config.go index fe4eb33f..466eff14 100644 --- a/builder/proxmox/common/config.go +++ b/builder/proxmox/common/config.go @@ -2,7 +2,7 @@ // SPDX-License-Identifier: MPL-2.0 //go:generate packer-sdc struct-markdown -//go:generate packer-sdc mapstructure-to-hcl2 -type Config,NICConfig,diskConfig,rng0Config,pciDeviceConfig,vgaConfig,ISOsConfig,efiConfig,tpmConfig +//go:generate packer-sdc mapstructure-to-hcl2 -type Config,NICConfig,diskConfig,rng0Config,pciDeviceConfig,vgaConfig,ISOsConfig,efiConfig,tpmConfig,agentConfig package proxmox @@ -158,10 +158,13 @@ type Config struct { // ] // ``` Serials []string `mapstructure:"serials"` + // DEPRECATED. Define QEMU Guest Agent settings in a `qemu_guest_agent` block instead. // Enables QEMU Agent option for this VM. When enabled, // then `qemu-guest-agent` must be installed on the guest. When disabled, then // `ssh_host` should be used. Defaults to `true`. Agent config.Trilean `mapstructure:"qemu_agent"` + // QEMU Guest Agent configuration. See [QEMU Guest Agent](#qemu-guest-agent) + GuestAgent agentConfig `mapstructure:"qemu_guest_agent"` // The SCSI controller model to emulate. Can be `lsi`, // `lsi53c810`, `virtio-scsi-pci`, `virtio-scsi-single`, `megasas`, or `pvscsi`. // Defaults to `lsi`. @@ -207,6 +210,45 @@ type Config struct { Ctx interpolate.Context `mapstructure-to-hcl2:",skip"` } +// Set the QEMU Guest Agent options. +// +// JSON Example: +// +// ```json +// +// "qemu_guest_agent": { +// "enabled": true, +// "type": "isa", +// "freeze": false, +// "fstrim": false +// } +// +// ``` +// HCL2 example: +// +// ```hcl +// +// qemu_guest_agent { +// enabled = true +// type = "isa" +// freeze = false +// fstrim = false +// } +// +// ``` +type agentConfig struct { + // Enable QEMU Agent option for this VM. When enabled + // `qemu-guest-agent` must be installed on the guest. When disabled + // `ssh_host` should be used. Defaults to `true`. + Enabled config.Trilean `mapstructure:"enabled"` + // Sets the Agent Type. Must be `isa` or `virtio`. Defaults to `virtio` + Type string `mapstructure:"type"` + // Enable freeze/thaw of guest filesystem on backup. Defaults to `true` + Freeze config.Trilean `mapstructure:"freeze"` + // Run guest-trim after a disk move or VM migration. Defaults to `false` + FsTrim bool `mapstructure:"fstrim"` +} + // ISO files attached to the virtual machine. // // JSON Example: @@ -606,7 +648,27 @@ func (c *Config) Prepare(upper interface{}, raws ...interface{}) ([]string, []st // Default qemu_agent to true if c.Agent != config.TriFalse { - c.Agent = config.TriTrue + warnings = append(warnings, "qemu_agent is deprecated and will be removed in a future release. define QEMU agent settings in a qemu_guest_agent block instead") + // convert to qemu_guest_agent block value + c.GuestAgent.Enabled = config.TriTrue + } + + // Default qemu_guest_agent.enable to true + if c.GuestAgent.Enabled != config.TriFalse { + c.GuestAgent.Enabled = config.TriTrue + } + // Default qemu_guest_agent.freeze to true + if c.GuestAgent.Freeze != config.TriFalse { + c.GuestAgent.Freeze = config.TriTrue + } + + switch c.GuestAgent.Type { + case "virtio", "isa": + case "": + log.Printf("qemu_guest_agent type not specified, defaulting to `virtio`") + c.GuestAgent.Type = "virtio" + default: + errs = packersdk.MultiErrorAppend(errs, errors.New("qemu_guest_agent type field must be `virtio` or `isa`")) } packersdk.LogSecretFilter.Set(c.Password) diff --git a/builder/proxmox/common/config.hcl2spec.go b/builder/proxmox/common/config.hcl2spec.go index de4bae7c..be7ab735 100644 --- a/builder/proxmox/common/config.hcl2spec.go +++ b/builder/proxmox/common/config.hcl2spec.go @@ -108,6 +108,7 @@ type FlatConfig struct { PCIDevices []FlatpciDeviceConfig `mapstructure:"pci_devices" cty:"pci_devices" hcl:"pci_devices"` Serials []string `mapstructure:"serials" cty:"serials" hcl:"serials"` Agent *bool `mapstructure:"qemu_agent" cty:"qemu_agent" hcl:"qemu_agent"` + GuestAgent *FlatagentConfig `mapstructure:"qemu_guest_agent" cty:"qemu_guest_agent" hcl:"qemu_guest_agent"` SCSIController *string `mapstructure:"scsi_controller" cty:"scsi_controller" hcl:"scsi_controller"` Onboot *bool `mapstructure:"onboot" cty:"onboot" hcl:"onboot"` DisableKVM *bool `mapstructure:"disable_kvm" cty:"disable_kvm" hcl:"disable_kvm"` @@ -231,6 +232,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec { "pci_devices": &hcldec.BlockListSpec{TypeName: "pci_devices", Nested: hcldec.ObjectSpec((*FlatpciDeviceConfig)(nil).HCL2Spec())}, "serials": &hcldec.AttrSpec{Name: "serials", Type: cty.List(cty.String), Required: false}, "qemu_agent": &hcldec.AttrSpec{Name: "qemu_agent", Type: cty.Bool, Required: false}, + "qemu_guest_agent": &hcldec.BlockSpec{TypeName: "qemu_guest_agent", Nested: hcldec.ObjectSpec((*FlatagentConfig)(nil).HCL2Spec())}, "scsi_controller": &hcldec.AttrSpec{Name: "scsi_controller", Type: cty.String, Required: false}, "onboot": &hcldec.AttrSpec{Name: "onboot", Type: cty.Bool, Required: false}, "disable_kvm": &hcldec.AttrSpec{Name: "disable_kvm", Type: cty.Bool, Required: false}, @@ -334,6 +336,35 @@ func (*FlatNICConfig) HCL2Spec() map[string]hcldec.Spec { return s } +// FlatagentConfig is an auto-generated flat version of agentConfig. +// Where the contents of a field with a `mapstructure:,squash` tag are bubbled up. +type FlatagentConfig struct { + Enabled *bool `mapstructure:"enabled" cty:"enabled" hcl:"enabled"` + Type *string `mapstructure:"type" cty:"type" hcl:"type"` + Freeze *bool `mapstructure:"freeze" cty:"freeze" hcl:"freeze"` + FsTrim *bool `mapstructure:"fstrim" cty:"fstrim" hcl:"fstrim"` +} + +// FlatMapstructure returns a new FlatagentConfig. +// FlatagentConfig is an auto-generated flat version of agentConfig. +// Where the contents a fields with a `mapstructure:,squash` tag are bubbled up. +func (*agentConfig) FlatMapstructure() interface{ HCL2Spec() map[string]hcldec.Spec } { + return new(FlatagentConfig) +} + +// HCL2Spec returns the hcl spec of a agentConfig. +// This spec is used by HCL to read the fields of agentConfig. +// The decoded values from this spec will then be applied to a FlatagentConfig. +func (*FlatagentConfig) HCL2Spec() map[string]hcldec.Spec { + s := map[string]hcldec.Spec{ + "enabled": &hcldec.AttrSpec{Name: "enabled", Type: cty.Bool, Required: false}, + "type": &hcldec.AttrSpec{Name: "type", Type: cty.String, Required: false}, + "freeze": &hcldec.AttrSpec{Name: "freeze", Type: cty.Bool, Required: false}, + "fstrim": &hcldec.AttrSpec{Name: "fstrim", Type: cty.Bool, Required: false}, + } + return s +} + // FlatdiskConfig is an auto-generated flat version of diskConfig. // Where the contents of a field with a `mapstructure:,squash` tag are bubbled up. type FlatdiskConfig struct { diff --git a/builder/proxmox/common/config_test.go b/builder/proxmox/common/config_test.go index eeec71ba..9844583c 100644 --- a/builder/proxmox/common/config_test.go +++ b/builder/proxmox/common/config_test.go @@ -63,6 +63,22 @@ func TestAgentSetToFalse(t *testing.T) { } } +func TestQemuAgentInvalidType(t *testing.T) { + cfg := mandatoryConfig(t) + + agentCfg := make(map[string]interface{}) + agentCfg["type"] = "qwerty" + + cfg["qemu_guest_agent"] = agentCfg + + var c Config + _, _, err := c.Prepare(&c, cfg) + // expect error, if none returned fail test + if err == nil { + t.Error("expected config preparation to fail, but no error occured") + } +} + func TestPacketQueueSupportForNetworkAdapters(t *testing.T) { drivertests := []struct { expectedToFail bool diff --git a/builder/proxmox/common/step_start_vm.go b/builder/proxmox/common/step_start_vm.go index 3781c6b1..aef5875f 100644 --- a/builder/proxmox/common/step_start_vm.go +++ b/builder/proxmox/common/step_start_vm.go @@ -15,7 +15,6 @@ import ( "github.com/Telmate/proxmox-api-go/proxmox" "github.com/hashicorp/packer-plugin-sdk/multistep" packersdk "github.com/hashicorp/packer-plugin-sdk/packer" - "github.com/hashicorp/packer-plugin-sdk/template/config" ) // stepStartVM takes the given configuration and starts a VM on the given Proxmox node. @@ -123,7 +122,7 @@ func (s *stepStartVM) Run(ctx context.Context, state multistep.StateBag) multist config := proxmox.ConfigQemu{ Name: c.VMName, - Agent: generateAgentConfig(c.Agent), + Agent: generateAgentConfig(c.GuestAgent), QemuKVM: &kvm, Tags: generateTags(c.Tags), Boot: c.Boot, // Boot priority, example: "order=virtio0;ide2;net0", virtio0:Disk0 -> ide0:CDROM -> net0:Network @@ -255,16 +254,18 @@ func (s *stepStartVM) Run(ctx context.Context, state multistep.StateBag) multist return multistep.ActionContinue } -func generateAgentConfig(agent config.Trilean) *proxmox.QemuGuestAgent { - var enableAgent bool +func generateAgentConfig(agent agentConfig) *proxmox.QemuGuestAgent { + var agentCfg proxmox.QemuGuestAgent - if agent.True() { - enableAgent = true - } + agentCfg.Enable = agent.Enabled.ToBoolPointer() + agentCfg.Freeze = agent.Freeze.ToBoolPointer() - return &proxmox.QemuGuestAgent{ - Enable: &enableAgent, - } + agentType := proxmox.QemuGuestAgentType(agent.Type) + agentCfg.Type = &agentType + + agentCfg.FsTrim = &agent.FsTrim + + return &agentCfg } func generateTags(rawTags string) *[]proxmox.Tag { diff --git a/builder/proxmox/common/step_start_vm_test.go b/builder/proxmox/common/step_start_vm_test.go index a228778b..91a84947 100644 --- a/builder/proxmox/common/step_start_vm_test.go +++ b/builder/proxmox/common/step_start_vm_test.go @@ -12,6 +12,7 @@ import ( "github.com/hashicorp/packer-plugin-sdk/common" "github.com/hashicorp/packer-plugin-sdk/multistep" packersdk "github.com/hashicorp/packer-plugin-sdk/packer" + "github.com/hashicorp/packer-plugin-sdk/template/config" "github.com/stretchr/testify/assert" ) @@ -1309,3 +1310,104 @@ func TestGenerateProxmoxDisks(t *testing.T) { }) } } + +func boolPointer(b bool) *bool { + return &b +} + +func qemuGuestAgentTypePointer(t proxmox.QemuGuestAgentType) *proxmox.QemuGuestAgentType { + return &t +} + +func TestGenerateQEMUAgentConfig(t *testing.T) { + + tests := []struct { + name string + agentConfig agentConfig + expectOutput *proxmox.QemuGuestAgent + }{ + { + "plain config, no special options set", + agentConfig{ + Enabled: config.TriTrue, + Type: "virtio", + Freeze: config.TriTrue, + FsTrim: false, + }, + &proxmox.QemuGuestAgent{ + Enable: boolPointer(true), + Type: qemuGuestAgentTypePointer("virtio"), + Freeze: boolPointer(true), + FsTrim: boolPointer(false), + }, + }, + { + "configure for isa type", + agentConfig{ + Enabled: config.TriTrue, + Type: "isa", + Freeze: config.TriTrue, + FsTrim: false, + }, + &proxmox.QemuGuestAgent{ + Enable: boolPointer(true), + Type: qemuGuestAgentTypePointer("isa"), + Freeze: boolPointer(true), + FsTrim: boolPointer(false), + }, + }, + { + "disable agent", + agentConfig{ + Enabled: config.TriFalse, + Type: "virtio", + Freeze: config.TriTrue, + FsTrim: false, + }, + &proxmox.QemuGuestAgent{ + Enable: boolPointer(false), + Type: qemuGuestAgentTypePointer("virtio"), + Freeze: boolPointer(true), + FsTrim: boolPointer(false), + }, + }, + { + "enable fstrim", + agentConfig{ + Enabled: config.TriFalse, + Type: "virtio", + Freeze: config.TriTrue, + FsTrim: true, + }, + &proxmox.QemuGuestAgent{ + Enable: boolPointer(false), + Type: qemuGuestAgentTypePointer("virtio"), + Freeze: boolPointer(true), + FsTrim: boolPointer(true), + }, + }, + { + "disable freeze", + agentConfig{ + Enabled: config.TriFalse, + Type: "virtio", + Freeze: config.TriTrue, + FsTrim: true, + }, + &proxmox.QemuGuestAgent{ + Enable: boolPointer(false), + Type: qemuGuestAgentTypePointer("virtio"), + Freeze: boolPointer(true), + FsTrim: boolPointer(true), + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + agentCfg := generateAgentConfig(tt.agentConfig) + + assert.Equal(t, agentCfg, tt.expectOutput) + }) + } +} diff --git a/builder/proxmox/iso/config.hcl2spec.go b/builder/proxmox/iso/config.hcl2spec.go index 9dcc1618..3dd21beb 100644 --- a/builder/proxmox/iso/config.hcl2spec.go +++ b/builder/proxmox/iso/config.hcl2spec.go @@ -109,6 +109,7 @@ type FlatConfig struct { PCIDevices []proxmox.FlatpciDeviceConfig `mapstructure:"pci_devices" cty:"pci_devices" hcl:"pci_devices"` Serials []string `mapstructure:"serials" cty:"serials" hcl:"serials"` Agent *bool `mapstructure:"qemu_agent" cty:"qemu_agent" hcl:"qemu_agent"` + GuestAgent *proxmox.FlatagentConfig `mapstructure:"qemu_guest_agent" cty:"qemu_guest_agent" hcl:"qemu_guest_agent"` SCSIController *string `mapstructure:"scsi_controller" cty:"scsi_controller" hcl:"scsi_controller"` Onboot *bool `mapstructure:"onboot" cty:"onboot" hcl:"onboot"` DisableKVM *bool `mapstructure:"disable_kvm" cty:"disable_kvm" hcl:"disable_kvm"` @@ -242,6 +243,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec { "pci_devices": &hcldec.BlockListSpec{TypeName: "pci_devices", Nested: hcldec.ObjectSpec((*proxmox.FlatpciDeviceConfig)(nil).HCL2Spec())}, "serials": &hcldec.AttrSpec{Name: "serials", Type: cty.List(cty.String), Required: false}, "qemu_agent": &hcldec.AttrSpec{Name: "qemu_agent", Type: cty.Bool, Required: false}, + "qemu_guest_agent": &hcldec.BlockSpec{TypeName: "qemu_guest_agent", Nested: hcldec.ObjectSpec((*proxmox.FlatagentConfig)(nil).HCL2Spec())}, "scsi_controller": &hcldec.AttrSpec{Name: "scsi_controller", Type: cty.String, Required: false}, "onboot": &hcldec.AttrSpec{Name: "onboot", Type: cty.Bool, Required: false}, "disable_kvm": &hcldec.AttrSpec{Name: "disable_kvm", Type: cty.Bool, Required: false}, diff --git a/builder/proxmox/iso/config_test.go b/builder/proxmox/iso/config_test.go index f2540087..524695e3 100644 --- a/builder/proxmox/iso/config_test.go +++ b/builder/proxmox/iso/config_test.go @@ -103,8 +103,8 @@ func TestBasicExampleFromDocsIsValid(t *testing.T) { if b.config.Disks[0].CacheMode != "none" { t.Errorf("Expected disk cache mode to be 'none', got %s", b.config.Disks[0].CacheMode) } - if b.config.Agent.True() != true { - t.Errorf("Expected Agent to be true, got %t", b.config.Agent.True()) + if b.config.GuestAgent.Enabled.True() != true { + t.Errorf("Expected Agent to be true, got %t", b.config.GuestAgent.Enabled.True()) } if b.config.DisableKVM != false { t.Errorf("Expected Disable KVM toggle to be false, got %t", b.config.DisableKVM) diff --git a/docs-partials/builder/proxmox/common/Config-not-required.mdx b/docs-partials/builder/proxmox/common/Config-not-required.mdx index 83de1cde..ce928ba2 100644 --- a/docs-partials/builder/proxmox/common/Config-not-required.mdx +++ b/docs-partials/builder/proxmox/common/Config-not-required.mdx @@ -106,10 +106,13 @@ ] ``` -- `qemu_agent` (boolean) - Enables QEMU Agent option for this VM. When enabled, +- `qemu_agent` (boolean) - DEPRECATED. Define QEMU Guest Agent settings in a `qemu_guest_agent` block instead. + Enables QEMU Agent option for this VM. When enabled, then `qemu-guest-agent` must be installed on the guest. When disabled, then `ssh_host` should be used. Defaults to `true`. +- `qemu_guest_agent` (agentConfig) - QEMU Guest Agent configuration. See [QEMU Guest Agent](#qemu-guest-agent) + - `scsi_controller` (string) - The SCSI controller model to emulate. Can be `lsi`, `lsi53c810`, `virtio-scsi-pci`, `virtio-scsi-single`, `megasas`, or `pvscsi`. Defaults to `lsi`. diff --git a/docs-partials/builder/proxmox/common/agentConfig-not-required.mdx b/docs-partials/builder/proxmox/common/agentConfig-not-required.mdx new file mode 100644 index 00000000..19957bae --- /dev/null +++ b/docs-partials/builder/proxmox/common/agentConfig-not-required.mdx @@ -0,0 +1,13 @@ + + +- `enabled` (boolean) - Enable QEMU Agent option for this VM. When enabled + `qemu-guest-agent` must be installed on the guest. When disabled + `ssh_host` should be used. Defaults to `true`. + +- `type` (string) - Sets the Agent Type. Must be `isa` or `virtio`. Defaults to `virtio` + +- `freeze` (boolean) - Enable freeze/thaw of guest filesystem on backup. Defaults to `true` + +- `fstrim` (bool) - Run guest-trim after a disk move or VM migration. Defaults to `false` + + diff --git a/docs-partials/builder/proxmox/common/agentConfig.mdx b/docs-partials/builder/proxmox/common/agentConfig.mdx new file mode 100644 index 00000000..2e919ca6 --- /dev/null +++ b/docs-partials/builder/proxmox/common/agentConfig.mdx @@ -0,0 +1,30 @@ + + +Set the QEMU Guest Agent options. + +JSON Example: + +```json + + "qemu_guest_agent": { + "enabled": true, + "type": "isa", + "freeze": false, + "fstrim": false + } + +``` +HCL2 example: + +```hcl + + qemu_guest_agent { + enabled = true + type = "isa" + freeze = false + fstrim = false + } + +``` + + diff --git a/docs/builders/clone.mdx b/docs/builders/clone.mdx index ae2348cd..ffa43ee6 100644 --- a/docs/builders/clone.mdx +++ b/docs/builders/clone.mdx @@ -103,6 +103,14 @@ to you to use it or delete it. @include 'builder/proxmox/common/efiConfig-not-required.mdx' +### QEMU Guest Agent + +@include 'builder/proxmox/common/agentConfig.mdx' + +#### Optional: + +@include 'builder/proxmox/common/agentConfig-not-required.mdx' + ### VirtIO RNG device @include 'builder/proxmox/common/rng0Config.mdx' diff --git a/docs/builders/iso.mdx b/docs/builders/iso.mdx index 99ca64b4..2fe6a267 100644 --- a/docs/builders/iso.mdx +++ b/docs/builders/iso.mdx @@ -90,6 +90,14 @@ to you to use it or delete it. @include 'builder/proxmox/common/efiConfig-not-required.mdx' +### QEMU Guest Agent + +@include 'builder/proxmox/common/agentConfig.mdx' + +#### Optional: + +@include 'builder/proxmox/common/agentConfig-not-required.mdx' + ### VirtIO RNG device @include 'builder/proxmox/common/rng0Config.mdx' From 0b738ef8aea3162c2d2658992c93146c1638a10b Mon Sep 17 00:00:00 2001 From: Martin Pywell Date: Fri, 4 Oct 2024 23:41:45 +1000 Subject: [PATCH 2/3] fix agent config test --- builder/proxmox/common/step_start_vm_test.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/builder/proxmox/common/step_start_vm_test.go b/builder/proxmox/common/step_start_vm_test.go index 91a84947..f9c19ddf 100644 --- a/builder/proxmox/common/step_start_vm_test.go +++ b/builder/proxmox/common/step_start_vm_test.go @@ -1389,15 +1389,15 @@ func TestGenerateQEMUAgentConfig(t *testing.T) { { "disable freeze", agentConfig{ - Enabled: config.TriFalse, + Enabled: config.TriTrue, Type: "virtio", - Freeze: config.TriTrue, + Freeze: config.TriFalse, FsTrim: true, }, &proxmox.QemuGuestAgent{ - Enable: boolPointer(false), + Enable: boolPointer(true), Type: qemuGuestAgentTypePointer("virtio"), - Freeze: boolPointer(true), + Freeze: boolPointer(false), FsTrim: boolPointer(true), }, }, From daafbbeb7d231a81a708fa6b905544ce00693d16 Mon Sep 17 00:00:00 2001 From: Martin Pywell Date: Wed, 30 Oct 2024 21:50:29 +1100 Subject: [PATCH 3/3] common: qemu_agent, qemu_guest_agent updates - fix qemu_agent deprecation warnings and conversion - invert freeze config option for qemu_guest_agent - simplify test logic for TestBasicExampleFromDocsIsValid --- .web-docs/components/builder/clone/README.md | 2 +- .web-docs/components/builder/iso/README.md | 2 +- builder/proxmox/common/config.go | 13 ++---- builder/proxmox/common/config.hcl2spec.go | 16 ++++---- builder/proxmox/common/step_start_vm.go | 7 +++- builder/proxmox/common/step_start_vm_test.go | 40 +++++++++---------- builder/proxmox/iso/config_test.go | 2 +- .../common/agentConfig-not-required.mdx | 2 +- 8 files changed, 42 insertions(+), 42 deletions(-) diff --git a/.web-docs/components/builder/clone/README.md b/.web-docs/components/builder/clone/README.md index 9aaacad3..3c34042b 100644 --- a/.web-docs/components/builder/clone/README.md +++ b/.web-docs/components/builder/clone/README.md @@ -873,7 +873,7 @@ HCL2 example: - `type` (string) - Sets the Agent Type. Must be `isa` or `virtio`. Defaults to `virtio` -- `freeze` (boolean) - Enable freeze/thaw of guest filesystem on backup. Defaults to `true` +- `disable_freeze` (bool) - Disable freeze/thaw of guest filesystem on backup. Defaults to `false` - `fstrim` (bool) - Run guest-trim after a disk move or VM migration. Defaults to `false` diff --git a/.web-docs/components/builder/iso/README.md b/.web-docs/components/builder/iso/README.md index 8144cd65..e7cb543e 100644 --- a/.web-docs/components/builder/iso/README.md +++ b/.web-docs/components/builder/iso/README.md @@ -714,7 +714,7 @@ HCL2 example: - `type` (string) - Sets the Agent Type. Must be `isa` or `virtio`. Defaults to `virtio` -- `freeze` (boolean) - Enable freeze/thaw of guest filesystem on backup. Defaults to `true` +- `disable_freeze` (bool) - Disable freeze/thaw of guest filesystem on backup. Defaults to `false` - `fstrim` (bool) - Run guest-trim after a disk move or VM migration. Defaults to `false` diff --git a/builder/proxmox/common/config.go b/builder/proxmox/common/config.go index 466eff14..2b934fa0 100644 --- a/builder/proxmox/common/config.go +++ b/builder/proxmox/common/config.go @@ -243,8 +243,8 @@ type agentConfig struct { Enabled config.Trilean `mapstructure:"enabled"` // Sets the Agent Type. Must be `isa` or `virtio`. Defaults to `virtio` Type string `mapstructure:"type"` - // Enable freeze/thaw of guest filesystem on backup. Defaults to `true` - Freeze config.Trilean `mapstructure:"freeze"` + // Disable freeze/thaw of guest filesystem on backup. Defaults to `false` + DisableFreeze bool `mapstructure:"disable_freeze"` // Run guest-trim after a disk move or VM migration. Defaults to `false` FsTrim bool `mapstructure:"fstrim"` } @@ -646,21 +646,16 @@ func (c *Config) Prepare(upper interface{}, raws ...interface{}) ([]string, []st warnings = append(warnings, "proxmox is deprecated, please use proxmox-iso instead") } - // Default qemu_agent to true - if c.Agent != config.TriFalse { + if c.Agent != config.TriUnset { warnings = append(warnings, "qemu_agent is deprecated and will be removed in a future release. define QEMU agent settings in a qemu_guest_agent block instead") // convert to qemu_guest_agent block value - c.GuestAgent.Enabled = config.TriTrue + c.GuestAgent.Enabled = c.Agent } // Default qemu_guest_agent.enable to true if c.GuestAgent.Enabled != config.TriFalse { c.GuestAgent.Enabled = config.TriTrue } - // Default qemu_guest_agent.freeze to true - if c.GuestAgent.Freeze != config.TriFalse { - c.GuestAgent.Freeze = config.TriTrue - } switch c.GuestAgent.Type { case "virtio", "isa": diff --git a/builder/proxmox/common/config.hcl2spec.go b/builder/proxmox/common/config.hcl2spec.go index be7ab735..b64d5a0b 100644 --- a/builder/proxmox/common/config.hcl2spec.go +++ b/builder/proxmox/common/config.hcl2spec.go @@ -339,10 +339,10 @@ func (*FlatNICConfig) HCL2Spec() map[string]hcldec.Spec { // FlatagentConfig is an auto-generated flat version of agentConfig. // Where the contents of a field with a `mapstructure:,squash` tag are bubbled up. type FlatagentConfig struct { - Enabled *bool `mapstructure:"enabled" cty:"enabled" hcl:"enabled"` - Type *string `mapstructure:"type" cty:"type" hcl:"type"` - Freeze *bool `mapstructure:"freeze" cty:"freeze" hcl:"freeze"` - FsTrim *bool `mapstructure:"fstrim" cty:"fstrim" hcl:"fstrim"` + Enabled *bool `mapstructure:"enabled" cty:"enabled" hcl:"enabled"` + Type *string `mapstructure:"type" cty:"type" hcl:"type"` + DisableFreeze *bool `mapstructure:"disable_freeze" cty:"disable_freeze" hcl:"disable_freeze"` + FsTrim *bool `mapstructure:"fstrim" cty:"fstrim" hcl:"fstrim"` } // FlatMapstructure returns a new FlatagentConfig. @@ -357,10 +357,10 @@ func (*agentConfig) FlatMapstructure() interface{ HCL2Spec() map[string]hcldec.S // The decoded values from this spec will then be applied to a FlatagentConfig. func (*FlatagentConfig) HCL2Spec() map[string]hcldec.Spec { s := map[string]hcldec.Spec{ - "enabled": &hcldec.AttrSpec{Name: "enabled", Type: cty.Bool, Required: false}, - "type": &hcldec.AttrSpec{Name: "type", Type: cty.String, Required: false}, - "freeze": &hcldec.AttrSpec{Name: "freeze", Type: cty.Bool, Required: false}, - "fstrim": &hcldec.AttrSpec{Name: "fstrim", Type: cty.Bool, Required: false}, + "enabled": &hcldec.AttrSpec{Name: "enabled", Type: cty.Bool, Required: false}, + "type": &hcldec.AttrSpec{Name: "type", Type: cty.String, Required: false}, + "disable_freeze": &hcldec.AttrSpec{Name: "disable_freeze", Type: cty.Bool, Required: false}, + "fstrim": &hcldec.AttrSpec{Name: "fstrim", Type: cty.Bool, Required: false}, } return s } diff --git a/builder/proxmox/common/step_start_vm.go b/builder/proxmox/common/step_start_vm.go index aef5875f..090e460c 100644 --- a/builder/proxmox/common/step_start_vm.go +++ b/builder/proxmox/common/step_start_vm.go @@ -256,9 +256,14 @@ func (s *stepStartVM) Run(ctx context.Context, state multistep.StateBag) multist func generateAgentConfig(agent agentConfig) *proxmox.QemuGuestAgent { var agentCfg proxmox.QemuGuestAgent + freeze := true agentCfg.Enable = agent.Enabled.ToBoolPointer() - agentCfg.Freeze = agent.Freeze.ToBoolPointer() + + if agent.DisableFreeze { + freeze = false + } + agentCfg.Freeze = &freeze agentType := proxmox.QemuGuestAgentType(agent.Type) agentCfg.Type = &agentType diff --git a/builder/proxmox/common/step_start_vm_test.go b/builder/proxmox/common/step_start_vm_test.go index f9c19ddf..0e4e41e4 100644 --- a/builder/proxmox/common/step_start_vm_test.go +++ b/builder/proxmox/common/step_start_vm_test.go @@ -1329,10 +1329,10 @@ func TestGenerateQEMUAgentConfig(t *testing.T) { { "plain config, no special options set", agentConfig{ - Enabled: config.TriTrue, - Type: "virtio", - Freeze: config.TriTrue, - FsTrim: false, + Enabled: config.TriTrue, + Type: "virtio", + DisableFreeze: false, + FsTrim: false, }, &proxmox.QemuGuestAgent{ Enable: boolPointer(true), @@ -1344,10 +1344,10 @@ func TestGenerateQEMUAgentConfig(t *testing.T) { { "configure for isa type", agentConfig{ - Enabled: config.TriTrue, - Type: "isa", - Freeze: config.TriTrue, - FsTrim: false, + Enabled: config.TriTrue, + Type: "isa", + DisableFreeze: false, + FsTrim: false, }, &proxmox.QemuGuestAgent{ Enable: boolPointer(true), @@ -1359,10 +1359,10 @@ func TestGenerateQEMUAgentConfig(t *testing.T) { { "disable agent", agentConfig{ - Enabled: config.TriFalse, - Type: "virtio", - Freeze: config.TriTrue, - FsTrim: false, + Enabled: config.TriFalse, + Type: "virtio", + DisableFreeze: false, + FsTrim: false, }, &proxmox.QemuGuestAgent{ Enable: boolPointer(false), @@ -1374,10 +1374,10 @@ func TestGenerateQEMUAgentConfig(t *testing.T) { { "enable fstrim", agentConfig{ - Enabled: config.TriFalse, - Type: "virtio", - Freeze: config.TriTrue, - FsTrim: true, + Enabled: config.TriFalse, + Type: "virtio", + DisableFreeze: false, + FsTrim: true, }, &proxmox.QemuGuestAgent{ Enable: boolPointer(false), @@ -1389,10 +1389,10 @@ func TestGenerateQEMUAgentConfig(t *testing.T) { { "disable freeze", agentConfig{ - Enabled: config.TriTrue, - Type: "virtio", - Freeze: config.TriFalse, - FsTrim: true, + Enabled: config.TriTrue, + Type: "virtio", + DisableFreeze: true, + FsTrim: true, }, &proxmox.QemuGuestAgent{ Enable: boolPointer(true), diff --git a/builder/proxmox/iso/config_test.go b/builder/proxmox/iso/config_test.go index 524695e3..1fbad342 100644 --- a/builder/proxmox/iso/config_test.go +++ b/builder/proxmox/iso/config_test.go @@ -103,7 +103,7 @@ func TestBasicExampleFromDocsIsValid(t *testing.T) { if b.config.Disks[0].CacheMode != "none" { t.Errorf("Expected disk cache mode to be 'none', got %s", b.config.Disks[0].CacheMode) } - if b.config.GuestAgent.Enabled.True() != true { + if !b.config.GuestAgent.Enabled.True() { t.Errorf("Expected Agent to be true, got %t", b.config.GuestAgent.Enabled.True()) } if b.config.DisableKVM != false { diff --git a/docs-partials/builder/proxmox/common/agentConfig-not-required.mdx b/docs-partials/builder/proxmox/common/agentConfig-not-required.mdx index 19957bae..9ac2a217 100644 --- a/docs-partials/builder/proxmox/common/agentConfig-not-required.mdx +++ b/docs-partials/builder/proxmox/common/agentConfig-not-required.mdx @@ -6,7 +6,7 @@ - `type` (string) - Sets the Agent Type. Must be `isa` or `virtio`. Defaults to `virtio` -- `freeze` (boolean) - Enable freeze/thaw of guest filesystem on backup. Defaults to `true` +- `disable_freeze` (bool) - Disable freeze/thaw of guest filesystem on backup. Defaults to `false` - `fstrim` (bool) - Run guest-trim after a disk move or VM migration. Defaults to `false`