Repository: hashicorp/packer-plugin-proxmox (language: go)

Issue:
Ballooning/Dynamic Memory
#### Description

It would be great if we could set the min/max RAM available to the VM. 

Currently, we can set the memory as a single value, but Proxmox allows for ballooning.

#### Potential configuration

```
Memory:
Minimum_Memory:
Shares:
Ballooning Device:
```

![image](https://user-images.githubusercontent.com/4349962/204045278-c08d38ca-7fbb-4c67-9e29-501d14fd1b87.png)

#### Potential References
https://pve.proxmox.com/wiki/Dynamic_Memory_Management


Discussion / hints:
Absolutely agree. This would be super nice indeed!

Fix patch:
diff --git a/builder/proxmox/clone/config.hcl2spec.go b/builder/proxmox/clone/config.hcl2spec.go
index 9c8c8c16..781e4a65 100644
--- a/builder/proxmox/clone/config.hcl2spec.go
+++ b/builder/proxmox/clone/config.hcl2spec.go
@@ -90,6 +90,7 @@ type FlatConfig struct {
 	VMID                      *int                               `mapstructure:"vm_id" cty:"vm_id" hcl:"vm_id"`
 	Boot                      *string                            `mapstructure:"boot" cty:"boot" hcl:"boot"`
 	Memory                    *int                               `mapstructure:"memory" cty:"memory" hcl:"memory"`
+	BalloonMinimum            *int                               `mapstructure:"ballooning_minimum" cty:"ballooning_minimum" hcl:"ballooning_minimum"`
 	Cores                     *int                               `mapstructure:"cores" cty:"cores" hcl:"cores"`
 	CPUType                   *string                            `mapstructure:"cpu_type" cty:"cpu_type" hcl:"cpu_type"`
 	Sockets                   *int                               `mapstructure:"sockets" cty:"sockets" hcl:"sockets"`
@@ -211,6 +212,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
 		"vm_id":                        &hcldec.AttrSpec{Name: "vm_id", Type: cty.Number, Required: false},
 		"boot":                         &hcldec.AttrSpec{Name: "boot", Type: cty.String, Required: false},
 		"memory":                       &hcldec.AttrSpec{Name: "memory", Type: cty.Number, Required: false},
+		"ballooning_minimum":           &hcldec.AttrSpec{Name: "ballooning_minimum", Type: cty.Number, Required: false},
 		"cores":                        &hcldec.AttrSpec{Name: "cores", Type: cty.Number, Required: false},
 		"cpu_type":                     &hcldec.AttrSpec{Name: "cpu_type", Type: cty.String, Required: false},
 		"sockets":                      &hcldec.AttrSpec{Name: "sockets", Type: cty.Number, Required: false},
diff --git a/builder/proxmox/common/config.go b/builder/proxmox/common/config.go
index b5f9c53c..f27829ed 100644
--- a/builder/proxmox/common/config.go
+++ b/builder/proxmox/common/config.go
@@ -50,6 +50,7 @@ type Config struct {
 
 	Boot           string         `mapstructure:"boot"`
 	Memory         int            `mapstructure:"memory"`
+	BalloonMinimum int            `mapstructure:"ballooning_minimum"`
 	Cores          int            `mapstructure:"cores"`
 	CPUType        string         `mapstructure:"cpu_type"`
 	Sockets        int            `mapstructure:"sockets"`
@@ -187,6 +188,9 @@ func (c *Config) Prepare(upper interface{}, raws ...interface{}) ([]string, []st
 		log.Printf("Memory %d is too small, using default: 512", c.Memory)
 		c.Memory = 512
 	}
+	if c.Memory < c.BalloonMinimum {
+		errs = packersdk.MultiErrorAppend(errs, fmt.Errorf("ballooning_minimum (%d) must be lower than memory (%d)", c.BalloonMinimum, c.Memory))
+	}
 	if c.Cores < 1 {
 		log.Printf("Number of cores %d is too small, using default: 1", c.Cores)
 		c.Cores = 1
diff --git a/builder/proxmox/common/config.hcl2spec.go b/builder/proxmox/common/config.hcl2spec.go
index 2f91f981..829029a1 100644
--- a/builder/proxmox/common/config.hcl2spec.go
+++ b/builder/proxmox/common/config.hcl2spec.go
@@ -89,6 +89,7 @@ type FlatConfig struct {
 	VMID                      *int                       `mapstructure:"vm_id" cty:"vm_id" hcl:"vm_id"`
 	Boot                      *string                    `mapstructure:"boot" cty:"boot" hcl:"boot"`
 	Memory                    *int                       `mapstructure:"memory" cty:"memory" hcl:"memory"`
+	BalloonMinimum            *int                       `mapstructure:"ballooning_minimum" cty:"ballooning_minimum" hcl:"ballooning_minimum"`
 	Cores                     *int                       `mapstructure:"cores" cty:"cores" hcl:"cores"`
 	CPUType                   *string                    `mapstructure:"cpu_type" cty:"cpu_type" hcl:"cpu_type"`
 	Sockets                   *int                       `mapstructure:"sockets" cty:"sockets" hcl:"sockets"`
@@ -204,6 +205,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
 		"vm_id":                        &hcldec.AttrSpec{Name: "vm_id", Type: cty.Number, Required: false},
 		"boot":                         &hcldec.AttrSpec{Name: "boot", Type: cty.String, Required: false},
 		"memory":                       &hcldec.AttrSpec{Name: "memory", Type: cty.Number, Required: false},
+		"ballooning_minimum":           &hcldec.AttrSpec{Name: "ballooning_minimum", Type: cty.Number, Required: false},
 		"cores":                        &hcldec.AttrSpec{Name: "cores", Type: cty.Number, Required: false},
 		"cpu_type":                     &hcldec.AttrSpec{Name: "cpu_type", Type: cty.String, Required: false},
 		"sockets":                      &hcldec.AttrSpec{Name: "sockets", Type: cty.Number, Required: false},
diff --git a/builder/proxmox/common/step_start_vm.go b/builder/proxmox/common/step_start_vm.go
index d7be6841..9350fa7e 100644
--- a/builder/proxmox/common/step_start_vm.go
+++ b/builder/proxmox/common/step_start_vm.go
@@ -131,6 +131,13 @@ func (s *stepStartVM) Run(ctx context.Context, state multistep.StateBag) multist
 		Onboot:       &c.Onboot,
 	}
 
+	// 0 disables the ballooning device, which is useful for all VMs
+	// and should be kept enabled by default.
+	// See https://github.com/hashicorp/packer-plugin-proxmox/issues/127#issuecomment-1464030102
+	if c.BalloonMinimum > 0 {
+		config.Balloon = c.BalloonMinimum
+	}
+
 	if c.PackerForce {
 		ui.Say("Force set, checking for existing artifact on PVE cluster")
 		vmRef, err := getExistingTemplate(c, client)
diff --git a/builder/proxmox/iso/config.hcl2spec.go b/builder/proxmox/iso/config.hcl2spec.go
index 869cc364..d0ed202d 100644
--- a/builder/proxmox/iso/config.hcl2spec.go
+++ b/builder/proxmox/iso/config.hcl2spec.go
@@ -90,6 +90,7 @@ type FlatConfig struct {
 	VMID                      *int                               `mapstructure:"vm_id" cty:"vm_id" hcl:"vm_id"`
 	Boot                      *string                            `mapstructure:"boot" cty:"boot" hcl:"boot"`
 	Memory                    *int                               `mapstructure:"memory" cty:"memory" hcl:"memory"`
+	BalloonMinimum            *int                               `mapstructure:"ballooning_minimum" cty:"ballooning_minimum" hcl:"ballooning_minimum"`
 	Cores                     *int                               `mapstructure:"cores" cty:"cores" hcl:"cores"`
 	CPUType                   *string                            `mapstructure:"cpu_type" cty:"cpu_type" hcl:"cpu_type"`
 	Sockets                   *int                               `mapstructure:"sockets" cty:"sockets" hcl:"sockets"`
@@ -214,6 +215,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
 		"vm_id":                        &hcldec.AttrSpec{Name: "vm_id", Type: cty.Number, Required: false},
 		"boot":                         &hcldec.AttrSpec{Name: "boot", Type: cty.String, Required: false},
 		"memory":                       &hcldec.AttrSpec{Name: "memory", Type: cty.Number, Required: false},
+		"ballooning_minimum":           &hcldec.AttrSpec{Name: "ballooning_minimum", Type: cty.Number, Required: false},
 		"cores":                        &hcldec.AttrSpec{Name: "cores", Type: cty.Number, Required: false},
 		"cpu_type":                     &hcldec.AttrSpec{Name: "cpu_type", Type: cty.String, Required: false},
 		"sockets":                      &hcldec.AttrSpec{Name: "sockets", Type: cty.Number, Required: false},
diff --git a/docs-partials/builder/proxmox/common/Config-not-required.mdx b/docs-partials/builder/proxmox/common/Config-not-required.mdx
index 6621a961..60e21c8d 100644
--- a/docs-partials/builder/proxmox/common/Config-not-required.mdx
+++ b/docs-partials/builder/proxmox/common/Config-not-required.mdx
@@ -26,6 +26,8 @@
 
 - `memory` (int) - Memory
 
+- `ballooning_minimum` (int) - Balloon Minimum
+
 - `cores` (int) - Cores
 
 - `cpu_type` (string) - CPU Type
diff --git a/docs/builders/clone.mdx b/docs/builders/clone.mdx
index bfc3ec86..9c701c66 100644
--- a/docs/builders/clone.mdx
+++ b/docs/builders/clone.mdx
@@ -91,8 +91,14 @@ in the image's Cloud-Init settings for provisioning.
   and are limited to the range 100-999999999.
   If not given, the next free ID on the cluster will be used.
 
-- `memory` (int) - How much memory, in megabytes, to give the virtual
-  machine. Defaults to `512`.
+- `memory` (int) - How much memory (in megabytes) to give the virtual
+  machine. If `ballooning_minimum` is also set, `memory` defines the maximum amount
+  of memory the VM will be able to use.
+  Defaults to `512`.
+
+- `ballooning_minimum` (int) - Setting this option enables KVM memory ballooning and
+  defines the minimum amount of memory (in megabytes) the VM will have.
+  Defaults to `0` (memory ballooning disabled).
 
 - `cores` (int) - How many CPU cores to give the virtual machine. Defaults
   to `1`.
diff --git a/docs/builders/iso.mdx b/docs/builders/iso.mdx
index 7740bfc9..dece584f 100644
--- a/docs/builders/iso.mdx
+++ b/docs/builders/iso.mdx
@@ -102,8 +102,14 @@ in the image's Cloud-Init settings for provisioning.
   and are limited to the range 100-999999999.
   If not given, the next free ID on the cluster will be used.
 
-- `memory` (int) - How much memory, in megabytes, to give the virtual
-  machine. Defaults to `512`.
+- `memory` (int) - How much memory (in megabytes) to give the virtual
+  machine. If `ballooning_minimum` is also set, `memory` defines the maximum amount
+  of memory the VM will be able to use.
+  Defaults to `512`.
+
+- `ballooning_minimum` (int) - Setting this option enables KVM memory ballooning and
+  defines the minimum amount of memory (in megabytes) the VM will have.
+  Defaults to `0` (memory ballooning disabled).
 
 - `cores` (int) - How many CPU cores to give the virtual machine. Defaults
   to `1`.


Test patch: