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