From 07fffd7cd5f192de0b86221dd0fe8ad34f0b8e23 Mon Sep 17 00:00:00 2001 From: Rickard von Essen Date: Sun, 16 Jul 2017 18:23:59 +0200 Subject: [PATCH 1/4] cloudstack: moved instanceSource to statebag --- builder/cloudstack/config.go | 5 ++--- builder/cloudstack/step_create_instance.go | 3 ++- builder/cloudstack/step_prepare_config.go | 10 ++++++---- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/builder/cloudstack/config.go b/builder/cloudstack/config.go index 5d6e9da0a..68fe778d4 100644 --- a/builder/cloudstack/config.go +++ b/builder/cloudstack/config.go @@ -55,9 +55,8 @@ type Config struct { TemplateScalable bool `mapstructure:"template_scalable"` TemplateTag string `mapstructure:"template_tag"` - ctx interpolate.Context - hostAddress string // The host address used by the communicators. - instanceSource string // This can be either a template ID or an ISO ID. + ctx interpolate.Context + hostAddress string // The host address used by the communicators. } // NewConfig parses and validates the given config. diff --git a/builder/cloudstack/step_create_instance.go b/builder/cloudstack/step_create_instance.go index 3b624de3c..90db2d960 100644 --- a/builder/cloudstack/step_create_instance.go +++ b/builder/cloudstack/step_create_instance.go @@ -30,13 +30,14 @@ func (s *stepCreateInstance) Run(state multistep.StateBag) multistep.StepAction client := state.Get("client").(*cloudstack.CloudStackClient) config := state.Get("config").(*Config) ui := state.Get("ui").(packer.Ui) + source := state.Get("source").(string) ui.Say("Creating instance...") // Create a new parameter struct. p := client.VirtualMachine.NewDeployVirtualMachineParams( config.ServiceOffering, - config.instanceSource, + source, config.Zone, ) diff --git a/builder/cloudstack/step_prepare_config.go b/builder/cloudstack/step_prepare_config.go index de397308e..8fafc809e 100644 --- a/builder/cloudstack/step_prepare_config.go +++ b/builder/cloudstack/step_prepare_config.go @@ -101,23 +101,25 @@ func (s *stepPrepareConfig) Run(state multistep.StateBag) multistep.StepAction { if config.SourceISO != "" { if isUUID(config.SourceISO) { - config.instanceSource = config.SourceISO + state.Put("source", config.SourceISO) } else { - config.instanceSource, _, err = client.ISO.GetIsoID(config.SourceISO, "executable", config.Zone) + isoID, _, err := client.ISO.GetIsoID(config.SourceISO, "executable", config.Zone) if err != nil { errs = packer.MultiErrorAppend(errs, &retrieveErr{"ISO", config.SourceISO, err}) } + state.Put("source", isoID) } } if config.SourceTemplate != "" { if isUUID(config.SourceTemplate) { - config.instanceSource = config.SourceTemplate + state.Put("source", config.SourceTemplate) } else { - config.instanceSource, _, err = client.Template.GetTemplateID(config.SourceTemplate, "executable", config.Zone) + templateID, _, err := client.Template.GetTemplateID(config.SourceTemplate, "executable", config.Zone) if err != nil { errs = packer.MultiErrorAppend(errs, &retrieveErr{"template", config.SourceTemplate, err}) } + state.Put("source", templateID) } } From 1bf8a0c6a146481500acf939425d53a505952baf Mon Sep 17 00:00:00 2001 From: Rickard von Essen Date: Mon, 17 Jul 2017 09:05:12 +0200 Subject: [PATCH 2/4] cloudstack: Move ipaddress and host port to state --- builder/cloudstack/builder.go | 4 +++- builder/cloudstack/config.go | 3 +-- builder/cloudstack/ssh.go | 24 ++++++++++--------- .../cloudstack/step_configure_networking.go | 12 +++------- builder/cloudstack/step_create_instance.go | 2 +- builder/cloudstack/step_prepare_config.go | 2 +- 6 files changed, 22 insertions(+), 25 deletions(-) diff --git a/builder/cloudstack/builder.go b/builder/cloudstack/builder.go index 369fe0cc6..51254983a 100644 --- a/builder/cloudstack/builder.go +++ b/builder/cloudstack/builder.go @@ -68,10 +68,12 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe &communicator.StepConnect{ Config: &b.config.Comm, Host: commHost, - SSHConfig: SSHConfig( + SSHConfig: sshConfig( b.config.Comm.SSHAgentAuth, b.config.Comm.SSHUsername, b.config.Comm.SSHPassword), + SSHPort: commPort, + WinRMPort: commPort, }, &common.StepProvision{}, &stepShutdownInstance{}, diff --git a/builder/cloudstack/config.go b/builder/cloudstack/config.go index 68fe778d4..c91b65b04 100644 --- a/builder/cloudstack/config.go +++ b/builder/cloudstack/config.go @@ -55,8 +55,7 @@ type Config struct { TemplateScalable bool `mapstructure:"template_scalable"` TemplateTag string `mapstructure:"template_tag"` - ctx interpolate.Context - hostAddress string // The host address used by the communicators. + ctx interpolate.Context } // NewConfig parses and validates the given config. diff --git a/builder/cloudstack/ssh.go b/builder/cloudstack/ssh.go index ab350d053..725961504 100644 --- a/builder/cloudstack/ssh.go +++ b/builder/cloudstack/ssh.go @@ -7,28 +7,30 @@ import ( packerssh "github.com/hashicorp/packer/communicator/ssh" "github.com/mitchellh/multistep" - "github.com/xanzy/go-cloudstack/cloudstack" "golang.org/x/crypto/ssh" "golang.org/x/crypto/ssh/agent" ) func commHost(state multistep.StateBag) (string, error) { - client := state.Get("client").(*cloudstack.CloudStackClient) - config := state.Get("config").(*Config) - if config.hostAddress == "" { - ipAddr, _, err := client.Address.GetPublicIpAddressByID(config.PublicIPAddress) - if err != nil { - return "", fmt.Errorf("Failed to retrieve IP address: %s", err) - } + ip, hasIp := state.Get("ipaddress").(string) + if !hasIp { + return "", fmt.Errorf("Failed to retrieve IP address") + } + + return ip, nil +} - config.hostAddress = ipAddr.Ipaddress +func commPort(state multistep.StateBag) (int, error) { + commPort, hasPort := state.Get("commPort").(int) + if !hasPort { + return 0, fmt.Errorf("Failed to retrieve communication port") } - return config.hostAddress, nil + return commPort, nil } -func SSHConfig(useAgent bool, username, password string) func(state multistep.StateBag) (*ssh.ClientConfig, error) { +func sshConfig(useAgent bool, username, password string) func(state multistep.StateBag) (*ssh.ClientConfig, error) { return func(state multistep.StateBag) (*ssh.ClientConfig, error) { if useAgent { authSock := os.Getenv("SSH_AUTH_SOCK") diff --git a/builder/cloudstack/step_configure_networking.go b/builder/cloudstack/step_configure_networking.go index 48a3742ab..d9a6a365c 100644 --- a/builder/cloudstack/step_configure_networking.go +++ b/builder/cloudstack/step_configure_networking.go @@ -25,6 +25,7 @@ func (s *stepSetupNetworking) Run(state multistep.StateBag) multistep.StepAction if config.UseLocalIPAddress { ui.Message("Using the local IP address...") + state.Put("commPort", config.Comm.Port()) ui.Message("Networking has been setup!") return multistep.ActionContinue } @@ -32,18 +33,11 @@ func (s *stepSetupNetworking) Run(state multistep.StateBag) multistep.StepAction // Generate a random public port used to configure our port forward. rand.Seed(time.Now().UnixNano()) s.publicPort = 50000 + rand.Intn(10000) + state.Put("commPort", s.publicPort) // Set the currently configured port to be the private port. s.privatePort = config.Comm.Port() - // Set the SSH or WinRM port to be the randomly generated public port. - switch config.Comm.Type { - case "ssh": - config.Comm.SSHPort = s.publicPort - case "winrm": - config.Comm.WinRMPort = s.publicPort - } - // Retrieve the instance ID from the previously saved state. instanceID, ok := state.Get("instance_id").(string) if !ok || instanceID == "" { @@ -91,7 +85,7 @@ func (s *stepSetupNetworking) Run(state multistep.StateBag) multistep.StepAction // Set the IP address and it's ID. config.PublicIPAddress = ipAddr.Id - config.hostAddress = ipAddr.Ipaddress + state.Put("ipaddress", ipAddr.Ipaddress) // Store the IP address ID. state.Put("ip_address_id", ipAddr.Id) diff --git a/builder/cloudstack/step_create_instance.go b/builder/cloudstack/step_create_instance.go index 90db2d960..aa032eecb 100644 --- a/builder/cloudstack/step_create_instance.go +++ b/builder/cloudstack/step_create_instance.go @@ -130,7 +130,7 @@ func (s *stepCreateInstance) Run(state multistep.StateBag) multistep.StepAction // Set the host address when using the local IP address to connect. if config.UseLocalIPAddress { - config.hostAddress = instance.Nic[0].Ipaddress + state.Put("ipaddress", instance.Nic[0].Ipaddress) } // Store the instance ID so we can remove it later. diff --git a/builder/cloudstack/step_prepare_config.go b/builder/cloudstack/step_prepare_config.go index 8fafc809e..45b6068f8 100644 --- a/builder/cloudstack/step_prepare_config.go +++ b/builder/cloudstack/step_prepare_config.go @@ -64,7 +64,7 @@ func (s *stepPrepareConfig) Run(state multistep.StateBag) multistep.StepAction { if config.PublicIPAddress != "" && !isUUID(config.PublicIPAddress) { // Save the public IP address before replacing it with it's UUID. - config.hostAddress = config.PublicIPAddress + state.Put("ipaddress", config.PublicIPAddress) p := client.Address.NewListPublicIpAddressesParams() p.SetIpaddress(config.PublicIPAddress) From 2fea16729460eeccb4f6388da8267d9a7d55fa0f Mon Sep 17 00:00:00 2001 From: Rickard von Essen Date: Wed, 26 Jul 2017 19:01:12 +0200 Subject: [PATCH 3/4] cloudstack: Updated after review --- builder/cloudstack/ssh.go | 5 ++--- builder/cloudstack/step_create_instance.go | 3 +-- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/builder/cloudstack/ssh.go b/builder/cloudstack/ssh.go index 725961504..7a4c2fcba 100644 --- a/builder/cloudstack/ssh.go +++ b/builder/cloudstack/ssh.go @@ -12,9 +12,8 @@ import ( ) func commHost(state multistep.StateBag) (string, error) { - - ip, hasIp := state.Get("ipaddress").(string) - if !hasIp { + ip, hasIP := state.Get("ipaddress").(string) + if !hasIP { return "", fmt.Errorf("Failed to retrieve IP address") } diff --git a/builder/cloudstack/step_create_instance.go b/builder/cloudstack/step_create_instance.go index aa032eecb..064754855 100644 --- a/builder/cloudstack/step_create_instance.go +++ b/builder/cloudstack/step_create_instance.go @@ -30,14 +30,13 @@ func (s *stepCreateInstance) Run(state multistep.StateBag) multistep.StepAction client := state.Get("client").(*cloudstack.CloudStackClient) config := state.Get("config").(*Config) ui := state.Get("ui").(packer.Ui) - source := state.Get("source").(string) ui.Say("Creating instance...") // Create a new parameter struct. p := client.VirtualMachine.NewDeployVirtualMachineParams( config.ServiceOffering, - source, + state.Get("source").(string), config.Zone, ) From 858f1227af5fca4c400ba352626023cb2505b758 Mon Sep 17 00:00:00 2001 From: Rickard von Essen Date: Thu, 27 Jul 2017 21:32:47 +0200 Subject: [PATCH 4/4] cloudstack: Updated after review (2) --- builder/cloudstack/step_prepare_config.go | 42 ++++++++++++++--------- 1 file changed, 25 insertions(+), 17 deletions(-) diff --git a/builder/cloudstack/step_prepare_config.go b/builder/cloudstack/step_prepare_config.go index 45b6068f8..24d342f4d 100644 --- a/builder/cloudstack/step_prepare_config.go +++ b/builder/cloudstack/step_prepare_config.go @@ -62,26 +62,34 @@ func (s *stepPrepareConfig) Run(state multistep.StateBag) multistep.StepAction { } } - if config.PublicIPAddress != "" && !isUUID(config.PublicIPAddress) { - // Save the public IP address before replacing it with it's UUID. - state.Put("ipaddress", config.PublicIPAddress) + if config.PublicIPAddress != "" { + if isUUID(config.PublicIPAddress) { + ip, _, err := client.Address.GetPublicIpAddressByID(config.PublicIPAddress) + if err != nil { + errs = packer.MultiErrorAppend(errs, fmt.Errorf("Failed to retrieve IP address: %s", err)) + } + state.Put("ipaddress", ip.Ipaddress) + } else { + // Save the public IP address before replacing it with it's UUID. + state.Put("ipaddress", config.PublicIPAddress) - p := client.Address.NewListPublicIpAddressesParams() - p.SetIpaddress(config.PublicIPAddress) + p := client.Address.NewListPublicIpAddressesParams() + p.SetIpaddress(config.PublicIPAddress) - if config.Project != "" { - p.SetProjectid(config.Project) - } + if config.Project != "" { + p.SetProjectid(config.Project) + } - ipAddrs, err := client.Address.ListPublicIpAddresses(p) - if err != nil { - errs = packer.MultiErrorAppend(errs, &retrieveErr{"IP address", config.PublicIPAddress, err}) - } - if err == nil && ipAddrs.Count != 1 { - errs = packer.MultiErrorAppend(errs, &retrieveErr{"IP address", config.PublicIPAddress, ipAddrs}) - } - if err == nil && ipAddrs.Count == 1 { - config.PublicIPAddress = ipAddrs.PublicIpAddresses[0].Id + ipAddrs, err := client.Address.ListPublicIpAddresses(p) + if err != nil { + errs = packer.MultiErrorAppend(errs, &retrieveErr{"IP address", config.PublicIPAddress, err}) + } + if err == nil && ipAddrs.Count != 1 { + errs = packer.MultiErrorAppend(errs, &retrieveErr{"IP address", config.PublicIPAddress, ipAddrs}) + } + if err == nil && ipAddrs.Count == 1 { + config.PublicIPAddress = ipAddrs.PublicIpAddresses[0].Id + } } }