lib/vagrant/ssh.rb in vagrant-0.7.0.beta vs lib/vagrant/ssh.rb in vagrant-0.7.0.beta2

- old
+ new

@@ -1,10 +1,12 @@ require 'timeout' require 'net/ssh' require 'net/scp' require 'mario' +require 'vagrant/ssh/session' + module Vagrant # Manages SSH access to a specific environment. Allows an environment to # replace the process with SSH itself, run a specific set of commands, # upload files, or even check if a host is up. class SSH @@ -40,10 +42,11 @@ # Command line options command_options = ["-p #{options[:port]}", "-o UserKnownHostsFile=/dev/null", "-o StrictHostKeyChecking=no", "-o IdentitiesOnly=yes", "-i #{options[:private_key_path]}"] command_options << "-o ForwardAgent=yes" if env.config.ssh.forward_agent + command_options << "-o ForwardX11=yes" if env.config.ssh.forward_x11 # Some hackery going on here. On Mac OS X Leopard (10.5), exec fails # (GH-51). As a workaround, we fork and wait. On all other platforms, # we simply exec. pid = nil @@ -158,80 +161,8 @@ return pnum.hostport if pnum # Fall back to the default return env.config.ssh.port - end - end - - class SSH - # A helper class which wraps around `Net::SSH::Connection::Session` - # in order to provide basic command error checking while still - # providing access to the actual session object. - class Session - include Util::Retryable - - attr_reader :session - - def initialize(session) - @session = session - end - - # Executes a given command on the SSH session and blocks until - # the command completes. This is an almost line for line copy of - # the actual `exec!` implementation, except that this - # implementation also reports `:exit_status` to the block if given. - def exec!(command, options=nil, &block) - options = { - :error_check => true - }.merge(options || {}) - - block ||= Proc.new do |ch, type, data| - check_exit_status(data, command, options) if type == :exit_status && options[:error_check] - - ch[:result] ||= "" - ch[:result] << data if [:stdout, :stderr].include?(type) - end - - retryable(:tries => 5, :on => IOError, :sleep => 0.5) do - metach = session.open_channel do |channel| - channel.exec(command) do |ch, success| - raise "could not execute command: #{command.inspect}" unless success - - # Output stdout data to the block - channel.on_data do |ch2, data| - block.call(ch2, :stdout, data) - end - - # Output stderr data to the block - channel.on_extended_data do |ch2, type, data| - block.call(ch2, :stderr, data) - end - - # Output exit status information to the block - channel.on_request("exit-status") do |ch2, data| - block.call(ch2, :exit_status, data.read_long) - end - end - end - - metach.wait - metach[:result] - end - end - - # Checks for an erroroneous exit status and raises an exception - # if so. - def check_exit_status(exit_status, command, options=nil) - if exit_status != 0 - options = { - :_error_class => Errors::VagrantError, - :_key => :ssh_bad_exit_status, - :command => command - }.merge(options || {}) - - raise options[:_error_class], options - end - end end end end