SSH class converted to instance methods. now loads on the environment
This commit is contained in:
parent
689f69bd4c
commit
260b099dba
|
@ -28,27 +28,27 @@ module Vagrant
|
|||
# useful information such as whether or not the environment is created
|
||||
# and if its running, suspended, etc.
|
||||
def status
|
||||
Env.load!
|
||||
env = Environment.load!
|
||||
|
||||
wrap_output do
|
||||
if !Env.persisted_vm
|
||||
if !env.vm
|
||||
puts <<-msg
|
||||
The environment has not yet been created. Run `vagrant up` to create the
|
||||
environment.
|
||||
msg
|
||||
else
|
||||
additional_msg = ""
|
||||
if Env.persisted_vm.vm.running?
|
||||
if env.vm.vm.running?
|
||||
additional_msg = <<-msg
|
||||
To stop this VM, you can run `vagrant halt` to shut it down forcefully,
|
||||
or you can run `vagrant suspend` to simply suspend the virtual machine.
|
||||
In either case, to restart it again, simply run a `vagrant up`.
|
||||
msg
|
||||
elsif Env.persisted_vm.vm.saved?
|
||||
elsif env.vm.vm.saved?
|
||||
additional_msg = <<-msg
|
||||
To resume this VM, simply run `vagrant up`.
|
||||
msg
|
||||
elsif Env.persisted_vm.vm.powered_off?
|
||||
elsif env.vm.vm.powered_off?
|
||||
additional_msg = <<-msg
|
||||
To restart this VM, simply run `vagrant up`.
|
||||
msg
|
||||
|
@ -61,7 +61,7 @@ msg
|
|||
|
||||
puts <<-msg
|
||||
The environment has been created. The status of the current environment's
|
||||
virtual machine is: "#{Env.persisted_vm.vm.state}."#{additional_msg}
|
||||
virtual machine is: "#{env.vm.vm.state}."#{additional_msg}
|
||||
msg
|
||||
end
|
||||
end
|
||||
|
|
|
@ -13,6 +13,7 @@ module Vagrant
|
|||
attr_reader :config
|
||||
attr_reader :box
|
||||
attr_reader :vm
|
||||
attr_reader :ssh
|
||||
|
||||
#---------------------------------------------------------------
|
||||
# Class Methods
|
||||
|
@ -84,6 +85,7 @@ module Vagrant
|
|||
load_config!
|
||||
self.class.check_virtualbox!
|
||||
load_vm!
|
||||
load_ssh!
|
||||
self
|
||||
end
|
||||
|
||||
|
@ -167,6 +169,11 @@ module Vagrant
|
|||
@vm = nil
|
||||
end
|
||||
|
||||
# Loads/initializes the SSH object
|
||||
def load_ssh!
|
||||
@ssh = SSH.new(self)
|
||||
end
|
||||
|
||||
#---------------------------------------------------------------
|
||||
# Methods to manage VM
|
||||
#---------------------------------------------------------------
|
||||
|
|
|
@ -1,54 +1,77 @@
|
|||
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
|
||||
include Vagrant::Util
|
||||
|
||||
class << self
|
||||
def connect(opts={})
|
||||
options = {}
|
||||
[:host, :username, :private_key_path].each do |param|
|
||||
options[param] = opts[param] || Vagrant.config.ssh.send(param)
|
||||
end
|
||||
# Reference back up to the environment which this SSH object belongs
|
||||
# to
|
||||
attr_accessor :env
|
||||
|
||||
Kernel.exec "ssh -p #{port(opts)} -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -i #{options[:private_key_path]} #{options[:username]}@#{options[:host]}".strip
|
||||
def initialize(environment)
|
||||
@env = environment
|
||||
end
|
||||
|
||||
# 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.
|
||||
def connect(opts={})
|
||||
options = {}
|
||||
[:host, :username, :private_key_path].each do |param|
|
||||
options[param] = opts[param] || env.config.ssh.send(param)
|
||||
end
|
||||
|
||||
def execute(opts={})
|
||||
Net::SSH.start(Vagrant.config.ssh.host,
|
||||
Vagrant.config[:ssh][:username],
|
||||
opts.merge( :port => port,
|
||||
:keys => [Vagrant.config.ssh.private_key_path])) do |ssh|
|
||||
yield ssh
|
||||
end
|
||||
end
|
||||
Kernel.exec "ssh -p #{port(opts)} -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -i #{options[:private_key_path]} #{options[:username]}@#{options[:host]}".strip
|
||||
end
|
||||
|
||||
def upload!(from, to)
|
||||
execute do |ssh|
|
||||
scp = Net::SCP.new(ssh)
|
||||
scp.upload!(from, to)
|
||||
end
|
||||
# Opens an SSH connection to this environment's virtual machine and yields
|
||||
# a Net::SSH object which can be used to execute remote commands.
|
||||
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
|
||||
|
||||
def up?
|
||||
check_thread = Thread.new do
|
||||
begin
|
||||
Thread.current[:result] = false
|
||||
execute(:timeout => Vagrant.config.ssh.timeout) do |ssh|
|
||||
Thread.current[:result] = true
|
||||
end
|
||||
rescue Errno::ECONNREFUSED, Net::SSH::Disconnect
|
||||
# False, its defaulted above
|
||||
# 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.
|
||||
def upload!(from, to)
|
||||
execute do |ssh|
|
||||
scp = Net::SCP.new(ssh)
|
||||
scp.upload!(from, to)
|
||||
end
|
||||
end
|
||||
|
||||
# Checks if this environment's machine is up (i.e. responding to SSH).
|
||||
#
|
||||
# @return [Boolean]
|
||||
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
|
||||
|
||||
check_thread.join(Vagrant.config.ssh.timeout)
|
||||
return check_thread[:result]
|
||||
rescue Net::SSH::AuthenticationFailed
|
||||
error_and_exit(:vm_ssh_auth_failed)
|
||||
end
|
||||
|
||||
def port(opts={})
|
||||
opts[:port] || Vagrant.config.vm.forwarded_ports[Vagrant.config.ssh.forwarded_port_key][:hostport]
|
||||
end
|
||||
check_thread.join(env.config.ssh.timeout)
|
||||
return check_thread[:result]
|
||||
rescue Net::SSH::AuthenticationFailed
|
||||
error_and_exit(:vm_ssh_auth_failed)
|
||||
end
|
||||
|
||||
# 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`
|
||||
def port(opts={})
|
||||
opts[:port] || env.config.vm.forwarded_ports[env.config.ssh.forwarded_port_key][:hostport]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -128,6 +128,7 @@ class EnvironmentTest < Test::Unit::TestCase
|
|||
@env.expects(:load_config!).once.in_sequence(call_seq)
|
||||
Vagrant::Environment.expects(:check_virtualbox!).once.in_sequence(call_seq)
|
||||
@env.expects(:load_vm!).once.in_sequence(call_seq)
|
||||
@env.expects(:load_ssh!).once.in_sequence(call_seq)
|
||||
assert_equal @env, @env.load!
|
||||
end
|
||||
end
|
||||
|
@ -368,6 +369,19 @@ class EnvironmentTest < Test::Unit::TestCase
|
|||
assert_nil @env.vm
|
||||
end
|
||||
end
|
||||
|
||||
context "loading SSH" do
|
||||
setup do
|
||||
@env = mock_environment
|
||||
end
|
||||
|
||||
should "initialize the SSH object with the given environment" do
|
||||
ssh = mock("ssh")
|
||||
Vagrant::SSH.expects(:new).with(@env).returns(ssh)
|
||||
@env.load_ssh!
|
||||
assert_equal ssh, @env.ssh
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "requiring properties" do
|
||||
|
|
|
@ -5,24 +5,35 @@ class SshTest < Test::Unit::TestCase
|
|||
mock_config
|
||||
end
|
||||
|
||||
context "connecting to SSH" do
|
||||
test "should call exec with defaults when no options are supplied" do
|
||||
ssh = Vagrant.config.ssh
|
||||
ssh_exec_expect(Vagrant::SSH.port,
|
||||
Vagrant.config.ssh.private_key_path,
|
||||
Vagrant.config.ssh.username,
|
||||
Vagrant.config.ssh.host)
|
||||
Vagrant::SSH.connect
|
||||
def mock_ssh
|
||||
@env = mock_environment do |config|
|
||||
yield config if block_given?
|
||||
end
|
||||
|
||||
test "should call exec with supplied params" do
|
||||
@ssh = Vagrant::SSH.new(@env)
|
||||
end
|
||||
|
||||
context "connecting to external SSH" do
|
||||
setup do
|
||||
mock_ssh
|
||||
end
|
||||
|
||||
should "call exec with defaults when no options are supplied" do
|
||||
ssh_exec_expect(@ssh.port,
|
||||
@env.config.ssh.private_key_path,
|
||||
@env.config.ssh.username,
|
||||
@env.config.ssh.host)
|
||||
@ssh.connect
|
||||
end
|
||||
|
||||
should "call exec with supplied params" do
|
||||
args = {:username => 'bar', :private_key_path => 'baz', :host => 'bak', :port => 'bag'}
|
||||
ssh_exec_expect(args[:port], args[:private_key_path], args[:username], args[:host])
|
||||
Vagrant::SSH.connect(args)
|
||||
@ssh.connect(args)
|
||||
end
|
||||
|
||||
def ssh_exec_expect(port, key_path, uname, host)
|
||||
Kernel.expects(:exec).with() do |arg|
|
||||
Kernel.expects(:exec).with() do |arg|
|
||||
assert arg =~ /^ssh/
|
||||
assert arg =~ /-p #{port}/
|
||||
assert arg =~ /-i #{key_path}/
|
||||
|
@ -34,91 +45,103 @@ class SshTest < Test::Unit::TestCase
|
|||
end
|
||||
|
||||
context "executing ssh commands" do
|
||||
setup do
|
||||
mock_ssh
|
||||
end
|
||||
|
||||
should "call net::ssh.start with the proper names" do
|
||||
Net::SSH.expects(:start).once.with() do |host, username, opts|
|
||||
assert_equal Vagrant.config.ssh.host, host
|
||||
assert_equal Vagrant.config.ssh.username, username
|
||||
assert_equal Vagrant::SSH.port, opts[:port]
|
||||
assert_equal [Vagrant.config.ssh.private_key_path], opts[:keys]
|
||||
assert_equal @env.config.ssh.host, host
|
||||
assert_equal @env.config.ssh.username, username
|
||||
assert_equal @ssh.port, opts[:port]
|
||||
assert_equal [@env.config.ssh.private_key_path], opts[:keys]
|
||||
true
|
||||
end
|
||||
Vagrant::SSH.execute
|
||||
@ssh.execute
|
||||
end
|
||||
|
||||
should "use custom host if set" do
|
||||
Vagrant.config.ssh.host = "foo"
|
||||
Net::SSH.expects(:start).with(Vagrant.config.ssh.host, Vagrant.config.ssh.username, anything).once
|
||||
Vagrant::SSH.execute
|
||||
@env.config.ssh.host = "foo"
|
||||
Net::SSH.expects(:start).with(@env.config.ssh.host, @env.config.ssh.username, anything).once
|
||||
@ssh.execute
|
||||
end
|
||||
end
|
||||
|
||||
context "SCPing files to the remote host" do
|
||||
setup do
|
||||
mock_ssh
|
||||
end
|
||||
|
||||
should "use Vagrant::SSH execute to setup an SCP connection and upload" do
|
||||
scp = mock("scp")
|
||||
ssh = mock("ssh")
|
||||
scp.expects(:upload!).with("foo", "bar").once
|
||||
Net::SCP.expects(:new).with(ssh).returns(scp).once
|
||||
Vagrant::SSH.expects(:execute).yields(ssh).once
|
||||
Vagrant::SSH.upload!("foo", "bar")
|
||||
@ssh.expects(:execute).yields(ssh).once
|
||||
@ssh.upload!("foo", "bar")
|
||||
end
|
||||
end
|
||||
|
||||
context "checking if host is up" do
|
||||
setup do
|
||||
mock_config
|
||||
mock_ssh
|
||||
end
|
||||
|
||||
should "return true if SSH connection works" do
|
||||
Net::SSH.expects(:start).yields("success")
|
||||
assert Vagrant::SSH.up?
|
||||
assert @ssh.up?
|
||||
end
|
||||
|
||||
should "return false if SSH connection times out" do
|
||||
Net::SSH.expects(:start)
|
||||
assert !Vagrant::SSH.up?
|
||||
assert !@ssh.up?
|
||||
end
|
||||
|
||||
should "allow the thread the configured timeout time" do
|
||||
@thread = mock("thread")
|
||||
@thread.stubs(:[])
|
||||
Thread.expects(:new).returns(@thread)
|
||||
@thread.expects(:join).with(Vagrant.config.ssh.timeout).once
|
||||
Vagrant::SSH.up?
|
||||
@thread.expects(:join).with(@env.config.ssh.timeout).once
|
||||
@ssh.up?
|
||||
end
|
||||
|
||||
should "return false if the connection is refused" do
|
||||
Net::SSH.expects(:start).raises(Errno::ECONNREFUSED)
|
||||
assert_nothing_raised {
|
||||
assert !Vagrant::SSH.up?
|
||||
assert !@ssh.up?
|
||||
}
|
||||
end
|
||||
|
||||
should "return false if the connection is dropped" do
|
||||
Net::SSH.expects(:start).raises(Net::SSH::Disconnect)
|
||||
assert_nothing_raised {
|
||||
assert !Vagrant::SSH.up?
|
||||
assert !@ssh.up?
|
||||
}
|
||||
end
|
||||
|
||||
should "specifity the timeout as an option to execute" do
|
||||
Vagrant::SSH.expects(:execute).with(:timeout => Vagrant.config.ssh.timeout).yields(true)
|
||||
assert Vagrant::SSH.up?
|
||||
@ssh.expects(:execute).with(:timeout => @env.config.ssh.timeout).yields(true)
|
||||
assert @ssh.up?
|
||||
end
|
||||
|
||||
should "error and exit if a Net::SSH::AuthenticationFailed is raised" do
|
||||
Vagrant::SSH.expects(:execute).raises(Net::SSH::AuthenticationFailed)
|
||||
Vagrant::SSH.expects(:error_and_exit).with(:vm_ssh_auth_failed).once
|
||||
Vagrant::SSH.up?
|
||||
@ssh.expects(:execute).raises(Net::SSH::AuthenticationFailed)
|
||||
@ssh.expects(:error_and_exit).with(:vm_ssh_auth_failed).once
|
||||
@ssh.up?
|
||||
end
|
||||
end
|
||||
|
||||
context "getting the ssh port" do
|
||||
setup do
|
||||
mock_ssh
|
||||
end
|
||||
|
||||
should "return the configured port by default" do
|
||||
assert_equal Vagrant.config.vm.forwarded_ports[Vagrant.config.ssh.forwarded_port_key][:hostport], Vagrant::SSH.port
|
||||
assert_equal @env.config.vm.forwarded_ports[@env.config.ssh.forwarded_port_key][:hostport], @ssh.port
|
||||
end
|
||||
|
||||
should "return the port given in options if it exists" do
|
||||
assert_equal "47", Vagrant::SSH.port({ :port => "47" })
|
||||
assert_equal "47", @ssh.port({ :port => "47" })
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue