diff --git a/builder/openstack/builder.go b/builder/openstack/builder.go index 2e7f00e7f..1d444cc84 100644 --- a/builder/openstack/builder.go +++ b/builder/openstack/builder.go @@ -108,7 +108,8 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe computeClient, b.config.SSHInterface, b.config.SSHIPVersion), - SSHConfig: SSHConfig(b.config.RunConfig.Comm.SSHUsername), + SSHConfig: SSHConfig(b.config.RunConfig.Comm.SSHUsername, + b.config.RunConfig.Comm.SSHPassword), }, &common.StepProvision{}, &StepStopServer{}, diff --git a/builder/openstack/ssh.go b/builder/openstack/ssh.go index f7fb2d5a9..99f8e6669 100644 --- a/builder/openstack/ssh.go +++ b/builder/openstack/ssh.go @@ -7,6 +7,7 @@ import ( "time" "github.com/mitchellh/multistep" + packerssh "github.com/mitchellh/packer/communicator/ssh" "github.com/rackspace/gophercloud" "github.com/rackspace/gophercloud/openstack/compute/v2/extensions/floatingip" "github.com/rackspace/gophercloud/openstack/compute/v2/servers" @@ -60,23 +61,37 @@ func CommHost( } // SSHConfig returns a function that can be used for the SSH communicator -// config for connecting to the instance created over SSH using the generated -// private key. -func SSHConfig(username string) func(multistep.StateBag) (*ssh.ClientConfig, error) { +// config for connecting to the instance created over SSH using a private key +// or a password. +func SSHConfig(username, password string) func(multistep.StateBag) (*ssh.ClientConfig, error) { return func(state multistep.StateBag) (*ssh.ClientConfig, error) { - privateKey := state.Get("privateKey").(string) - signer, err := ssh.ParsePrivateKey([]byte(privateKey)) - if err != nil { - return nil, fmt.Errorf("Error setting up SSH config: %s", err) + privateKey, hasKey := state.GetOk("privateKey") + + if hasKey { + + signer, err := ssh.ParsePrivateKey([]byte(privateKey.(string))) + if err != nil { + return nil, fmt.Errorf("Error setting up SSH config: %s", err) + } + + return &ssh.ClientConfig{ + User: username, + Auth: []ssh.AuthMethod{ + ssh.PublicKeys(signer), + }, + }, nil + + } else { + + return &ssh.ClientConfig{ + User: username, + Auth: []ssh.AuthMethod{ + ssh.Password(password), + ssh.KeyboardInteractive( + packerssh.PasswordKeyboardInteractive(password)), + }}, nil } - - return &ssh.ClientConfig{ - User: username, - Auth: []ssh.AuthMethod{ - ssh.PublicKeys(signer), - }, - }, nil } } diff --git a/builder/openstack/step_key_pair.go b/builder/openstack/step_key_pair.go index 2fcb8bc51..906f11cee 100644 --- a/builder/openstack/step_key_pair.go +++ b/builder/openstack/step_key_pair.go @@ -42,6 +42,11 @@ func (s *StepKeyPair) Run(state multistep.StateBag) multistep.StepAction { config := state.Get("config").(Config) ui := state.Get("ui").(packer.Ui) + if config.Comm.Type == "ssh" && config.Comm.SSHPassword != "" { + ui.Say("Not creating temporary keypair when using password.") + return multistep.ActionContinue + } + // We need the v2 compute client computeClient, err := config.computeV2Client() if err != nil { diff --git a/builder/openstack/step_run_source_server.go b/builder/openstack/step_run_source_server.go index c0fabb212..afe3af8ff 100644 --- a/builder/openstack/step_run_source_server.go +++ b/builder/openstack/step_run_source_server.go @@ -27,7 +27,6 @@ type StepRunSourceServer struct { func (s *StepRunSourceServer) Run(state multistep.StateBag) multistep.StepAction { config := state.Get("config").(Config) flavor := state.Get("flavor_id").(string) - keyName := state.Get("keyPair").(string) ui := state.Get("ui").(packer.Ui) // We need the v2 compute client @@ -54,21 +53,31 @@ func (s *StepRunSourceServer) Run(state multistep.StateBag) multistep.StepAction } ui.Say("Launching server...") - s.server, err = servers.Create(computeClient, keypairs.CreateOptsExt{ - CreateOptsBuilder: servers.CreateOpts{ - Name: s.Name, - ImageRef: s.SourceImage, - ImageName: s.SourceImageName, - FlavorRef: flavor, - SecurityGroups: s.SecurityGroups, - Networks: networks, - AvailabilityZone: s.AvailabilityZone, - UserData: userData, - ConfigDrive: s.ConfigDrive, - }, - KeyName: keyName, - }).Extract() + serverOpts := servers.CreateOpts{ + Name: s.Name, + ImageRef: s.SourceImage, + ImageName: s.SourceImageName, + FlavorRef: flavor, + SecurityGroups: s.SecurityGroups, + Networks: networks, + AvailabilityZone: s.AvailabilityZone, + UserData: userData, + ConfigDrive: s.ConfigDrive, + } + + var serverOptsExt servers.CreateOptsBuilder + keyName, hasKey := state.GetOk("keyPair") + if hasKey { + serverOptsExt = keypairs.CreateOptsExt{ + CreateOptsBuilder: serverOpts, + KeyName: keyName.(string), + } + } else { + serverOptsExt = serverOpts + } + + s.server, err = servers.Create(computeClient, serverOptsExt).Extract() if err != nil { err := fmt.Errorf("Error launching source server: %s", err) state.Put("error", err)