diff --git a/.web-docs/components/builder/clone/README.md b/.web-docs/components/builder/clone/README.md index a60f5488..d4552350 100644 --- a/.web-docs/components/builder/clone/README.md +++ b/.web-docs/components/builder/clone/README.md @@ -185,23 +185,23 @@ boot time. - `boot` (string) - Override default boot order. Format example `order=virtio0;ide2;net0`. Prior to Proxmox 6.2-15 the format was `cdn` (c:CDROM -> d:Disk -> n:Network) -- `memory` (int) - How much memory (in megabytes) to give the virtual +- `memory` (uint32) - 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 +- `ballooning_minimum` (uint32) - 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 +- `cores` (uint8) - How many CPU cores to give the virtual machine. Defaults to `1`. - `cpu_type` (string) - The CPU type to emulate. See the Proxmox API documentation for the complete list of accepted values. For best performance, set this to `host`. Defaults to `kvm64`. -- `sockets` (int) - How many CPU sockets to give the virtual machine. +- `sockets` (uint8) - How many CPU sockets to give the virtual machine. Defaults to `1` - `numa` (bool) - If true, support for non-uniform memory access (NUMA) diff --git a/.web-docs/components/builder/iso/README.md b/.web-docs/components/builder/iso/README.md index cd806e81..f9750c7b 100644 --- a/.web-docs/components/builder/iso/README.md +++ b/.web-docs/components/builder/iso/README.md @@ -120,23 +120,23 @@ in the image's Cloud-Init settings for provisioning. - `boot` (string) - Override default boot order. Format example `order=virtio0;ide2;net0`. Prior to Proxmox 6.2-15 the format was `cdn` (c:CDROM -> d:Disk -> n:Network) -- `memory` (int) - How much memory (in megabytes) to give the virtual +- `memory` (uint32) - 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 +- `ballooning_minimum` (uint32) - 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 +- `cores` (uint8) - How many CPU cores to give the virtual machine. Defaults to `1`. - `cpu_type` (string) - The CPU type to emulate. See the Proxmox API documentation for the complete list of accepted values. For best performance, set this to `host`. Defaults to `kvm64`. -- `sockets` (int) - How many CPU sockets to give the virtual machine. +- `sockets` (uint8) - How many CPU sockets to give the virtual machine. Defaults to `1` - `numa` (bool) - If true, support for non-uniform memory access (NUMA) diff --git a/builder/proxmox/clone/builder.go b/builder/proxmox/clone/builder.go index bfc94d6f..9b6d512e 100644 --- a/builder/proxmox/clone/builder.go +++ b/builder/proxmox/clone/builder.go @@ -4,6 +4,10 @@ package proxmoxclone import ( + "crypto" + "net/netip" + "strings" + proxmoxapi "github.com/Telmate/proxmox-api-go/proxmox" "github.com/hashicorp/hcl/v2/hcldec" proxmox "github.com/hashicorp/packer-plugin-proxmox/builder/proxmox/common" @@ -61,17 +65,78 @@ func (*cloneVMCreator) Create(vmRef *proxmoxapi.VmRef, config proxmoxapi.ConfigQ config.FullClone = &fullClone // cloud-init options - config.CIuser = comm.SSHUsername - config.Sshkeys = string(comm.SSHPublicKey) - config.Nameserver = c.Nameserver - config.Searchdomain = c.Searchdomain - IpconfigMap := make(map[int]interface{}) + + var nameServers []netip.Addr + if c.Nameserver != "" { + for _, nameserver := range strings.Split(c.Nameserver, " ") { + ip, _ := netip.ParseAddr(nameserver) + nameServers = append(nameServers, ip) + } + } + + IpconfigMap := proxmoxapi.CloudInitNetworkInterfaces{} for idx := range c.Ipconfigs { if c.Ipconfigs[idx] != (cloudInitIpconfig{}) { - IpconfigMap[idx] = c.Ipconfigs[idx].String() + + // backwards compatibility conversions + + var ipv4cfg proxmoxapi.CloudInitIPv4Config + var ipv6cfg proxmoxapi.CloudInitIPv6Config + + // cloudInitIpconfig.Ip accepts a CIDR address or 'dhcp' string + switch c.Ipconfigs[idx].Ip { + case "dhcp": + ipv4cfg.DHCP = true + default: + if c.Ipconfigs[idx].Ip != "" { + addr := proxmoxapi.IPv4CIDR(c.Ipconfigs[idx].Ip) + ipv4cfg.Address = &addr + } + } + if c.Ipconfigs[idx].Gateway != "" { + gw := proxmoxapi.IPv4Address(c.Ipconfigs[idx].Gateway) + ipv4cfg.Gateway = &gw + } + + // cloudInitIpconfig.Ip6 accepts a CIDR address, 'auto' or 'dhcp' string + switch c.Ipconfigs[idx].Ip6 { + case "dhcp": + ipv6cfg.DHCP = true + case "auto": + ipv6cfg.SLAAC = true + default: + if c.Ipconfigs[idx].Ip6 != "" { + addr := proxmoxapi.IPv6CIDR(c.Ipconfigs[idx].Ip6) + ipv6cfg.Address = &addr + } + } + if c.Ipconfigs[idx].Gateway6 != "" { + addr := proxmoxapi.IPv6Address(c.Ipconfigs[idx].Gateway6) + ipv6cfg.Gateway = &addr + } + + IpconfigMap[proxmoxapi.QemuNetworkInterfaceID(idx)] = proxmoxapi.CloudInitNetworkConfig{ + IPv4: &ipv4cfg, + IPv6: &ipv6cfg, + } } } - config.Ipconfig = IpconfigMap + + var publicKey []crypto.PublicKey + + if comm.SSHPublicKey != nil { + publicKey = append(publicKey, crypto.PublicKey(string(comm.SSHPublicKey))) + } + + config.CloudInit = &proxmoxapi.CloudInit{ + Username: &comm.SSHUsername, + PublicSSHkeys: &publicKey, + DNS: &proxmoxapi.GuestDNS{ + NameServers: &nameServers, + SearchDomain: &c.Searchdomain, + }, + NetworkInterfaces: IpconfigMap, + } var sourceVmr *proxmoxapi.VmRef if c.CloneVM != "" { diff --git a/builder/proxmox/clone/config.hcl2spec.go b/builder/proxmox/clone/config.hcl2spec.go index e131cb6b..0de5951f 100644 --- a/builder/proxmox/clone/config.hcl2spec.go +++ b/builder/proxmox/clone/config.hcl2spec.go @@ -90,11 +90,11 @@ type FlatConfig struct { VMID *int `mapstructure:"vm_id" cty:"vm_id" hcl:"vm_id"` Tags *string `mapstructure:"tags" cty:"tags" hcl:"tags"` 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"` + Memory *uint32 `mapstructure:"memory" cty:"memory" hcl:"memory"` + BalloonMinimum *uint32 `mapstructure:"ballooning_minimum" cty:"ballooning_minimum" hcl:"ballooning_minimum"` + Cores *uint8 `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"` + Sockets *uint8 `mapstructure:"sockets" cty:"sockets" hcl:"sockets"` Numa *bool `mapstructure:"numa" cty:"numa" hcl:"numa"` OS *string `mapstructure:"os" cty:"os" hcl:"os"` BIOS *string `mapstructure:"bios" cty:"bios" hcl:"bios"` diff --git a/builder/proxmox/common/config.go b/builder/proxmox/common/config.go index 2a29d944..6ceee0de 100644 --- a/builder/proxmox/common/config.go +++ b/builder/proxmox/common/config.go @@ -104,21 +104,21 @@ type Config struct { // machine. If `ballooning_minimum` is also set, `memory` defines the maximum amount // of memory the VM will be able to use. // Defaults to `512`. - Memory int `mapstructure:"memory"` + Memory uint32 `mapstructure:"memory"` // 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). - BalloonMinimum int `mapstructure:"ballooning_minimum"` + BalloonMinimum uint32 `mapstructure:"ballooning_minimum"` // How many CPU cores to give the virtual machine. Defaults // to `1`. - Cores int `mapstructure:"cores"` + Cores uint8 `mapstructure:"cores"` // The CPU type to emulate. See the Proxmox API // documentation for the complete list of accepted values. For best // performance, set this to `host`. Defaults to `kvm64`. CPUType string `mapstructure:"cpu_type"` // How many CPU sockets to give the virtual machine. // Defaults to `1` - Sockets int `mapstructure:"sockets"` + Sockets uint8 `mapstructure:"sockets"` // If true, support for non-uniform memory access (NUMA) // is enabled. Defaults to `false`. Numa bool `mapstructure:"numa"` @@ -678,6 +678,11 @@ func (c *Config) Prepare(upper interface{}, raws ...interface{}) ([]string, []st // (possibly to a local file) to an ISO file that will be downloaded and // then uploaded to Proxmox. if c.ISOs[idx].ISOFile != "" { + // ISOFile should match :iso/ format + res := regexp.MustCompile(`^.+:iso\/.+$`) + if !res.MatchString(c.ISOs[idx].ISOFile) { + errs = packersdk.MultiErrorAppend(errs, fmt.Errorf("iso_path should match pattern \":iso/\". Provided value was \"%s\"", c.ISOs[idx].ISOFile)) + } c.ISOs[idx].ShouldUploadISO = false } else { c.ISOs[idx].DownloadPathKey = "downloaded_additional_iso_path_" + strconv.Itoa(idx) diff --git a/builder/proxmox/common/config.hcl2spec.go b/builder/proxmox/common/config.hcl2spec.go index cb619338..de4bae7c 100644 --- a/builder/proxmox/common/config.hcl2spec.go +++ b/builder/proxmox/common/config.hcl2spec.go @@ -89,11 +89,11 @@ type FlatConfig struct { VMID *int `mapstructure:"vm_id" cty:"vm_id" hcl:"vm_id"` Tags *string `mapstructure:"tags" cty:"tags" hcl:"tags"` 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"` + Memory *uint32 `mapstructure:"memory" cty:"memory" hcl:"memory"` + BalloonMinimum *uint32 `mapstructure:"ballooning_minimum" cty:"ballooning_minimum" hcl:"ballooning_minimum"` + Cores *uint8 `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"` + Sockets *uint8 `mapstructure:"sockets" cty:"sockets" hcl:"sockets"` Numa *bool `mapstructure:"numa" cty:"numa" hcl:"numa"` OS *string `mapstructure:"os" cty:"os" hcl:"os"` BIOS *string `mapstructure:"bios" cty:"bios" hcl:"bios"` diff --git a/builder/proxmox/common/config_test.go b/builder/proxmox/common/config_test.go index 50cbc39d..eeec71ba 100644 --- a/builder/proxmox/common/config_test.go +++ b/builder/proxmox/common/config_test.go @@ -151,6 +151,17 @@ func TestISOs(t *testing.T) { "type": "ide", }, }, + { + name: "iso_file should fail if not correct format", + expectedToFail: true, + ISOs: map[string]interface{}{ + "type": "ide", + "cd_files": []string{ + "config_test.go", + }, + "iso_file": "local:/test.iso", + }, + }, { name: "cd_files and iso_file specified should fail", expectedToFail: true, diff --git a/builder/proxmox/common/step_start_vm.go b/builder/proxmox/common/step_start_vm.go index 7e05e53b..3781c6b1 100644 --- a/builder/proxmox/common/step_start_vm.go +++ b/builder/proxmox/common/step_start_vm.go @@ -119,18 +119,23 @@ func (s *stepStartVM) Run(ctx context.Context, state multistep.StateBag) multist } } + var description = "Packer ephemeral build VM" + config := proxmox.ConfigQemu{ - Name: c.VMName, - Agent: generateAgentConfig(c.Agent), - QemuKVM: &kvm, - Tags: generateTags(c.Tags), - Boot: c.Boot, // Boot priority, example: "order=virtio0;ide2;net0", virtio0:Disk0 -> ide0:CDROM -> net0:Network - QemuCpu: c.CPUType, - Description: "Packer ephemeral build VM", - Memory: c.Memory, - QemuCores: c.Cores, - QemuSockets: c.Sockets, - QemuNuma: &c.Numa, + Name: c.VMName, + Agent: generateAgentConfig(c.Agent), + QemuKVM: &kvm, + Tags: generateTags(c.Tags), + Boot: c.Boot, // Boot priority, example: "order=virtio0;ide2;net0", virtio0:Disk0 -> ide0:CDROM -> net0:Network + CPU: &proxmox.QemuCPU{ + Cores: (*proxmox.QemuCpuCores)(&c.Cores), + Sockets: (*proxmox.QemuCpuSockets)(&c.Sockets), + Numa: &c.Numa, + }, + Description: &description, + Memory: &proxmox.QemuMemory{ + CapacityMiB: (*proxmox.QemuMemoryCapacity)(&c.Memory), + }, QemuOs: c.OS, Bios: c.BIOS, EFIDisk: generateProxmoxEfi(c.EFIConfig), @@ -141,7 +146,7 @@ func (s *stepStartVM) Run(ctx context.Context, state multistep.StateBag) multist QemuNetworks: generateProxmoxNetworkAdapters(c.NICs), Disks: disks, QemuPCIDevices: generateProxmoxPCIDeviceMap(c.PCIDevices), - QemuSerials: generateProxmoxSerials(c.Serials), + Serials: generateProxmoxSerials(c.Serials), Scsihw: c.SCSIController, Onboot: &c.Onboot, Args: c.AdditionalArgs, @@ -152,7 +157,7 @@ func (s *stepStartVM) Run(ctx context.Context, state multistep.StateBag) multist // 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 + config.Memory.MinimumCapacityMiB = (*proxmox.QemuMemoryBalloonCapacity)(&c.BalloonMinimum) } if c.PackerForce { @@ -695,11 +700,19 @@ func generateProxmoxPCIDeviceMap(devices []pciDeviceConfig) proxmox.QemuDevices return devs } -func generateProxmoxSerials(serials []string) proxmox.QemuDevices { - devs := make(proxmox.QemuDevices) - for idx := range serials { - devs[idx] = make(proxmox.QemuDevice) - setDeviceParamIfDefined(devs[idx], "type", serials[idx]) +func generateProxmoxSerials(serials []string) proxmox.SerialInterfaces { + devs := make(proxmox.SerialInterfaces) + for idx, serial := range serials { + switch serial { + case "socket": + devs[proxmox.SerialID(idx)] = proxmox.SerialInterface{ + Socket: true, + } + default: + devs[proxmox.SerialID(idx)] = proxmox.SerialInterface{ + Path: proxmox.SerialPath(serial), + } + } } return devs } diff --git a/builder/proxmox/iso/config.hcl2spec.go b/builder/proxmox/iso/config.hcl2spec.go index 3e77a919..9dcc1618 100644 --- a/builder/proxmox/iso/config.hcl2spec.go +++ b/builder/proxmox/iso/config.hcl2spec.go @@ -90,11 +90,11 @@ type FlatConfig struct { VMID *int `mapstructure:"vm_id" cty:"vm_id" hcl:"vm_id"` Tags *string `mapstructure:"tags" cty:"tags" hcl:"tags"` 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"` + Memory *uint32 `mapstructure:"memory" cty:"memory" hcl:"memory"` + BalloonMinimum *uint32 `mapstructure:"ballooning_minimum" cty:"ballooning_minimum" hcl:"ballooning_minimum"` + Cores *uint8 `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"` + Sockets *uint8 `mapstructure:"sockets" cty:"sockets" hcl:"sockets"` Numa *bool `mapstructure:"numa" cty:"numa" hcl:"numa"` OS *string `mapstructure:"os" cty:"os" hcl:"os"` BIOS *string `mapstructure:"bios" cty:"bios" hcl:"bios"` diff --git a/docs-partials/builder/proxmox/common/Config-not-required.mdx b/docs-partials/builder/proxmox/common/Config-not-required.mdx index bf8dea12..83de1cde 100644 --- a/docs-partials/builder/proxmox/common/Config-not-required.mdx +++ b/docs-partials/builder/proxmox/common/Config-not-required.mdx @@ -48,23 +48,23 @@ - `boot` (string) - Override default boot order. Format example `order=virtio0;ide2;net0`. Prior to Proxmox 6.2-15 the format was `cdn` (c:CDROM -> d:Disk -> n:Network) -- `memory` (int) - How much memory (in megabytes) to give the virtual +- `memory` (uint32) - 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 +- `ballooning_minimum` (uint32) - 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 +- `cores` (uint8) - How many CPU cores to give the virtual machine. Defaults to `1`. - `cpu_type` (string) - The CPU type to emulate. See the Proxmox API documentation for the complete list of accepted values. For best performance, set this to `host`. Defaults to `kvm64`. -- `sockets` (int) - How many CPU sockets to give the virtual machine. +- `sockets` (uint8) - How many CPU sockets to give the virtual machine. Defaults to `1` - `numa` (bool) - If true, support for non-uniform memory access (NUMA) diff --git a/go.mod b/go.mod index 3debc62a..f5535b90 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/hashicorp/packer-plugin-proxmox go 1.21.0 require ( - github.com/Telmate/proxmox-api-go v0.0.0-20240525163725-6676d8933df0 + github.com/Telmate/proxmox-api-go v0.0.0-20241022204517-b149708f750b github.com/hashicorp/go-getter/v2 v2.2.2 github.com/hashicorp/hcl/v2 v2.19.1 github.com/hashicorp/packer-plugin-sdk v0.5.4 diff --git a/go.sum b/go.sum index 8b4e3804..cda12bb1 100644 --- a/go.sum +++ b/go.sum @@ -22,6 +22,8 @@ github.com/Telmate/proxmox-api-go v0.0.0-20240409105641-32c480fe008e h1:NdpVflh7 github.com/Telmate/proxmox-api-go v0.0.0-20240409105641-32c480fe008e/go.mod h1:bscBzOUx0tJAdVGmQvcnoWPg5eI2eJ6anJKV1ueZ1oU= github.com/Telmate/proxmox-api-go v0.0.0-20240525163725-6676d8933df0 h1:VK35Q0s1IayA2Nwm0uREu+LVs0WWPq9Zsn3Oic1q5eg= github.com/Telmate/proxmox-api-go v0.0.0-20240525163725-6676d8933df0/go.mod h1:bscBzOUx0tJAdVGmQvcnoWPg5eI2eJ6anJKV1ueZ1oU= +github.com/Telmate/proxmox-api-go v0.0.0-20241022204517-b149708f750b h1:vgK9CbUZpd37RYab6lCEQTyP0fw/Ygq5NOWctBI5rpA= +github.com/Telmate/proxmox-api-go v0.0.0-20241022204517-b149708f750b/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/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=