lib/chef/provisioning/transport/ssh.rb in chef-provisioning-1.5.1 vs lib/chef/provisioning/transport/ssh.rb in chef-provisioning-1.6.0
- old
+ new
@@ -40,25 +40,39 @@
@host = host
@username = username
@ssh_options = ssh_options
@options = options
@config = global_config
+ @remote_forwards = ssh_options.delete(:remote_forwards) { Array.new }
end
attr_reader :host
attr_reader :username
attr_reader :ssh_options
attr_reader :options
attr_reader :config
def execute(command, execute_options = {})
- Chef::Log.info("Executing #{options[:prefix]}#{command} on #{username}@#{host}")
+ Chef::Log.info("#{self.object_id} Executing #{options[:prefix]}#{command} on #{username}@#{host}")
stdout = ''
stderr = ''
exitstatus = nil
session # grab session outside timeout, it has its own timeout
+
with_execute_timeout(execute_options) do
+ @remote_forwards.each do |forward_info|
+ # -R flag to openssh client allows optional :remote_host and
+ # requires the other values so let's do that too.
+ remote_host = forward_info.fetch(:remote_host, 'localhost')
+ remote_port = forward_info.fetch(:remote_port)
+ local_host = forward_info.fetch(:local_host)
+ local_port = forward_info.fetch(:local_port)
+
+ actual_port, actual_host = forward_port(local_port, local_host, remote_port, remote_host)
+ Chef::Log.info("#{host} forwarded remote #{actual_host}:#{actual_port} to local #{local_host}:#{local_port}")
+ end
+
channel = session.open_channel do |channel|
# Enable PTY unless otherwise specified, some instances require this
unless options[:ssh_pty_enable] == false
channel.request_pty do |chan, success|
raise "could not get pty" if !success && options[:ssh_pty_enable]
@@ -83,10 +97,24 @@
end
end
end
channel.wait
+
+ @remote_forwards.each do |forward_info|
+ # -R flag to openssh client allows optional :remote_host and
+ # requires the other values so let's do that too.
+ remote_host = forward_info.fetch(:remote_host, 'localhost')
+ remote_port = forward_info.fetch(:remote_port)
+ local_host = forward_info.fetch(:local_host)
+ local_port = forward_info.fetch(:local_port)
+
+ session.forward.cancel_remote(remote_port, remote_host)
+ session.loop { session.forward.active_remotes.include?([remote_port, remote_host]) }
+
+ Chef::Log.info("#{host} canceled remote forward #{remote_host}:#{remote_port}")
+ end
end
Chef::Log.info("Completed #{command} on #{username}@#{host}: exit status #{exitstatus}")
Chef::Log.debug("Stdout was:\n#{stdout}") if stdout != '' && !options[:stream] && !options[:stream_stdout] && config[:log_level] != :debug
Chef::Log.info("Stderr was:\n#{stderr}") if stderr != '' && !options[:stream] && !options[:stream_stderr] && config[:log_level] != :debug
@@ -154,19 +182,21 @@
raise "Error forwarding port: could not forward #{uri.port} or 0"
end
end
uri.host = host
uri.port = port
+ Chef::Log.info("Port forwarded: local URL #{local_url} is available to #{self.host} as #{uri.to_s} for the duration of this SSH connection.")
+ else
+ Chef::Log.info("#{host} not forwarding non-local #{local_url}")
end
- Chef::Log.info("Port forwarded: local URL #{local_url} is available to #{self.host} as #{uri.to_s} for the duration of this SSH connection.")
uri.to_s
end
def disconnect
if @session
begin
- Chef::Log.debug("Closing SSH session on #{username}@#{host}")
+ Chef::Log.info("Closing SSH session on #{username}@#{host}")
@session.close
rescue
ensure
@session = nil
end
@@ -175,11 +205,11 @@
def available?
timeout = ssh_options[:timeout] || 10
execute('pwd', :timeout => timeout)
true
- rescue Timeout::Error, Errno::EHOSTUNREACH, Errno::ENETUNREACH, Errno::EHOSTDOWN, Errno::ETIMEDOUT, Errno::ECONNREFUSED, Errno::ECONNRESET, Net::SSH::Disconnect
+ rescue Timeout::Error, Errno::EHOSTUNREACH, Errno::ENETUNREACH, Errno::EHOSTDOWN, Errno::ETIMEDOUT, Errno::ECONNREFUSED, Errno::ECONNRESET, Net::SSH::Disconnect, Net::SSH::ConnectionTimeout
Chef::Log.debug("#{username}@#{host} unavailable: network connection failed or broke: #{$!.inspect}")
disconnect
false
rescue Net::SSH::AuthenticationFailed, Net::SSH::HostKeyMismatch
Chef::Log.debug("#{username}@#{host} unavailable: SSH authentication error: #{$!.inspect} ")
@@ -197,11 +227,11 @@
|ssh| ssh.delete(:key_data) }.inspect}")
begin
if gateway? then gateway.ssh(host, username, ssh_start_opts)
else Net::SSH.start(host, username, ssh_start_opts)
end
- rescue Timeout::Error
+ rescue Timeout::Error, Net::SSH::ConnectionTimeout
Chef::Log.debug("Timed out connecting to SSH: #{$!}")
raise InitialConnectTimeout.new($!)
end
end
end
@@ -331,10 +361,10 @@
# session and set up their own remotes, this will prevent us from
# overwriting them.
actual_remote_port, actual_remote_host = session.forward.active_remote_destinations[[local_port, local_host]]
if !actual_remote_port
- Chef::Log.debug("Forwarding local server #{local_host}:#{local_port} to #{username}@#{self.host}")
+ Chef::Log.info("Forwarding local server #{local_host}:#{local_port} to #{username}@#{self.host}")
session.forward.remote(local_port, local_host, remote_port, remote_host) do |new_remote_port, new_remote_host|
actual_remote_host = new_remote_host
actual_remote_port = new_remote_port || :error
:no_exception # I'll take care of it myself, thanks