Class: Vagrant::SSH

Inherits:
Object
  • Object
show all
Includes:
Util
Defined in:
lib/vagrant/ssh.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.

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Util

#error_and_exit, included, #logger, #wrap_output

Constructor Details

#initialize(environment) ⇒ SSH

Returns a new instance of SSH.



12
13
14
# File 'lib/vagrant/ssh.rb', line 12

def initialize(environment)
  @env = environment
end

Instance Attribute Details

#envObject

Reference back up to the environment which this SSH object belongs to



10
11
12
# File 'lib/vagrant/ssh.rb', line 10

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.



73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
# File 'lib/vagrant/ssh.rb', line 73

def check_key_permissions(key_path)
  # TODO: This only works on unix based systems for now. Windows
  # systems will need to be investigated further.
  stat = File.stat(key_path)

  if stat.owned? && file_perms(key_path) != "600"
    logger.info "Permissions on private key incorrect, fixing..."
    File.chmod(0600, key_path)

    error_and_exit(:ssh_bad_permissions, :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.
  error_and_exit(:ssh_bad_permissions, :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.



19
20
21
22
23
24
25
26
27
# File 'lib/vagrant/ssh.rb', line 19

def connect(opts={})
  options = {}
  [:host, :username, :private_key_path].each do |param|
    options[param] = opts[param] || env.config.ssh.send(param)
  end

  check_key_permissions(options[:private_key_path])
  Kernel.exec "ssh -p #{port(opts)} -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -i #{options[:private_key_path]} #{options[:username]}@#{options[:host]}".strip
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.



31
32
33
34
35
36
37
38
# File 'lib/vagrant/ssh.rb', line 31

def execute(opts={})
  Net::SSH.start(env.config.ssh.host,
                 env.config[:ssh][:username],
                 opts.merge( :port => port,
                             :keys => [env.config.ssh.private_key_path])) do |ssh|
    yield ssh
  end
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.



92
93
94
95
# File 'lib/vagrant/ssh.rb', line 92

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`



100
101
102
# File 'lib/vagrant/ssh.rb', line 100

def port(opts={})
  opts[:port] || env.config.vm.forwarded_ports[env.config.ssh.forwarded_port_key][:hostport]
end

#up?Boolean

Checks if this environment’s machine is up (i.e. responding to SSH).

Returns:

  • (Boolean)


53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
# File 'lib/vagrant/ssh.rb', line 53

def up?
  check_thread = Thread.new do
    begin
      Thread.current[:result] = false
      execute(:timeout => env.config.ssh.timeout) do |ssh|
        Thread.current[:result] = true
      end
    rescue Errno::ECONNREFUSED, Net::SSH::Disconnect
      # False, its defaulted above
    end
  end

  check_thread.join(env.config.ssh.timeout)
  return check_thread[:result]
rescue Net::SSH::AuthenticationFailed
  error_and_exit(:vm_ssh_auth_failed)
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.



43
44
45
46
47
48
# File 'lib/vagrant/ssh.rb', line 43

def upload!(from, to)
  execute do |ssh|
    scp = Net::SCP.new(ssh)
    scp.upload!(from, to)
  end
end