bmabey-vagrant 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +12 -0
- data/Gemfile +17 -0
- data/LICENSE +21 -0
- data/README.md +53 -0
- data/Rakefile +41 -0
- data/VERSION +1 -0
- data/bin/.gitignore +0 -0
- data/bin/vagrant +15 -0
- data/bin/vagrant-box +34 -0
- data/bin/vagrant-down +27 -0
- data/bin/vagrant-halt +28 -0
- data/bin/vagrant-init +27 -0
- data/bin/vagrant-package +29 -0
- data/bin/vagrant-reload +29 -0
- data/bin/vagrant-resume +27 -0
- data/bin/vagrant-ssh +27 -0
- data/bin/vagrant-status +29 -0
- data/bin/vagrant-suspend +27 -0
- data/bin/vagrant-up +29 -0
- data/config/default.rb +26 -0
- data/keys/README.md +10 -0
- data/keys/vagrant +27 -0
- data/keys/vagrant.pub +1 -0
- data/lib/vagrant.rb +19 -0
- data/lib/vagrant/actions/base.rb +118 -0
- data/lib/vagrant/actions/box/add.rb +22 -0
- data/lib/vagrant/actions/box/destroy.rb +14 -0
- data/lib/vagrant/actions/box/download.rb +72 -0
- data/lib/vagrant/actions/box/unpackage.rb +43 -0
- data/lib/vagrant/actions/collection.rb +36 -0
- data/lib/vagrant/actions/runner.rb +132 -0
- data/lib/vagrant/actions/vm/boot.rb +47 -0
- data/lib/vagrant/actions/vm/customize.rb +17 -0
- data/lib/vagrant/actions/vm/destroy.rb +23 -0
- data/lib/vagrant/actions/vm/down.rb +12 -0
- data/lib/vagrant/actions/vm/export.rb +41 -0
- data/lib/vagrant/actions/vm/forward_ports.rb +46 -0
- data/lib/vagrant/actions/vm/halt.rb +14 -0
- data/lib/vagrant/actions/vm/import.rb +18 -0
- data/lib/vagrant/actions/vm/move_hard_drive.rb +51 -0
- data/lib/vagrant/actions/vm/package.rb +65 -0
- data/lib/vagrant/actions/vm/provision.rb +49 -0
- data/lib/vagrant/actions/vm/reload.rb +17 -0
- data/lib/vagrant/actions/vm/resume.rb +16 -0
- data/lib/vagrant/actions/vm/shared_folders.rb +81 -0
- data/lib/vagrant/actions/vm/start.rb +18 -0
- data/lib/vagrant/actions/vm/suspend.rb +16 -0
- data/lib/vagrant/actions/vm/up.rb +40 -0
- data/lib/vagrant/active_list.rb +73 -0
- data/lib/vagrant/box.rb +152 -0
- data/lib/vagrant/busy.rb +73 -0
- data/lib/vagrant/commands.rb +219 -0
- data/lib/vagrant/config.rb +183 -0
- data/lib/vagrant/downloaders/base.rb +16 -0
- data/lib/vagrant/downloaders/file.rb +17 -0
- data/lib/vagrant/downloaders/http.rb +47 -0
- data/lib/vagrant/environment.rb +263 -0
- data/lib/vagrant/provisioners/base.rb +29 -0
- data/lib/vagrant/provisioners/chef.rb +103 -0
- data/lib/vagrant/provisioners/chef_server.rb +84 -0
- data/lib/vagrant/provisioners/chef_solo.rb +97 -0
- data/lib/vagrant/ssh.rb +104 -0
- data/lib/vagrant/util.rb +51 -0
- data/lib/vagrant/util/errors.rb +36 -0
- data/lib/vagrant/util/stacked_proc_runner.rb +35 -0
- data/lib/vagrant/util/template_renderer.rb +83 -0
- data/lib/vagrant/vm.rb +61 -0
- data/templates/Vagrantfile.erb +8 -0
- data/templates/errors.yml +117 -0
- data/test/test_helper.rb +163 -0
- data/test/vagrant/actions/base_test.rb +32 -0
- data/test/vagrant/actions/box/add_test.rb +37 -0
- data/test/vagrant/actions/box/destroy_test.rb +18 -0
- data/test/vagrant/actions/box/download_test.rb +131 -0
- data/test/vagrant/actions/box/unpackage_test.rb +100 -0
- data/test/vagrant/actions/collection_test.rb +110 -0
- data/test/vagrant/actions/runner_test.rb +265 -0
- data/test/vagrant/actions/vm/boot_test.rb +55 -0
- data/test/vagrant/actions/vm/customize_test.rb +16 -0
- data/test/vagrant/actions/vm/destroy_test.rb +36 -0
- data/test/vagrant/actions/vm/down_test.rb +32 -0
- data/test/vagrant/actions/vm/export_test.rb +88 -0
- data/test/vagrant/actions/vm/forward_ports_test.rb +104 -0
- data/test/vagrant/actions/vm/halt_test.rb +27 -0
- data/test/vagrant/actions/vm/import_test.rb +43 -0
- data/test/vagrant/actions/vm/move_hard_drive_test.rb +108 -0
- data/test/vagrant/actions/vm/package_test.rb +181 -0
- data/test/vagrant/actions/vm/provision_test.rb +108 -0
- data/test/vagrant/actions/vm/reload_test.rb +47 -0
- data/test/vagrant/actions/vm/resume_test.rb +27 -0
- data/test/vagrant/actions/vm/shared_folders_test.rb +176 -0
- data/test/vagrant/actions/vm/start_test.rb +36 -0
- data/test/vagrant/actions/vm/suspend_test.rb +27 -0
- data/test/vagrant/actions/vm/up_test.rb +107 -0
- data/test/vagrant/active_list_test.rb +190 -0
- data/test/vagrant/box_test.rb +151 -0
- data/test/vagrant/busy_test.rb +83 -0
- data/test/vagrant/commands_test.rb +307 -0
- data/test/vagrant/config_test.rb +256 -0
- data/test/vagrant/downloaders/base_test.rb +27 -0
- data/test/vagrant/downloaders/file_test.rb +26 -0
- data/test/vagrant/downloaders/http_test.rb +40 -0
- data/test/vagrant/environment_test.rb +607 -0
- data/test/vagrant/provisioners/base_test.rb +33 -0
- data/test/vagrant/provisioners/chef_server_test.rb +187 -0
- data/test/vagrant/provisioners/chef_solo_test.rb +149 -0
- data/test/vagrant/provisioners/chef_test.rb +117 -0
- data/test/vagrant/ssh_test.rb +222 -0
- data/test/vagrant/util/errors_test.rb +57 -0
- data/test/vagrant/util/stacked_proc_runner_test.rb +43 -0
- data/test/vagrant/util/template_renderer_test.rb +138 -0
- data/test/vagrant/util_test.rb +64 -0
- data/test/vagrant/vm_test.rb +114 -0
- data/vagrant.gemspec +216 -0
- metadata +285 -0
@@ -0,0 +1,29 @@
|
|
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
|
+
# The environment which this is being provisioned in
|
11
|
+
attr_reader :env
|
12
|
+
|
13
|
+
def initialize(env)
|
14
|
+
@env = env
|
15
|
+
end
|
16
|
+
|
17
|
+
# This is the method called to "prepare" the provisioner. This is called
|
18
|
+
# before any actions are run by the action runner (see {Vagrant::Actions::Runner}).
|
19
|
+
# This can be used to setup shared folders, forward ports, etc. Whatever is
|
20
|
+
# necessary on a "meta" level.
|
21
|
+
def prepare; end
|
22
|
+
|
23
|
+
# This is the method called to provision the system. This method
|
24
|
+
# is expected to do whatever necessary to provision the system (create files,
|
25
|
+
# SSH, etc.)
|
26
|
+
def provision!; end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,103 @@
|
|
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
|
+
attr_accessor :role_path
|
18
|
+
|
19
|
+
# Shared config
|
20
|
+
attr_accessor :provisioning_path
|
21
|
+
attr_accessor :json
|
22
|
+
|
23
|
+
def initialize
|
24
|
+
@validation_client_name = "chef-validator"
|
25
|
+
@client_key_path = "/etc/chef/client.pem"
|
26
|
+
|
27
|
+
@cookbooks_path = "cookbooks"
|
28
|
+
@provisioning_path = "/tmp/vagrant-chef"
|
29
|
+
@json = {
|
30
|
+
:instance_role => "vagrant",
|
31
|
+
:run_list => ["recipe[vagrant_main]"]
|
32
|
+
}
|
33
|
+
end
|
34
|
+
|
35
|
+
# Returns the run list for the provisioning
|
36
|
+
def run_list
|
37
|
+
json[:run_list]
|
38
|
+
end
|
39
|
+
|
40
|
+
# Sets the run list to the specified value
|
41
|
+
def run_list=(value)
|
42
|
+
json[:run_list] = value
|
43
|
+
end
|
44
|
+
|
45
|
+
# Adds a recipe to the run list
|
46
|
+
def add_recipe(name)
|
47
|
+
name = "recipe[#{name}]" unless name =~ /^recipe\[(.+?)\]$/
|
48
|
+
run_list << name
|
49
|
+
end
|
50
|
+
|
51
|
+
# Adds a role to the run list
|
52
|
+
def add_role(name)
|
53
|
+
name = "role[#{name}]" unless name =~ /^role\[(.+?)\]$/
|
54
|
+
run_list << name
|
55
|
+
end
|
56
|
+
|
57
|
+
def to_json
|
58
|
+
# Overridden so that the 'json' key could be removed, since its just
|
59
|
+
# merged into the config anyways
|
60
|
+
data = instance_variables_hash
|
61
|
+
data.delete(:json)
|
62
|
+
data.to_json
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
# Tell the Vagrant configure class about our custom configuration
|
67
|
+
Config.configures :chef, ChefConfig
|
68
|
+
|
69
|
+
def prepare
|
70
|
+
raise Actions::ActionException.new(:chef_base_invalid_provisioner)
|
71
|
+
end
|
72
|
+
|
73
|
+
def chown_provisioning_folder
|
74
|
+
logger.info "Setting permissions on chef provisioning folder..."
|
75
|
+
env.ssh.execute do |ssh|
|
76
|
+
ssh.exec!("sudo mkdir -p #{env.config.chef.provisioning_path}")
|
77
|
+
ssh.exec!("sudo chown #{env.config.ssh.username} #{env.config.chef.provisioning_path}")
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def setup_json
|
82
|
+
logger.info "Generating chef JSON and uploading..."
|
83
|
+
|
84
|
+
# Set up initial configuration
|
85
|
+
data = {
|
86
|
+
:config => env.config,
|
87
|
+
:directory => env.config.vm.project_directory,
|
88
|
+
}
|
89
|
+
|
90
|
+
# And wrap it under the "vagrant" namespace
|
91
|
+
data = { :vagrant => data }
|
92
|
+
|
93
|
+
# Merge with the "extra data" which isn't put under the
|
94
|
+
# vagrant namespace by default
|
95
|
+
data.merge!(env.config.chef.json)
|
96
|
+
|
97
|
+
json = data.to_json
|
98
|
+
|
99
|
+
env.ssh.upload!(StringIO.new(json), File.join(env.config.chef.provisioning_path, "dna.json"))
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
@@ -0,0 +1,84 @@
|
|
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 env.config.chef.validation_key_path.nil?
|
8
|
+
raise Actions::ActionException.new(:chef_server_validation_key_required)
|
9
|
+
elsif !File.file?(validation_key_path)
|
10
|
+
raise Actions::ActionException.new(:chef_server_validation_key_doesnt_exist)
|
11
|
+
end
|
12
|
+
|
13
|
+
if env.config.chef.chef_server_url.nil?
|
14
|
+
raise Actions::ActionException.new(:chef_server_url_required)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def provision!
|
19
|
+
chown_provisioning_folder
|
20
|
+
create_client_key_folder
|
21
|
+
upload_validation_key
|
22
|
+
setup_json
|
23
|
+
setup_config
|
24
|
+
run_chef_client
|
25
|
+
end
|
26
|
+
|
27
|
+
def create_client_key_folder
|
28
|
+
logger.info "Creating folder to hold client key..."
|
29
|
+
path = Pathname.new(env.config.chef.client_key_path)
|
30
|
+
|
31
|
+
env.ssh.execute do |ssh|
|
32
|
+
ssh.exec!("sudo mkdir -p #{path.dirname}")
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def upload_validation_key
|
37
|
+
logger.info "Uploading chef client validation key..."
|
38
|
+
env.ssh.upload!(validation_key_path, guest_validation_key_path)
|
39
|
+
end
|
40
|
+
|
41
|
+
def setup_config
|
42
|
+
solo_file = <<-solo
|
43
|
+
log_level :info
|
44
|
+
log_location STDOUT
|
45
|
+
ssl_verify_mode :verify_none
|
46
|
+
chef_server_url "#{env.config.chef.chef_server_url}"
|
47
|
+
|
48
|
+
validation_client_name "#{env.config.chef.validation_client_name}"
|
49
|
+
validation_key "#{guest_validation_key_path}"
|
50
|
+
client_key "#{env.config.chef.client_key_path}"
|
51
|
+
|
52
|
+
file_store_path "/srv/chef/file_store"
|
53
|
+
file_cache_path "/srv/chef/cache"
|
54
|
+
|
55
|
+
pid_file "/var/run/chef/chef-client.pid"
|
56
|
+
|
57
|
+
Mixlib::Log::Formatter.show_time = true
|
58
|
+
solo
|
59
|
+
|
60
|
+
logger.info "Uploading chef-client configuration script..."
|
61
|
+
env.ssh.upload!(StringIO.new(solo_file), File.join(env.config.chef.provisioning_path, "client.rb"))
|
62
|
+
end
|
63
|
+
|
64
|
+
def run_chef_client
|
65
|
+
logger.info "Running chef-client..."
|
66
|
+
env.ssh.execute do |ssh|
|
67
|
+
ssh.exec!("cd #{env.config.chef.provisioning_path} && sudo chef-client -c client.rb -j dna.json") do |channel, data, stream|
|
68
|
+
# TODO: Very verbose. It would be easier to save the data and only show it during
|
69
|
+
# an error, or when verbosity level is set high
|
70
|
+
logger.info("#{stream}: #{data}")
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def validation_key_path
|
76
|
+
File.expand_path(env.config.chef.validation_key_path, env.root_path)
|
77
|
+
end
|
78
|
+
|
79
|
+
def guest_validation_key_path
|
80
|
+
File.join(@env.config.chef.provisioning_path, "validation.pem")
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
@@ -0,0 +1,97 @@
|
|
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
|
+
share_role_folder
|
8
|
+
end
|
9
|
+
|
10
|
+
def provision!
|
11
|
+
chown_provisioning_folder
|
12
|
+
setup_json
|
13
|
+
setup_solo_config
|
14
|
+
run_chef_solo
|
15
|
+
end
|
16
|
+
|
17
|
+
def share_cookbook_folders
|
18
|
+
host_cookbook_paths.each_with_index do |cookbook, i|
|
19
|
+
env.config.vm.share_folder("vagrant-chef-solo-#{i}", cookbook_path(i), cookbook)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def share_role_folder
|
24
|
+
env.config.vm.share_folder("vagrant-chef-solo-roles", guest_role_path, host_role_path) if host_role_path
|
25
|
+
end
|
26
|
+
|
27
|
+
def setup_solo_config
|
28
|
+
solo_file = <<-solo
|
29
|
+
file_cache_path "#{env.config.chef.provisioning_path}"
|
30
|
+
cookbook_path #{cookbooks_path}
|
31
|
+
solo
|
32
|
+
solo_file << "role_path #{role_path}" if host_role_path
|
33
|
+
|
34
|
+
logger.info "Uploading chef-solo configuration script..."
|
35
|
+
env.ssh.upload!(StringIO.new(solo_file), File.join(env.config.chef.provisioning_path, "solo.rb"))
|
36
|
+
end
|
37
|
+
|
38
|
+
def run_chef_solo
|
39
|
+
logger.info "Running chef-solo..."
|
40
|
+
env.ssh.execute do |ssh|
|
41
|
+
ssh.exec!("cd #{env.config.chef.provisioning_path} && sudo chef-solo -c solo.rb -j dna.json") do |channel, data, stream|
|
42
|
+
# TODO: Very verbose. It would be easier to save the data and only show it during
|
43
|
+
# an error, or when verbosity level is set high
|
44
|
+
logger.info("#{stream}: #{data}")
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def host_cookbook_paths
|
50
|
+
cookbooks = env.config.chef.cookbooks_path
|
51
|
+
cookbooks = [cookbooks] unless cookbooks.is_a?(Array)
|
52
|
+
cookbooks.collect! { |cookbook| full_env_path(cookbook)}
|
53
|
+
return cookbooks
|
54
|
+
end
|
55
|
+
|
56
|
+
def cookbook_path(i)
|
57
|
+
full_provisioning_path "cookbooks-#{i}"
|
58
|
+
end
|
59
|
+
|
60
|
+
def host_role_path
|
61
|
+
env.config.chef.role_path
|
62
|
+
end
|
63
|
+
|
64
|
+
def role_path
|
65
|
+
guest_role_path.to_json
|
66
|
+
end
|
67
|
+
|
68
|
+
def cookbooks_path
|
69
|
+
result = []
|
70
|
+
host_cookbook_paths.each_with_index do |host_path, i|
|
71
|
+
result << cookbook_path(i)
|
72
|
+
end
|
73
|
+
|
74
|
+
# We're lucky that ruby's string and array syntax for strings is the
|
75
|
+
# same as JSON, so we can just convert to JSON here and use that
|
76
|
+
result = result.to_s if result.length == 1
|
77
|
+
result.to_json
|
78
|
+
end
|
79
|
+
|
80
|
+
private
|
81
|
+
|
82
|
+
def guest_role_path
|
83
|
+
full_provisioning_path "roles"
|
84
|
+
end
|
85
|
+
|
86
|
+
# TODO: Maybe these should be moved up so they can be reused...
|
87
|
+
def full_provisioning_path(relative_path)
|
88
|
+
File.join(env.config.chef.provisioning_path, relative_path)
|
89
|
+
end
|
90
|
+
|
91
|
+
|
92
|
+
def full_env_path(relative_path)
|
93
|
+
File.expand_path(relative_path, env.root_path)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
data/lib/vagrant/ssh.rb
ADDED
@@ -0,0 +1,104 @@
|
|
1
|
+
module Vagrant
|
2
|
+
# Manages SSH access to a specific environment. Allows an environment to
|
3
|
+
# replace the process with SSH itself, run a specific set of commands,
|
4
|
+
# upload files, or even check if a host is up.
|
5
|
+
class SSH
|
6
|
+
include Vagrant::Util
|
7
|
+
|
8
|
+
# Reference back up to the environment which this SSH object belongs
|
9
|
+
# to
|
10
|
+
attr_accessor :env
|
11
|
+
|
12
|
+
def initialize(environment)
|
13
|
+
@env = environment
|
14
|
+
end
|
15
|
+
|
16
|
+
# Connects to the environment's virtual machine, replacing the ruby
|
17
|
+
# process with an SSH process. This method optionally takes a hash
|
18
|
+
# of options which override the configuration values.
|
19
|
+
def connect(opts={})
|
20
|
+
options = {}
|
21
|
+
[:host, :username, :private_key_path].each do |param|
|
22
|
+
options[param] = opts[param] || env.config.ssh.send(param)
|
23
|
+
end
|
24
|
+
|
25
|
+
check_key_permissions(options[:private_key_path])
|
26
|
+
Kernel.exec "ssh -p #{port(opts)} -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -i #{options[:private_key_path]} #{options[:username]}@#{options[:host]}".strip
|
27
|
+
end
|
28
|
+
|
29
|
+
# Opens an SSH connection to this environment's virtual machine and yields
|
30
|
+
# a Net::SSH object which can be used to execute remote commands.
|
31
|
+
def execute(opts={})
|
32
|
+
Net::SSH.start(env.config.ssh.host,
|
33
|
+
env.config[:ssh][:username],
|
34
|
+
opts.merge( :port => port,
|
35
|
+
:keys => [env.config.ssh.private_key_path])) do |ssh|
|
36
|
+
yield ssh
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
# Uploads a file from `from` to `to`. `from` is expected to be a filename
|
41
|
+
# or StringIO, and `to` is expected to be a path. This method simply forwards
|
42
|
+
# the arguments to `Net::SCP#upload!` so view that for more information.
|
43
|
+
def upload!(from, to)
|
44
|
+
execute do |ssh|
|
45
|
+
scp = Net::SCP.new(ssh)
|
46
|
+
scp.upload!(from, to)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
# Checks if this environment's machine is up (i.e. responding to SSH).
|
51
|
+
#
|
52
|
+
# @return [Boolean]
|
53
|
+
def up?
|
54
|
+
check_thread = Thread.new do
|
55
|
+
begin
|
56
|
+
Thread.current[:result] = false
|
57
|
+
execute(:timeout => env.config.ssh.timeout) do |ssh|
|
58
|
+
Thread.current[:result] = true
|
59
|
+
end
|
60
|
+
rescue Errno::ECONNREFUSED, Net::SSH::Disconnect
|
61
|
+
# False, its defaulted above
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
check_thread.join(env.config.ssh.timeout)
|
66
|
+
return check_thread[:result]
|
67
|
+
rescue Net::SSH::AuthenticationFailed
|
68
|
+
error_and_exit(:vm_ssh_auth_failed)
|
69
|
+
end
|
70
|
+
|
71
|
+
# Checks the file permissions for the private key, resetting them
|
72
|
+
# if needed, or on failure erroring.
|
73
|
+
def check_key_permissions(key_path)
|
74
|
+
# TODO: This only works on unix based systems for now. Windows
|
75
|
+
# systems will need to be investigated further.
|
76
|
+
stat = File.stat(key_path)
|
77
|
+
|
78
|
+
if stat.owned? && file_perms(key_path) != "600"
|
79
|
+
logger.info "Permissions on private key incorrect, fixing..."
|
80
|
+
File.chmod(0600, key_path)
|
81
|
+
|
82
|
+
error_and_exit(:ssh_bad_permissions, :key_path => key_path) if file_perms(key_path) != "600"
|
83
|
+
end
|
84
|
+
rescue Errno::EPERM
|
85
|
+
# This shouldn't happen since we verify we own the file, but just
|
86
|
+
# in case.
|
87
|
+
error_and_exit(:ssh_bad_permissions, :key_path => key_path)
|
88
|
+
end
|
89
|
+
|
90
|
+
# Returns the file permissions of a given file. This is fairly unix specific
|
91
|
+
# and probably doesn't belong in this class. Will be refactored out later.
|
92
|
+
def file_perms(path)
|
93
|
+
perms = sprintf("%o", File.stat(path).mode)
|
94
|
+
perms.reverse[0..2].reverse
|
95
|
+
end
|
96
|
+
|
97
|
+
# Returns the port which is either given in the options hash or taken from
|
98
|
+
# the config by finding it in the forwarded ports hash based on the
|
99
|
+
# `config.ssh.forwarded_port_key`
|
100
|
+
def port(opts={})
|
101
|
+
opts[:port] || env.config.vm.forwarded_ports[env.config.ssh.forwarded_port_key][:hostport]
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
data/lib/vagrant/util.rb
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
module Vagrant
|
2
|
+
module Util
|
3
|
+
def self.included(base)
|
4
|
+
base.extend Vagrant::Util
|
5
|
+
end
|
6
|
+
|
7
|
+
def wrap_output
|
8
|
+
puts "====================================================================="
|
9
|
+
yield
|
10
|
+
puts "====================================================================="
|
11
|
+
end
|
12
|
+
|
13
|
+
def error_and_exit(key, data = {})
|
14
|
+
abort <<-error
|
15
|
+
=====================================================================
|
16
|
+
Vagrant experienced an error!
|
17
|
+
|
18
|
+
#{Errors.error_string(key, data).chomp}
|
19
|
+
=====================================================================
|
20
|
+
error
|
21
|
+
end
|
22
|
+
|
23
|
+
def logger
|
24
|
+
Logger.singleton_logger
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
class Logger < ::Logger
|
29
|
+
@@singleton_logger = nil
|
30
|
+
|
31
|
+
class << self
|
32
|
+
def singleton_logger
|
33
|
+
# TODO: Buffer messages until config is loaded, then output them?
|
34
|
+
if Vagrant.config.loaded?
|
35
|
+
@@singleton_logger ||= Vagrant::Logger.new(Vagrant.config.vagrant.log_output)
|
36
|
+
else
|
37
|
+
Vagrant::Logger.new(nil)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def reset_logger!
|
42
|
+
@@singleton_logger = nil
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def format_message(level, time, progname, msg)
|
47
|
+
"[#{level} #{time.strftime('%m-%d-%Y %X')}] Vagrant: #{msg}\n"
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|