vagrantup 0.1.4 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +1 -1
- data/Rakefile +1 -1
- data/VERSION +1 -1
- data/bin/vagrant +1 -1
- data/bin/vagrant-box +1 -2
- data/bin/vagrant-down +1 -2
- data/bin/vagrant-halt +1 -2
- data/bin/vagrant-init +1 -2
- data/bin/vagrant-package +1 -2
- data/bin/vagrant-reload +1 -2
- data/bin/vagrant-resume +1 -2
- data/bin/vagrant-ssh +1 -2
- data/bin/vagrant-status +29 -0
- data/bin/vagrant-suspend +1 -2
- data/bin/vagrant-up +1 -2
- data/config/default.rb +5 -9
- data/keys/README.md +10 -0
- data/keys/vagrant +27 -0
- data/keys/vagrant.pub +1 -0
- data/lib/vagrant.rb +10 -5
- data/lib/vagrant/actions/base.rb +14 -0
- data/lib/vagrant/actions/box/download.rb +3 -0
- data/lib/vagrant/actions/collection.rb +36 -0
- data/lib/vagrant/actions/runner.rb +4 -10
- data/lib/vagrant/actions/vm/boot.rb +4 -5
- data/lib/vagrant/actions/vm/customize.rb +17 -0
- data/lib/vagrant/actions/vm/destroy.rb +11 -2
- data/lib/vagrant/actions/vm/forward_ports.rb +24 -0
- data/lib/vagrant/actions/vm/import.rb +1 -0
- data/lib/vagrant/actions/vm/provision.rb +30 -52
- data/lib/vagrant/actions/vm/reload.rb +2 -2
- data/lib/vagrant/actions/vm/shared_folders.rb +37 -25
- data/lib/vagrant/actions/vm/up.rb +8 -4
- data/lib/vagrant/active_list.rb +66 -0
- data/lib/vagrant/commands.rb +44 -0
- data/lib/vagrant/config.rb +64 -47
- data/lib/vagrant/downloaders/base.rb +3 -0
- data/lib/vagrant/downloaders/file.rb +11 -11
- data/lib/vagrant/env.rb +48 -12
- data/lib/vagrant/provisioners/base.rb +22 -0
- data/lib/vagrant/provisioners/chef.rb +102 -0
- data/lib/vagrant/provisioners/chef_server.rb +96 -0
- data/lib/vagrant/provisioners/chef_solo.rb +67 -0
- data/lib/vagrant/ssh.rb +25 -6
- data/lib/vagrant/stacked_proc_runner.rb +33 -0
- data/lib/vagrant/vm.rb +8 -0
- data/test/test_helper.rb +22 -6
- data/test/vagrant/actions/box/download_test.rb +11 -0
- data/test/vagrant/actions/collection_test.rb +110 -0
- data/test/vagrant/actions/runner_test.rb +11 -7
- data/test/vagrant/actions/vm/boot_test.rb +7 -7
- data/test/vagrant/actions/vm/customize_test.rb +16 -0
- data/test/vagrant/actions/vm/destroy_test.rb +19 -6
- data/test/vagrant/actions/vm/forward_ports_test.rb +52 -0
- data/test/vagrant/actions/vm/import_test.rb +10 -3
- data/test/vagrant/actions/vm/provision_test.rb +75 -70
- data/test/vagrant/actions/vm/reload_test.rb +3 -2
- data/test/vagrant/actions/vm/shared_folders_test.rb +62 -9
- data/test/vagrant/actions/vm/up_test.rb +4 -4
- data/test/vagrant/active_list_test.rb +169 -0
- data/test/vagrant/config_test.rb +145 -29
- data/test/vagrant/downloaders/base_test.rb +7 -0
- data/test/vagrant/downloaders/file_test.rb +12 -18
- data/test/vagrant/env_test.rb +96 -23
- data/test/vagrant/provisioners/base_test.rb +27 -0
- data/test/vagrant/provisioners/chef_server_test.rb +175 -0
- data/test/vagrant/provisioners/chef_solo_test.rb +142 -0
- data/test/vagrant/provisioners/chef_test.rb +116 -0
- data/test/vagrant/ssh_test.rb +29 -8
- data/test/vagrant/stacked_proc_runner_test.rb +43 -0
- data/test/vagrant/vm_test.rb +23 -0
- data/vagrant.gemspec +34 -7
- metadata +33 -5
- data/script/vagrant-ssh-expect.sh +0 -22
@@ -5,6 +5,9 @@ module Vagrant
|
|
5
5
|
class Base
|
6
6
|
include Vagrant::Util
|
7
7
|
|
8
|
+
# Called prior to execution so any error checks can be done
|
9
|
+
def prepare(source_url); end
|
10
|
+
|
8
11
|
# Downloads the source file to the destination file. It is up to
|
9
12
|
# implementors of this class to handle the logic.
|
10
13
|
def download!(source_url, destination_file); end
|
@@ -3,19 +3,19 @@ module Vagrant
|
|
3
3
|
# "Downloads" a file to a temporary file. Basically, this downloader
|
4
4
|
# simply does a file copy.
|
5
5
|
class File < Base
|
6
|
-
|
6
|
+
def prepare(source_url)
|
7
|
+
if !::File.file?(source_url)
|
8
|
+
raise Actions::ActionException.new(<<-msg)
|
9
|
+
The given box does not exist on the file system:
|
7
10
|
|
8
|
-
|
9
|
-
|
10
|
-
# and copy it into the other. In the future, we should do
|
11
|
-
# a system-level file copy (FileUtils.cp).
|
12
|
-
open(source_url) do |f|
|
13
|
-
loop do
|
14
|
-
break if f.eof?
|
15
|
-
destination_file.write(f.read(BUFFERSIZE))
|
16
|
-
end
|
11
|
+
#{source_url}
|
12
|
+
msg
|
17
13
|
end
|
18
14
|
end
|
15
|
+
|
16
|
+
def download!(source_url, destination_file)
|
17
|
+
FileUtils.cp(source_url, destination_file.path)
|
18
|
+
end
|
19
19
|
end
|
20
20
|
end
|
21
|
-
end
|
21
|
+
end
|
data/lib/vagrant/env.rb
CHANGED
@@ -24,21 +24,52 @@ module Vagrant
|
|
24
24
|
load_config!
|
25
25
|
load_home_directory!
|
26
26
|
load_box!
|
27
|
+
load_config!
|
28
|
+
check_virtualbox!
|
27
29
|
load_vm!
|
28
30
|
end
|
29
31
|
|
32
|
+
def check_virtualbox!
|
33
|
+
version = VirtualBox::Command.version
|
34
|
+
if version.nil?
|
35
|
+
error_and_exit(<<-msg)
|
36
|
+
Vagrant could not detect VirtualBox! Make sure VirtualBox is properly installed.
|
37
|
+
If VirtualBox is installed, you may need to tweak the paths to the `VBoxManage`
|
38
|
+
application which ships with VirtualBox and the path to the global XML configuration
|
39
|
+
which VirtualBox typically stores somewhere in your home directory.
|
40
|
+
|
41
|
+
The following shows how to configure VirtualBox. This can be done in the
|
42
|
+
Vagrantfile. Note that 90% of the time, you shouldn't need to do this if VirtualBox
|
43
|
+
is installed. Please use the various Vagrant support lines to request more information
|
44
|
+
if you can't get this working.
|
45
|
+
|
46
|
+
VirtualBox::Command.vboxmanage = "/path/to/my/VBoxManage"
|
47
|
+
VirtualBox::Global.vboxconfig = "~/path/to/VirtualBox.xml"
|
48
|
+
msg
|
49
|
+
elsif version.to_f < 3.1
|
50
|
+
error_and_exit(<<-msg)
|
51
|
+
Vagrant has detected that you have VirtualBox version #{version} installed!
|
52
|
+
Vagrant requires that you use at least VirtualBox version 3.1. Please install
|
53
|
+
a more recent version of VirtualBox to continue.
|
54
|
+
msg
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
30
58
|
def load_config!
|
31
59
|
# Prepare load paths for config files
|
32
60
|
load_paths = [File.join(PROJECT_ROOT, "config", "default.rb")]
|
33
61
|
load_paths << File.join(box.directory, ROOTFILE_NAME) if box
|
62
|
+
load_paths << File.join(home_path, ROOTFILE_NAME) if Vagrant.config.vagrant.home
|
34
63
|
load_paths << File.join(root_path, ROOTFILE_NAME) if root_path
|
35
64
|
|
36
65
|
# Then clear out the old data
|
37
66
|
Config.reset!
|
38
67
|
|
39
68
|
load_paths.each do |path|
|
40
|
-
|
41
|
-
|
69
|
+
if File.exist?(path)
|
70
|
+
logger.info "Loading config from #{path}..."
|
71
|
+
load path
|
72
|
+
end
|
42
73
|
end
|
43
74
|
|
44
75
|
# Execute the configurations
|
@@ -63,11 +94,6 @@ module Vagrant
|
|
63
94
|
return unless root_path
|
64
95
|
|
65
96
|
@@box = Box.find(Vagrant.config.vm.box) if Vagrant.config.vm.box
|
66
|
-
|
67
|
-
if @@box
|
68
|
-
logger.info("Reloading configuration to account for loaded box...")
|
69
|
-
load_config!
|
70
|
-
end
|
71
97
|
end
|
72
98
|
|
73
99
|
def load_vm!
|
@@ -81,18 +107,28 @@ module Vagrant
|
|
81
107
|
end
|
82
108
|
|
83
109
|
def persist_vm(vm)
|
110
|
+
# Save to the dotfile for this project
|
84
111
|
File.open(dotfile_path, 'w+') do |f|
|
85
112
|
f.write(vm.uuid)
|
86
113
|
end
|
114
|
+
|
115
|
+
# Also add to the global store
|
116
|
+
ActiveList.add(vm)
|
117
|
+
end
|
118
|
+
|
119
|
+
def depersist_vm(vm)
|
120
|
+
# Delete the dotfile if it exists
|
121
|
+
File.delete(dotfile_path) if File.exist?(dotfile_path)
|
122
|
+
|
123
|
+
# Remove from the global store
|
124
|
+
ActiveList.remove(vm)
|
87
125
|
end
|
88
126
|
|
89
127
|
def load_root_path!(path=nil)
|
90
|
-
path
|
128
|
+
path = Pathname.new(File.expand_path(path || Dir.pwd))
|
91
129
|
|
92
|
-
# Stop if we're at the root.
|
93
|
-
|
94
|
-
# researched.
|
95
|
-
return false if path.to_s == '/' || path.to_s =~ /^[A-Z]:\.$/
|
130
|
+
# Stop if we're at the root.
|
131
|
+
return false if path.root?
|
96
132
|
|
97
133
|
file = "#{path}/#{ROOTFILE_NAME}"
|
98
134
|
if File.exist?(file)
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Vagrant
|
2
|
+
module Provisioners
|
3
|
+
# The base class for a "provisioner." A provisioner is responsible for
|
4
|
+
# provisioning a Vagrant system. This has been abstracted out to provide
|
5
|
+
# support for multiple solutions such as Chef Solo, Chef Client, and
|
6
|
+
# Puppet.
|
7
|
+
class Base
|
8
|
+
include Vagrant::Util
|
9
|
+
|
10
|
+
# This is the method called to "prepare" the provisioner. This is called
|
11
|
+
# before any actions are run by the action runner (see {Vagrant::Actions::Runner}).
|
12
|
+
# This can be used to setup shared folders, forward ports, etc. Whatever is
|
13
|
+
# necessary on a "meta" level.
|
14
|
+
def prepare; end
|
15
|
+
|
16
|
+
# This is the method called to provision the system. This method
|
17
|
+
# is expected to do whatever necessary to provision the system (create files,
|
18
|
+
# SSH, etc.)
|
19
|
+
def provision!; end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,102 @@
|
|
1
|
+
module Vagrant
|
2
|
+
module Provisioners
|
3
|
+
# This class is a base class where the common functinality shared between
|
4
|
+
# chef-solo and chef-client provisioning are stored. This is **not an actual
|
5
|
+
# provisioner**. Instead, {ChefSolo} or {ChefServer} should be used.
|
6
|
+
class Chef < Base
|
7
|
+
# This is the configuration which is available through `config.chef`
|
8
|
+
class ChefConfig < Vagrant::Config::Base
|
9
|
+
# Chef server specific config
|
10
|
+
attr_accessor :chef_server_url
|
11
|
+
attr_accessor :validation_key_path
|
12
|
+
attr_accessor :validation_client_name
|
13
|
+
attr_accessor :client_key_path
|
14
|
+
|
15
|
+
# Chef solo specific config
|
16
|
+
attr_accessor :cookbooks_path
|
17
|
+
|
18
|
+
# Shared config
|
19
|
+
attr_accessor :provisioning_path
|
20
|
+
attr_accessor :json
|
21
|
+
|
22
|
+
def initialize
|
23
|
+
@validation_client_name = "chef-validator"
|
24
|
+
@client_key_path = "/etc/chef/client.pem"
|
25
|
+
|
26
|
+
@cookbooks_path = "cookbooks"
|
27
|
+
@provisioning_path = "/tmp/vagrant-chef"
|
28
|
+
@json = {
|
29
|
+
:instance_role => "vagrant",
|
30
|
+
:run_list => ["recipe[vagrant_main]"]
|
31
|
+
}
|
32
|
+
end
|
33
|
+
|
34
|
+
# Returns the run list for the provisioning
|
35
|
+
def run_list
|
36
|
+
json[:run_list]
|
37
|
+
end
|
38
|
+
|
39
|
+
# Sets the run list to the specified value
|
40
|
+
def run_list=(value)
|
41
|
+
json[:run_list] = value
|
42
|
+
end
|
43
|
+
|
44
|
+
# Adds a recipe to the run list
|
45
|
+
def add_recipe(name)
|
46
|
+
name = "recipe[#{name}]" unless name =~ /^recipe\[(.+?)\]$/
|
47
|
+
run_list << name
|
48
|
+
end
|
49
|
+
|
50
|
+
# Adds a role to the run list
|
51
|
+
def add_role(name)
|
52
|
+
name = "role[#{name}]" unless name =~ /^role\[(.+?)\]$/
|
53
|
+
run_list << name
|
54
|
+
end
|
55
|
+
|
56
|
+
def to_json
|
57
|
+
# Overridden so that the 'json' key could be removed, since its just
|
58
|
+
# merged into the config anyways
|
59
|
+
data = instance_variables_hash
|
60
|
+
data.delete(:json)
|
61
|
+
data.to_json
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
# Tell the Vagrant configure class about our custom configuration
|
66
|
+
Config.configures :chef, ChefConfig
|
67
|
+
|
68
|
+
def prepare
|
69
|
+
raise Actions::ActionException.new("Vagrant::Provisioners::Chef is not a valid provisioner! Use ChefSolo or ChefServer instead.")
|
70
|
+
end
|
71
|
+
|
72
|
+
def chown_provisioning_folder
|
73
|
+
logger.info "Setting permissions on chef provisioning folder..."
|
74
|
+
SSH.execute do |ssh|
|
75
|
+
ssh.exec!("sudo mkdir -p #{Vagrant.config.chef.provisioning_path}")
|
76
|
+
ssh.exec!("sudo chown #{Vagrant.config.ssh.username} #{Vagrant.config.chef.provisioning_path}")
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def setup_json
|
81
|
+
logger.info "Generating chef JSON and uploading..."
|
82
|
+
|
83
|
+
# Set up initial configuration
|
84
|
+
data = {
|
85
|
+
:config => Vagrant.config,
|
86
|
+
:directory => Vagrant.config.vm.project_directory,
|
87
|
+
}
|
88
|
+
|
89
|
+
# And wrap it under the "vagrant" namespace
|
90
|
+
data = { :vagrant => data }
|
91
|
+
|
92
|
+
# Merge with the "extra data" which isn't put under the
|
93
|
+
# vagrant namespace by default
|
94
|
+
data.merge!(Vagrant.config.chef.json)
|
95
|
+
|
96
|
+
json = data.to_json
|
97
|
+
|
98
|
+
SSH.upload!(StringIO.new(json), File.join(Vagrant.config.chef.provisioning_path, "dna.json"))
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
@@ -0,0 +1,96 @@
|
|
1
|
+
module Vagrant
|
2
|
+
module Provisioners
|
3
|
+
# This class implements provisioning via chef-client, allowing provisioning
|
4
|
+
# with a chef server.
|
5
|
+
class ChefServer < Chef
|
6
|
+
def prepare
|
7
|
+
if Vagrant.config.chef.validation_key_path.nil?
|
8
|
+
raise Actions::ActionException.new(<<-msg)
|
9
|
+
Chef server provisioning requires that the `config.chef.validation_key_path` configuration
|
10
|
+
be set to a path on your local machine of the validation key used to register the
|
11
|
+
VM with the chef server.
|
12
|
+
msg
|
13
|
+
elsif !File.file?(Vagrant.config.chef.validation_key_path)
|
14
|
+
raise Actions::ActionException.new(<<-msg)
|
15
|
+
The validation key set for `config.chef.validation_key_path` does not exist! This
|
16
|
+
file needs to exist so it can be uploaded to the virtual machine. It is
|
17
|
+
currently set to "#{Vagrant.config.chef.validation_key_path}"
|
18
|
+
msg
|
19
|
+
end
|
20
|
+
|
21
|
+
if Vagrant.config.chef.chef_server_url.nil?
|
22
|
+
raise Actions::ActionException.new(<<-msg)
|
23
|
+
Chef server provisioning requires that the `config.chef.chef_server_url` be set to the
|
24
|
+
URL of your chef server. Examples include "http://12.12.12.12:4000" and
|
25
|
+
"http://myserver.com:4000" (the port of course can be different, but 4000 is the default)
|
26
|
+
msg
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def provision!
|
31
|
+
chown_provisioning_folder
|
32
|
+
create_client_key_folder
|
33
|
+
upload_validation_key
|
34
|
+
setup_json
|
35
|
+
setup_config
|
36
|
+
run_chef_client
|
37
|
+
end
|
38
|
+
|
39
|
+
def create_client_key_folder
|
40
|
+
logger.info "Creating folder to hold client key..."
|
41
|
+
path = Pathname.new(Vagrant.config.chef.client_key_path)
|
42
|
+
|
43
|
+
SSH.execute do |ssh|
|
44
|
+
ssh.exec!("sudo mkdir -p #{path.dirname}")
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def upload_validation_key
|
49
|
+
logger.info "Uploading chef client validation key..."
|
50
|
+
SSH.upload!(validation_key_path, guest_validation_key_path)
|
51
|
+
end
|
52
|
+
|
53
|
+
def setup_config
|
54
|
+
solo_file = <<-solo
|
55
|
+
log_level :info
|
56
|
+
log_location STDOUT
|
57
|
+
ssl_verify_mode :verify_none
|
58
|
+
chef_server_url "#{Vagrant.config.chef.chef_server_url}"
|
59
|
+
|
60
|
+
validation_client_name "#{Vagrant.config.chef.validation_client_name}"
|
61
|
+
validation_key "#{guest_validation_key_path}"
|
62
|
+
client_key "#{Vagrant.config.chef.client_key_path}"
|
63
|
+
|
64
|
+
file_store_path "/srv/chef/file_store"
|
65
|
+
file_cache_path "/srv/chef/cache"
|
66
|
+
|
67
|
+
pid_file "/var/run/chef/chef-client.pid"
|
68
|
+
|
69
|
+
Mixlib::Log::Formatter.show_time = true
|
70
|
+
solo
|
71
|
+
|
72
|
+
logger.info "Uploading chef-client configuration script..."
|
73
|
+
SSH.upload!(StringIO.new(solo_file), File.join(Vagrant.config.chef.provisioning_path, "client.rb"))
|
74
|
+
end
|
75
|
+
|
76
|
+
def run_chef_client
|
77
|
+
logger.info "Running chef-client..."
|
78
|
+
SSH.execute do |ssh|
|
79
|
+
ssh.exec!("cd #{Vagrant.config.chef.provisioning_path} && sudo chef-client -c client.rb -j dna.json") do |channel, data, stream|
|
80
|
+
# TODO: Very verbose. It would be easier to save the data and only show it during
|
81
|
+
# an error, or when verbosity level is set high
|
82
|
+
logger.info("#{stream}: #{data}")
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def validation_key_path
|
88
|
+
File.expand_path(Vagrant.config.chef.validation_key_path, Env.root_path)
|
89
|
+
end
|
90
|
+
|
91
|
+
def guest_validation_key_path
|
92
|
+
File.join(Vagrant.config.chef.provisioning_path, "validation.pem")
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
module Vagrant
|
2
|
+
module Provisioners
|
3
|
+
# This class implements provisioning via chef-solo.
|
4
|
+
class ChefSolo < Chef
|
5
|
+
def prepare
|
6
|
+
share_cookbook_folders
|
7
|
+
end
|
8
|
+
|
9
|
+
def provision!
|
10
|
+
chown_provisioning_folder
|
11
|
+
setup_json
|
12
|
+
setup_solo_config
|
13
|
+
run_chef_solo
|
14
|
+
end
|
15
|
+
|
16
|
+
def share_cookbook_folders
|
17
|
+
host_cookbook_paths.each_with_index do |cookbook, i|
|
18
|
+
Vagrant.config.vm.share_folder("vagrant-chef-solo-#{i}", cookbook_path(i), cookbook)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def setup_solo_config
|
23
|
+
solo_file = <<-solo
|
24
|
+
file_cache_path "#{Vagrant.config.chef.provisioning_path}"
|
25
|
+
cookbook_path #{cookbooks_path}
|
26
|
+
solo
|
27
|
+
|
28
|
+
logger.info "Uploading chef-solo configuration script..."
|
29
|
+
SSH.upload!(StringIO.new(solo_file), File.join(Vagrant.config.chef.provisioning_path, "solo.rb"))
|
30
|
+
end
|
31
|
+
|
32
|
+
def run_chef_solo
|
33
|
+
logger.info "Running chef-solo..."
|
34
|
+
SSH.execute do |ssh|
|
35
|
+
ssh.exec!("cd #{Vagrant.config.chef.provisioning_path} && sudo chef-solo -c solo.rb -j dna.json") do |channel, data, stream|
|
36
|
+
# TODO: Very verbose. It would be easier to save the data and only show it during
|
37
|
+
# an error, or when verbosity level is set high
|
38
|
+
logger.info("#{stream}: #{data}")
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def host_cookbook_paths
|
44
|
+
cookbooks = Vagrant.config.chef.cookbooks_path
|
45
|
+
cookbooks = [cookbooks] unless cookbooks.is_a?(Array)
|
46
|
+
cookbooks.collect! { |cookbook| File.expand_path(cookbook, Env.root_path) }
|
47
|
+
return cookbooks
|
48
|
+
end
|
49
|
+
|
50
|
+
def cookbook_path(i)
|
51
|
+
File.join(Vagrant.config.chef.provisioning_path, "cookbooks-#{i}")
|
52
|
+
end
|
53
|
+
|
54
|
+
def cookbooks_path
|
55
|
+
result = []
|
56
|
+
host_cookbook_paths.each_with_index do |host_path, i|
|
57
|
+
result << cookbook_path(i)
|
58
|
+
end
|
59
|
+
|
60
|
+
# We're lucky that ruby's string and array syntax for strings is the
|
61
|
+
# same as JSON, so we can just convert to JSON here and use that
|
62
|
+
result = result.to_s if result.length == 1
|
63
|
+
result.to_json
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
data/lib/vagrant/ssh.rb
CHANGED
@@ -1,19 +1,22 @@
|
|
1
1
|
module Vagrant
|
2
2
|
class SSH
|
3
|
-
|
3
|
+
include Vagrant::Util
|
4
4
|
|
5
5
|
class << self
|
6
6
|
def connect(opts={})
|
7
7
|
options = {}
|
8
|
-
[:host, :
|
8
|
+
[:host, :username, :private_key_path].each do |param|
|
9
9
|
options[param] = opts[param] || Vagrant.config.ssh.send(param)
|
10
10
|
end
|
11
11
|
|
12
|
-
Kernel.exec "#{
|
12
|
+
Kernel.exec "ssh -p #{port(opts)} -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -i #{options[:private_key_path]} #{options[:username]}@#{options[:host]}".strip
|
13
13
|
end
|
14
14
|
|
15
|
-
def execute
|
16
|
-
Net::SSH.start(Vagrant.config.ssh.host,
|
15
|
+
def execute(opts={})
|
16
|
+
Net::SSH.start(Vagrant.config.ssh.host,
|
17
|
+
Vagrant.config[:ssh][:username],
|
18
|
+
opts.merge( :port => port,
|
19
|
+
:keys => [Vagrant.config.ssh.private_key_path])) do |ssh|
|
17
20
|
yield ssh
|
18
21
|
end
|
19
22
|
end
|
@@ -29,7 +32,7 @@ module Vagrant
|
|
29
32
|
check_thread = Thread.new do
|
30
33
|
begin
|
31
34
|
Thread.current[:result] = false
|
32
|
-
|
35
|
+
execute(:timeout => Vagrant.config.ssh.timeout) do |ssh|
|
33
36
|
Thread.current[:result] = true
|
34
37
|
end
|
35
38
|
rescue Errno::ECONNREFUSED, Net::SSH::Disconnect
|
@@ -39,6 +42,22 @@ module Vagrant
|
|
39
42
|
|
40
43
|
check_thread.join(Vagrant.config.ssh.timeout)
|
41
44
|
return check_thread[:result]
|
45
|
+
rescue Net::SSH::AuthenticationFailed
|
46
|
+
error_and_exit(<<-msg)
|
47
|
+
SSH authentication failed! While this could be due to a variety of reasons,
|
48
|
+
the two most common are: private key path is incorrect or you're using a box
|
49
|
+
which was built for Vagrant 0.1.x.
|
50
|
+
|
51
|
+
Vagrant 0.2.x dropped support for password-based authentication. If you're
|
52
|
+
tring to `vagrant up` a box which does not support Vagrant's private/public
|
53
|
+
keypair, then this error will be raised. To resolve this, read the guide
|
54
|
+
on converting base boxes from password-based to keypairs here:
|
55
|
+
|
56
|
+
http://vagrantup.com/docs/converting_password_to_key_ssh.html
|
57
|
+
|
58
|
+
If the box was built for 0.2.x and contains a custom public key, perhaps
|
59
|
+
the path to the private key is incorrect. Check your `config.ssh.private_key_path`.
|
60
|
+
msg
|
42
61
|
end
|
43
62
|
|
44
63
|
def port(opts={})
|