Merge pull request #4709 from hashicorp/sshdeadline

set deadline in ssh connection
This commit is contained in:
Matthew Hooker 2018-01-31 12:36:10 -08:00 committed by GitHub
commit 2ecefbbf35
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 43 additions and 0 deletions

View File

@ -59,6 +59,9 @@ type Config struct {
// KeepAliveInterval sets how often we send a channel request to the // KeepAliveInterval sets how often we send a channel request to the
// server. A value < 0 disables. // server. A value < 0 disables.
KeepAliveInterval time.Duration KeepAliveInterval time.Duration
// Timeout is how long to wait for a read or write to succeed.
Timeout time.Duration
} }
// Creates a new packer.Communicator implementation over SSH. This takes // Creates a new packer.Communicator implementation over SSH. This takes
@ -291,6 +294,10 @@ func (c *comm) reconnect() (err error) {
return return
} }
if c.config.Timeout > 0 {
c.conn = &timeoutConn{c.conn, c.config.Timeout, c.config.Timeout}
}
log.Printf("handshaking with SSH") log.Printf("handshaking with SSH")
// Default timeout to 1 minute if it wasn't specified (zero value). For // Default timeout to 1 minute if it wasn't specified (zero value). For

View File

@ -0,0 +1,30 @@
package ssh
import (
"net"
"time"
)
// timeoutConn wraps a net.Conn, and sets a deadline for every read
// and write operation.
type timeoutConn struct {
net.Conn
ReadTimeout time.Duration
WriteTimeout time.Duration
}
func (c *timeoutConn) Read(b []byte) (int, error) {
err := c.Conn.SetReadDeadline(time.Now().Add(c.ReadTimeout))
if err != nil {
return 0, err
}
return c.Conn.Read(b)
}
func (c *timeoutConn) Write(b []byte) (int, error) {
err := c.Conn.SetWriteDeadline(time.Now().Add(c.WriteTimeout))
if err != nil {
return 0, err
}
return c.Conn.Write(b)
}

View File

@ -38,6 +38,7 @@ type Config struct {
SSHProxyUsername string `mapstructure:"ssh_proxy_username"` SSHProxyUsername string `mapstructure:"ssh_proxy_username"`
SSHProxyPassword string `mapstructure:"ssh_proxy_password"` SSHProxyPassword string `mapstructure:"ssh_proxy_password"`
SSHKeepAliveInterval time.Duration `mapstructure:"ssh_keep_alive_interval"` SSHKeepAliveInterval time.Duration `mapstructure:"ssh_keep_alive_interval"`
SSHReadWriteTimeout time.Duration `mapstructure:"ssh_read_write_timeout"`
// WinRM // WinRM
WinRMUser string `mapstructure:"winrm_username"` WinRMUser string `mapstructure:"winrm_username"`

View File

@ -183,6 +183,7 @@ func (s *StepConnectSSH) waitForSSH(state multistep.StateBag, cancel <-chan stru
DisableAgentForwarding: s.Config.SSHDisableAgentForwarding, DisableAgentForwarding: s.Config.SSHDisableAgentForwarding,
UseSftp: s.Config.SSHFileTransferMethod == "sftp", UseSftp: s.Config.SSHFileTransferMethod == "sftp",
KeepAliveInterval: s.Config.SSHKeepAliveInterval, KeepAliveInterval: s.Config.SSHKeepAliveInterval,
Timeout: s.Config.SSHReadWriteTimeout,
} }
log.Println("[INFO] Attempting SSH connection...") log.Println("[INFO] Attempting SSH connection...")

View File

@ -106,6 +106,10 @@ The SSH communicator has the following options:
- `ssh_pty` (boolean) - If true, a PTY will be requested for the SSH - `ssh_pty` (boolean) - If true, a PTY will be requested for the SSH
connection. This defaults to false. connection. This defaults to false.
* `ssh_read_write_timeout` (string) - The amount of time to wait for a remote
command to end. This might be useful if, for example, packer hangs on
a connection after a reboot. Example: "5m". Disabled by default.
- `ssh_timeout` (string) - The time to wait for SSH to become available. - `ssh_timeout` (string) - The time to wait for SSH to become available.
Packer uses this to determine when the machine has booted so this is Packer uses this to determine when the machine has booted so this is
usually quite long. Example value: "10m" usually quite long. Example value: "10m"