From c261428c4f7146247f8fc533f08507dfd90a1136 Mon Sep 17 00:00:00 2001 From: Peter Pribula Date: Thu, 25 Apr 2019 11:43:12 +0200 Subject: [PATCH 1/5] ProxMox builder ssh communicator uses ssh_host from builder config when present --- builder/proxmox/builder.go | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/builder/proxmox/builder.go b/builder/proxmox/builder.go index 59e271380..3e073a35e 100644 --- a/builder/proxmox/builder.go +++ b/builder/proxmox/builder.go @@ -71,7 +71,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack }, &communicator.StepConnect{ Config: &b.config.Comm, - Host: getVMIP, + Host: commHost(b.config.Comm.SSHHost), SSHConfig: b.config.Comm.SSHConfigFunc(), }, &common.StepProvision{}, @@ -98,6 +98,18 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack return artifact, nil } +// Returns ssh_host config parameter when set, otherwise gets the host IP from running VM +func commHost(sshHost string) func(state multistep.StateBag) (string, error) { + if sshHost != "" { + return func(state multistep.StateBag) (string, error) { + return sshHost, nil + } + } + return getVMIP +} + +// Reads the first non-loopback interface's IP address from the VM. +// qemu-guest-agent package must be installed on the VM func getVMIP(state multistep.StateBag) (string, error) { c := state.Get("proxmoxClient").(*proxmox.Client) vmRef := state.Get("vmRef").(*proxmox.VmRef) From cb7b77cd9078d8e917462a4051680d3cf91ac9c8 Mon Sep 17 00:00:00 2001 From: Peter Pribula Date: Thu, 25 Apr 2019 19:25:00 +0200 Subject: [PATCH 2/5] Adds `qemu_agent` optional config parameter --- builder/proxmox/config.go | 6 ++++++ builder/proxmox/config_test.go | 4 ++++ builder/proxmox/step_start_vm.go | 2 +- website/source/docs/builders/proxmox.html.md | 4 ++++ 4 files changed, 15 insertions(+), 1 deletion(-) diff --git a/builder/proxmox/config.go b/builder/proxmox/config.go index 8b60c509f..acdc1636b 100644 --- a/builder/proxmox/config.go +++ b/builder/proxmox/config.go @@ -43,6 +43,7 @@ type Config struct { NICs []nicConfig `mapstructure:"network_adapters"` Disks []diskConfig `mapstructure:"disks"` ISOFile string `mapstructure:"iso_file"` + Agent string `mapstructure:"qemu_agent"` TemplateName string `mapstructure:"template_name"` TemplateDescription string `mapstructure:"template_description"` @@ -149,6 +150,11 @@ func NewConfig(raws ...interface{}) (*Config, []string, error) { c.Disks[idx].CacheMode = "none" } } + // Valid values: 0 - no agent, 1 - with agent; default is 1 + if c.Agent != "0" && c.Agent != "1" { + log.Printf("Agent '%s' is not valid, using default: 1", c.Agent) + c.Agent = "1" + } errs = packer.MultiErrorAppend(errs, c.Comm.Prepare(&c.ctx)...) errs = packer.MultiErrorAppend(errs, c.BootConfig.Prepare(&c.ctx)...) diff --git a/builder/proxmox/config_test.go b/builder/proxmox/config_test.go index e04f4a0d5..5f09588e4 100644 --- a/builder/proxmox/config_test.go +++ b/builder/proxmox/config_test.go @@ -93,6 +93,7 @@ func TestBasicExampleFromDocsIsValid(t *testing.T) { // OS not set, using default 'other' // NIC 0 model not set, using default 'e1000' // Disk 0 cache mode not set, using default 'none' + // Agent not set, default is 1 if b.config.Memory != 512 { t.Errorf("Expected Memory to be 512, got %d", b.config.Memory) @@ -112,4 +113,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.Agent != "1" { + t.Errorf("Expected Agent to be 1, got %s", b.config.Agent) + } } diff --git a/builder/proxmox/step_start_vm.go b/builder/proxmox/step_start_vm.go index 779394023..e47525e24 100644 --- a/builder/proxmox/step_start_vm.go +++ b/builder/proxmox/step_start_vm.go @@ -24,7 +24,7 @@ func (s *stepStartVM) Run(ctx context.Context, state multistep.StateBag) multist ui.Say("Creating VM") config := proxmox.ConfigQemu{ Name: c.VMName, - Agent: "1", + Agent: c.Agent, Description: "Packer ephemeral build VM", Memory: c.Memory, QemuCores: c.Cores, diff --git a/website/source/docs/builders/proxmox.html.md b/website/source/docs/builders/proxmox.html.md index 2345c1911..cb133f76d 100644 --- a/website/source/docs/builders/proxmox.html.md +++ b/website/source/docs/builders/proxmox.html.md @@ -146,6 +146,10 @@ builder. - `unmount_iso` (bool) - If true, remove the mounted ISO from the template after finishing. Defaults to `false`. +- `qemu_agent` (string) - Enables (`1`) or disables (`0`) the QEMU Agent option + for this VM. When disabled, then Packer can't determine the guest's IP, + and `ssh_host` should be used. When enabled, then `qemu-guest-agent` + must be installed on the guest OS. Defaults to `1`. ## Example: Fedora with kickstart From 02b6e7f3de97d12371dcbd776d8a345789fa95fa Mon Sep 17 00:00:00 2001 From: Peter Pribula Date: Tue, 30 Apr 2019 20:23:34 +0200 Subject: [PATCH 3/5] Changes `qemu_agent` config frm string to bool Defaults to true --- builder/proxmox/config.go | 9 ++--- builder/proxmox/config_test.go | 39 ++++++++++++++++++-- builder/proxmox/step_start_vm.go | 7 +++- website/source/docs/builders/proxmox.html.md | 7 ++-- 4 files changed, 48 insertions(+), 14 deletions(-) diff --git a/builder/proxmox/config.go b/builder/proxmox/config.go index acdc1636b..a45ad5a9c 100644 --- a/builder/proxmox/config.go +++ b/builder/proxmox/config.go @@ -43,7 +43,7 @@ type Config struct { NICs []nicConfig `mapstructure:"network_adapters"` Disks []diskConfig `mapstructure:"disks"` ISOFile string `mapstructure:"iso_file"` - Agent string `mapstructure:"qemu_agent"` + Agent bool `mapstructure:"qemu_agent"` TemplateName string `mapstructure:"template_name"` TemplateDescription string `mapstructure:"template_description"` @@ -69,6 +69,8 @@ type diskConfig struct { func NewConfig(raws ...interface{}) (*Config, []string, error) { c := new(Config) + // Agent defaults to true + c.Agent = true var md mapstructure.Metadata err := config.Decode(c, &config.DecodeOpts{ @@ -150,11 +152,6 @@ func NewConfig(raws ...interface{}) (*Config, []string, error) { c.Disks[idx].CacheMode = "none" } } - // Valid values: 0 - no agent, 1 - with agent; default is 1 - if c.Agent != "0" && c.Agent != "1" { - log.Printf("Agent '%s' is not valid, using default: 1", c.Agent) - c.Agent = "1" - } errs = packer.MultiErrorAppend(errs, c.Comm.Prepare(&c.ctx)...) errs = packer.MultiErrorAppend(errs, c.BootConfig.Prepare(&c.ctx)...) diff --git a/builder/proxmox/config_test.go b/builder/proxmox/config_test.go index 5f09588e4..fa8b81524 100644 --- a/builder/proxmox/config_test.go +++ b/builder/proxmox/config_test.go @@ -93,7 +93,7 @@ func TestBasicExampleFromDocsIsValid(t *testing.T) { // OS not set, using default 'other' // NIC 0 model not set, using default 'e1000' // Disk 0 cache mode not set, using default 'none' - // Agent not set, default is 1 + // Agent not set, default is true if b.config.Memory != 512 { t.Errorf("Expected Memory to be 512, got %d", b.config.Memory) @@ -113,7 +113,40 @@ 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 != "1" { - t.Errorf("Expected Agent to be 1, got %s", b.config.Agent) + if b.config.Agent != true { + t.Errorf("Expected Agent to be true, got %t", b.config.Agent) + } +} + +func TestAgentSetToFalse(t *testing.T) { + // pnly the mandatory attributes are specified + const config = `{ + "builders": [ + { + "type": "proxmox", + "proxmox_url": "https://my-proxmox.my-domain:8006/api2/json", + "username": "apiuser@pve", + "password": "supersecret", + "iso_file": "local:iso/Fedora-Server-dvd-x86_64-29-1.2.iso", + "ssh_username": "root", + "node": "my-proxmox", + "qemu_agent": false + } + ] + }` + + tpl, err := template.Parse(strings.NewReader(config)) + if err != nil { + t.Fatal(err) + } + + b := &Builder{} + warn, err := b.Prepare(tpl.Builders["proxmox"].Config) + if err != nil { + t.Fatal(err, warn) + } + + if b.config.Agent != false { + t.Errorf("Expected Agent to be false, got %t", b.config.Agent) } } diff --git a/builder/proxmox/step_start_vm.go b/builder/proxmox/step_start_vm.go index e47525e24..a7521b14b 100644 --- a/builder/proxmox/step_start_vm.go +++ b/builder/proxmox/step_start_vm.go @@ -21,10 +21,15 @@ func (s *stepStartVM) Run(ctx context.Context, state multistep.StateBag) multist client := state.Get("proxmoxClient").(*proxmox.Client) c := state.Get("config").(*Config) + agent := "1" + if c.Agent == false { + agent = "0" + } + ui.Say("Creating VM") config := proxmox.ConfigQemu{ Name: c.VMName, - Agent: c.Agent, + Agent: agent, Description: "Packer ephemeral build VM", Memory: c.Memory, QemuCores: c.Cores, diff --git a/website/source/docs/builders/proxmox.html.md b/website/source/docs/builders/proxmox.html.md index cb133f76d..472509cdd 100644 --- a/website/source/docs/builders/proxmox.html.md +++ b/website/source/docs/builders/proxmox.html.md @@ -146,10 +146,9 @@ builder. - `unmount_iso` (bool) - If true, remove the mounted ISO from the template after finishing. Defaults to `false`. -- `qemu_agent` (string) - Enables (`1`) or disables (`0`) the QEMU Agent option - for this VM. When disabled, then Packer can't determine the guest's IP, - and `ssh_host` should be used. When enabled, then `qemu-guest-agent` - must be installed on the guest OS. Defaults to `1`. +- `qemu_agent` (boolean) - Disables 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`. ## Example: Fedora with kickstart From 778dda9fe0f3a81d783584a9b565baa261dc39aa Mon Sep 17 00:00:00 2001 From: Peter Pribula Date: Tue, 30 Apr 2019 22:26:40 +0200 Subject: [PATCH 4/5] Takes static WinRM config into consideration --- builder/proxmox/builder.go | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/builder/proxmox/builder.go b/builder/proxmox/builder.go index 3e073a35e..b919e4c43 100644 --- a/builder/proxmox/builder.go +++ b/builder/proxmox/builder.go @@ -71,7 +71,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack }, &communicator.StepConnect{ Config: &b.config.Comm, - Host: commHost(b.config.Comm.SSHHost), + Host: commHost(b.config.Comm.Host()), SSHConfig: b.config.Comm.SSHConfigFunc(), }, &common.StepProvision{}, @@ -98,11 +98,12 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack return artifact, nil } -// Returns ssh_host config parameter when set, otherwise gets the host IP from running VM -func commHost(sshHost string) func(state multistep.StateBag) (string, error) { - if sshHost != "" { +// Returns ssh_host or winrm_host (see communicator.Config.Host) config +// parameter when set, otherwise gets the host IP from running VM +func commHost(host string) func(state multistep.StateBag) (string, error) { + if host != "" { return func(state multistep.StateBag) (string, error) { - return sshHost, nil + return host, nil } } return getVMIP From 14f96e895132a0f1fa81ec9c1df509a041fc5314 Mon Sep 17 00:00:00 2001 From: Peter Pribula Date: Wed, 1 May 2019 08:39:48 +0200 Subject: [PATCH 5/5] Fixes a typo in a comment --- builder/proxmox/config_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/builder/proxmox/config_test.go b/builder/proxmox/config_test.go index fa8b81524..ec654dc54 100644 --- a/builder/proxmox/config_test.go +++ b/builder/proxmox/config_test.go @@ -119,7 +119,7 @@ func TestBasicExampleFromDocsIsValid(t *testing.T) { } func TestAgentSetToFalse(t *testing.T) { - // pnly the mandatory attributes are specified + // only the mandatory attributes are specified const config = `{ "builders": [ {