diff --git a/builder/digitalocean/step_connect_ssh.go b/builder/digitalocean/step_connect_ssh.go index d764a35d3..c6fcf7db6 100644 --- a/builder/digitalocean/step_connect_ssh.go +++ b/builder/digitalocean/step_connect_ssh.go @@ -42,17 +42,19 @@ func (s *stepConnectSSH) Run(state map[string]interface{}) multistep.StepAction } // Start trying to connect to SSH - connected := make(chan bool, 1) + connected := make(chan error, 1) connectQuit := make(chan bool, 1) defer func() { connectQuit <- true }() + var comm packer.Communicator go func() { var err error ui.Say("Connecting to the droplet via SSH...") attempts := 0 + handshakeAttempts := 0 for { select { case <-connectQuit: @@ -69,7 +71,20 @@ func (s *stepConnectSSH) Run(state map[string]interface{}) multistep.StepAction fmt.Sprintf("%s:%d", ipAddress, config.SSHPort), 10*time.Second) if err == nil { - break + log.Println("TCP connection made. Attempting SSH handshake.") + comm, err = ssh.New(s.conn, sshConfig) + if err == nil { + log.Println("Connected to SSH!") + break + } + + handshakeAttempts += 1 + log.Printf("SSH handshake error: %s", err) + + if handshakeAttempts > 5 { + connected <- err + return + } } // A brief sleep so we're not being overly zealous attempting @@ -77,7 +92,7 @@ func (s *stepConnectSSH) Run(state map[string]interface{}) multistep.StepAction time.Sleep(500 * time.Millisecond) } - connected <- true + connected <- nil }() log.Printf("Waiting up to %s for SSH connection", config.SSHTimeout) @@ -86,7 +101,14 @@ func (s *stepConnectSSH) Run(state map[string]interface{}) multistep.StepAction ConnectWaitLoop: for { select { - case <-connected: + case err := <-connected: + if err != nil { + err := fmt.Errorf("Error connecting to SSH: %s", err) + state["error"] = err + ui.Error(err.Error()) + return multistep.ActionHalt + } + // We connected. Just break the loop. break ConnectWaitLoop case <-timeout: @@ -102,18 +124,6 @@ ConnectWaitLoop: } } - var comm packer.Communicator - if err == nil { - comm, err = ssh.New(s.conn, sshConfig) - } - - if err != nil { - err := fmt.Errorf("Error connecting to SSH: %s", err) - state["error"] = err - ui.Error(err.Error()) - return multistep.ActionHalt - } - // Set the communicator on the state bag so it can be used later state["communicator"] = comm