Class: Vagrant::SSH
- Inherits:
-
Object
- Object
- Vagrant::SSH
- Includes:
- Util::Retryable
- Defined in:
- lib/vagrant/ssh.rb,
lib/vagrant/ssh/session.rb
Overview
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.
Defined Under Namespace
Classes: Session
Instance Attribute Summary collapse
-
#env ⇒ Object
Reference back up to the environment which this SSH object belongs to.
Instance Method Summary collapse
-
#check_key_permissions(key_path) ⇒ Object
Checks the file permissions for the private key, resetting them if needed, or on failure erroring.
-
#connect(opts = {}) ⇒ Object
Connects to the environment's virtual machine, replacing the ruby process with an SSH process.
-
#execute(opts = {}) ⇒ Object
Opens an SSH connection to this environment's virtual machine and yields a Net::SSH object which can be used to execute remote commands.
-
#file_perms(path) ⇒ Object
Returns the file permissions of a given file.
-
#initialize(environment) ⇒ SSH
constructor
A new instance of SSH.
-
#port(opts = {}) ⇒ Object
Returns the port which is either given in the options hash or taken from the config by finding it in the forwarded ports hash based on the
config.ssh.forwarded_port_key
. -
#up? ⇒ Boolean
Checks if this environment's machine is up (i.e. responding to SSH).
-
#upload!(from, to) ⇒ Object
Uploads a file from
from
toto
.
Methods included from Util::Retryable
Constructor Details
#initialize(environment) ⇒ SSH
Returns a new instance of SSH.
19 20 21 |
# File 'lib/vagrant/ssh.rb', line 19 def initialize(environment) @env = environment end |
Instance Attribute Details
#env ⇒ Object
Reference back up to the environment which this SSH object belongs to
17 18 19 |
# File 'lib/vagrant/ssh.rb', line 17 def env @env end |
Instance Method Details
#check_key_permissions(key_path) ⇒ Object
Checks the file permissions for the private key, resetting them if needed, or on failure erroring.
125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 |
# File 'lib/vagrant/ssh.rb', line 125 def (key_path) # Windows systems don't have this issue return if Mario::Platform.windows? stat = File.stat(key_path) if stat.owned? && file_perms(key_path) != "600" File.chmod(0600, key_path) raise Errors::SSHKeyBadPermissions, :key_path => key_path if file_perms(key_path) != "600" end rescue Errno::EPERM # This shouldn't happen since we verify we own the file, but just # in case. raise Errors::SSHKeyBadPermissions, :key_path => key_path end |
#connect(opts = {}) ⇒ Object
Connects to the environment's virtual machine, replacing the ruby process with an SSH process. This method optionally takes a hash of options which override the configuration values.
26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 |
# File 'lib/vagrant/ssh.rb', line 26 def connect(opts={}) if Mario::Platform.windows? raise Errors::SSHUnavailableWindows, :key_path => env.config.ssh.private_key_path, :ssh_port => port(opts) end raise Errors::SSHUnavailable if !Kernel.system("which ssh > /dev/null 2>&1") = {} [:port] = port(opts) [:host, :username, :private_key_path].each do |param| [param] = opts[param] || env.config.ssh.send(param) end ([:private_key_path]) # Command line options = ["-p #{[:port]}", "-o UserKnownHostsFile=/dev/null", "-o StrictHostKeyChecking=no", "-o IdentitiesOnly=yes", "-i #{[:private_key_path]}"] << "-o ForwardAgent=yes" if env.config.ssh.forward_agent if env.config.ssh.forward_x11 # Both are required so that no warnings are shown regarding X11 << "-o ForwardX11=yes" << "-o ForwardX11Trusted=yes" end # 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 pid = fork if Util::Platform.leopard? || Util::Platform.tiger? Kernel.exec "ssh #{.join(" ")} #{[:username]}@#{[:host]}".strip if pid.nil? Process.wait(pid) if pid end |
#execute(opts = {}) ⇒ Object
Opens an SSH connection to this environment's virtual machine and yields a Net::SSH object which can be used to execute remote commands.
65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 |
# File 'lib/vagrant/ssh.rb', line 65 def execute(opts={}) # Check the key permissions to avoid SSH hangs (env.config.ssh.private_key_path) # Merge in any additional options opts = opts.dup opts[:forward_agent] = true if env.config.ssh.forward_agent opts[:port] ||= port retryable(:tries => 5, :on => Errno::ECONNREFUSED) do Net::SSH.start(env.config.ssh.host, env.config.ssh.username, opts.merge( :keys => [env.config.ssh.private_key_path], :keys_only => true, :user_known_hosts_file => [], :paranoid => false, :config => false)) do |ssh| yield SSH::Session.new(ssh, env) end end rescue Errno::ECONNREFUSED raise Errors::SSHConnectionRefused end |
#file_perms(path) ⇒ Object
Returns the file permissions of a given file. This is fairly unix specific and probably doesn't belong in this class. Will be refactored out later.
144 145 146 147 |
# File 'lib/vagrant/ssh.rb', line 144 def file_perms(path) perms = sprintf("%o", File.stat(path).mode) perms.reverse[0..2].reverse end |
#port(opts = {}) ⇒ Object
Returns the port which is either given in the options hash or taken from
the config by finding it in the forwarded ports hash based on the
config.ssh.forwarded_port_key
.
152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 |
# File 'lib/vagrant/ssh.rb', line 152 def port(opts={}) # Check if port was specified in options hash pnum = opts[:port] return pnum if pnum # Check if we have an SSH forwarded port pnum = nil env.vm.vm.network_adapters.each do |na| pnum = na.nat_driver.forwarded_ports.detect do |fp| fp.name == env.config.ssh.forwarded_port_key end break if pnum end return pnum.hostport if pnum # This should NEVER happen. raise Errors::SSHPortNotDetected end |
#up? ⇒ Boolean
Checks if this environment's machine is up (i.e. responding to SSH).
104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 |
# File 'lib/vagrant/ssh.rb', line 104 def up? # We have to determine the port outside of the block since it uses # API calls which can only be used from the main thread in JRuby on # Windows ssh_port = port Timeout.timeout(env.config.ssh.timeout) do execute(:timeout => env.config.ssh.timeout, :port => ssh_port) { |ssh| } end true rescue Net::SSH::AuthenticationFailed raise Errors::SSHAuthenticationFailed rescue Timeout::Error, Errno::ECONNREFUSED, Net::SSH::Disconnect, Errors::SSHConnectionRefused, Net::SSH::AuthenticationFailed return false end |
#upload!(from, to) ⇒ Object
Uploads a file from from
to to
. from
is expected to be a filename
or StringIO, and to
is expected to be a path. This method simply forwards
the arguments to Net::SCP#upload!
so view that for more information.
92 93 94 95 96 97 98 99 |
# File 'lib/vagrant/ssh.rb', line 92 def upload!(from, to) retryable(:tries => 5, :on => IOError) do execute do |ssh| scp = Net::SCP.new(ssh.session) scp.upload!(from, to) end end end |