vagrant 1.0.1 → 1.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. data/CHANGELOG.md +26 -0
  2. data/bin/vagrant +2 -2
  3. data/lib/vagrant/action.rb +1 -0
  4. data/lib/vagrant/action/builtin.rb +1 -0
  5. data/lib/vagrant/action/vm/boot.rb +5 -0
  6. data/lib/vagrant/action/vm/check_port_collisions.rb +5 -1
  7. data/lib/vagrant/action/vm/provision.rb +4 -6
  8. data/lib/vagrant/action/vm/sane_defaults.rb +57 -0
  9. data/lib/vagrant/cli.rb +11 -5
  10. data/lib/vagrant/command/base.rb +28 -18
  11. data/lib/vagrant/command/box_add.rb +3 -0
  12. data/lib/vagrant/command/box_list.rb +4 -1
  13. data/lib/vagrant/command/box_remove.rb +4 -1
  14. data/lib/vagrant/command/box_repackage.rb +4 -1
  15. data/lib/vagrant/command/destroy.rb +5 -2
  16. data/lib/vagrant/command/gem.rb +5 -1
  17. data/lib/vagrant/command/halt.rb +5 -2
  18. data/lib/vagrant/command/init.rb +4 -1
  19. data/lib/vagrant/command/package.rb +4 -1
  20. data/lib/vagrant/command/provision.rb +6 -2
  21. data/lib/vagrant/command/reload.rb +7 -3
  22. data/lib/vagrant/command/resume.rb +5 -2
  23. data/lib/vagrant/command/ssh.rb +5 -2
  24. data/lib/vagrant/command/ssh_config.rb +10 -3
  25. data/lib/vagrant/command/status.rb +5 -2
  26. data/lib/vagrant/command/suspend.rb +5 -2
  27. data/lib/vagrant/command/up.rb +5 -2
  28. data/lib/vagrant/communication/ssh.rb +19 -12
  29. data/lib/vagrant/config/ssh.rb +1 -1
  30. data/lib/vagrant/errors.rb +10 -0
  31. data/lib/vagrant/guest/gentoo.rb +8 -0
  32. data/lib/vagrant/provisioners/chef_solo.rb +16 -0
  33. data/lib/vagrant/ssh.rb +5 -2
  34. data/lib/vagrant/ui.rb +6 -1
  35. data/lib/vagrant/util/is_port_open.rb +38 -0
  36. data/lib/vagrant/util/platform.rb +1 -1
  37. data/lib/vagrant/util/safe_puts.rb +31 -0
  38. data/lib/vagrant/version.rb +1 -1
  39. data/lib/vagrant/vm.rb +2 -2
  40. data/templates/commands/init/Vagrantfile.erb +6 -3
  41. data/templates/locales/en.yml +9 -0
  42. data/templates/provisioners/chef_solo/solo.erb +2 -0
  43. data/test/unit/vagrant/command/base_test.rb +1 -1
  44. data/test/unit/vagrant/util/is_port_open_test.rb +53 -0
  45. data/test/unit_legacy/vagrant/provisioners/chef_solo_test.rb +2 -1
  46. metadata +8 -4
@@ -1,5 +1,31 @@
1
+ ## 1.0.2 (March 25, 2012)
2
+
3
+ - Provisioners will still mount folders and such if `--no-provision` is
4
+ used, so that `vagrant provision` works. [GH-803]
5
+ - Nicer error message if an unsupported SSH key type is used. [GH-805]
6
+ - Gentoo guests can now have their host names changed. [GH-796]
7
+ - Relative paths can be used for the `config.ssh.private_key_path`
8
+ setting. [GH-808]
9
+ - `vagrant ssh` now works on Solaris, where `IdentitiesOnly` was not
10
+ an available option. [GH-820]
11
+ - Output works properly in the face of broken pipes. [GH-819]
12
+ - Enable Host IO Cache on the SATA controller by default.
13
+ - Chef-solo provisioner now supports encrypted data bags. [GH-816]
14
+ - Enable the NAT DNS proxy by default, allowing your DNS to continue
15
+ working when you switch networks. [GH-834]
16
+ - Checking for port forwarding collisions also checks for other applications
17
+ that are potentially listening on that port as well. [GH-821]
18
+ - Multiple VM names can be specified for the various commands now. For
19
+ example: `vagrant up web db service`. [GH-795]
20
+ - More robust error handling if a VM fails to boot. The error message
21
+ is much clearer now. [GH-825]
22
+
1
23
  ## 1.0.1 (March 11, 2012)
2
24
 
25
+ - Installers are now bundled with Ruby 1.9.3p125. Previously they were
26
+ bundled with 1.9.3p0. This actually fixes some IO issues with Windows.
27
+ - Windows installer now outputs a `vagrant` binary that will work in msys
28
+ or Cygwin environments.
3
29
  - Fix crashing issue which manifested itself in multi-VM environments.
4
30
  - Add missing `rubygems` require in `environment.rb` to avoid
5
31
  possible load errors. [GH-781]
@@ -39,8 +39,8 @@ begin
39
39
  logger.debug("Loading environment")
40
40
  env.load!
41
41
 
42
- # Execute the CLI interface
43
- env.cli(ARGV)
42
+ # Execute the CLI interface, and exit with the proper error code
43
+ exit(env.cli(ARGV))
44
44
  rescue Vagrant::Errors::VagrantError => e
45
45
  logger.error("Vagrant experienced an error! Details:")
46
46
  logger.error(e.inspect)
@@ -54,6 +54,7 @@ module Vagrant
54
54
  autoload :ProvisionerCleanup, 'vagrant/action/vm/provisioner_cleanup'
55
55
  autoload :PruneNFSExports, 'vagrant/action/vm/prune_nfs_exports'
56
56
  autoload :Resume, 'vagrant/action/vm/resume'
57
+ autoload :SaneDefaults, 'vagrant/action/vm/sane_defaults'
57
58
  autoload :ShareFolders, 'vagrant/action/vm/share_folders'
58
59
  autoload :SetupPackageFiles, 'vagrant/action/vm/setup_package_files'
59
60
  autoload :Suspend, 'vagrant/action/vm/suspend'
@@ -46,6 +46,7 @@ module Vagrant
46
46
  use VM::HostName
47
47
  use VM::ClearNetworkInterfaces
48
48
  use VM::Network
49
+ use VM::SaneDefaults
49
50
  use VM::Customize
50
51
  use VM::Boot
51
52
  end
@@ -35,6 +35,11 @@ module Vagrant
35
35
  # get shown
36
36
  return true if @env[:interrupted]
37
37
 
38
+ # If the VM is not starting or running, something went wrong
39
+ # and we need to show a useful error.
40
+ state = @env[:vm].state
41
+ raise Errors::VMFailedToRun if state != :starting && state != :running
42
+
38
43
  sleep 2 if !@env["vagrant.test"]
39
44
  end
40
45
 
@@ -1,9 +1,13 @@
1
+ require "vagrant/util/is_port_open"
2
+
1
3
  module Vagrant
2
4
  module Action
3
5
  module VM
4
6
  # Action that checks to make sure there are no forwarded port collisions,
5
7
  # and raises an exception if there is.
6
8
  class CheckPortCollisions
9
+ include Util::IsPortOpen
10
+
7
11
  def initialize(app, env)
8
12
  @app = app
9
13
  end
@@ -29,7 +33,7 @@ module Vagrant
29
33
  hostport = options[:hostport].to_i
30
34
  hostport = current[options[:name]] if current.has_key?(options[:name])
31
35
 
32
- if existing.include?(hostport)
36
+ if existing.include?(hostport) || is_port_open?("localhost", hostport)
33
37
  # We have a collision! Handle it
34
38
  send("handle_#{handler}".to_sym, options, existing)
35
39
  end
@@ -19,12 +19,10 @@ module Vagrant
19
19
  # We set this here so that even if this value is changed in the future,
20
20
  # it stays constant to what we expect here in this moment.
21
21
  enabled = env["provision.enabled"]
22
- if enabled
23
- # Instantiate and prepare the provisioners. Preparation must happen here
24
- # so that shared folders and such can properly take effect.
25
- provisioners = enabled_provisioners
26
- provisioners.map { |p| p.prepare }
27
- end
22
+ # Instantiate and prepare the provisioners. Preparation must happen here
23
+ # so that shared folders and such can properly take effect.
24
+ provisioners = enabled_provisioners
25
+ provisioners.map { |p| p.prepare }
28
26
 
29
27
  @app.call(env)
30
28
 
@@ -0,0 +1,57 @@
1
+ require "log4r"
2
+
3
+ module Vagrant
4
+ module Action
5
+ module VM
6
+ # This middleware enforces some sane defaults on the virtualbox
7
+ # VM which help with performance, stability, and in some cases
8
+ # behavior.
9
+ class SaneDefaults
10
+ def initialize(app, env)
11
+ @logger = Log4r::Logger.new("vagrant::action::vm::sanedefaults")
12
+ @app = app
13
+ end
14
+
15
+ def call(env)
16
+ # Set the env on an instance variable so we can access it in
17
+ # helpers.
18
+ @env = env
19
+
20
+ # Enable the host IO cache on the sata controller. Note that
21
+ # if this fails then its not a big deal, so we don't raise any
22
+ # errors. The Host IO cache vastly improves disk IO performance
23
+ # for VMs.
24
+ command = [
25
+ "storagectl", env[:vm].uuid,
26
+ "--name", "SATA Controller",
27
+ "--hostiocache", "on"
28
+ ]
29
+ attempt_and_log(command, "Enabling the Host I/O cache on the SATA controller...")
30
+
31
+ # Enable the DNS proxy while in NAT mode. This shields the guest
32
+ # VM from external DNS changs on the host machine.
33
+ command = [
34
+ "modifyvm", env[:vm].uuid,
35
+ "--natdnsproxy1", "on"
36
+ ]
37
+ attempt_and_log(command, "Enable the NAT DNS proxy on adapter 1...")
38
+
39
+ @app.call(env)
40
+ end
41
+
42
+ protected
43
+
44
+ # This is just a helper method that executes a single command, logs
45
+ # the given string to the log, and also includes the exit status in
46
+ # the log message.
47
+ #
48
+ # @param [Array] command Command to run
49
+ # @param [String] log Log message to write.
50
+ def attempt_and_log(command, log)
51
+ result = @env[:vm].driver.execute_command(command)
52
+ @logger.info("#{log} (exit status = #{result.exit_code})")
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
@@ -21,21 +21,27 @@ module Vagrant
21
21
  :version => Vagrant::VERSION),
22
22
  :prefix => false)
23
23
 
24
- return
24
+ return 0
25
25
  elsif @main_args.include?("-h") || @main_args.include?("--help")
26
26
  # Help is next in short-circuiting everything. Print
27
27
  # the help and exit.
28
- return help
28
+ help
29
+ return 0
29
30
  end
30
31
 
31
32
  # If we reached this far then we must have a subcommand. If not,
32
33
  # then we also just print the help and exit.
33
34
  command_class = Vagrant.commands.get(@sub_command.to_sym) if @sub_command
34
- return help if !command_class || !@sub_command
35
+ if !command_class || !@sub_command
36
+ help
37
+ return 0
38
+ end
35
39
  @logger.debug("Invoking command class: #{command_class} #{@sub_args.inspect}")
36
40
 
37
- # Initialize and execute the command class.
38
- command_class.new(@sub_args, @env).execute
41
+ # Initialize and execute the command class, returning the exit status.
42
+ result = command_class.new(@sub_args, @env).execute
43
+ result = 0 if !result.is_a?(Fixnum)
44
+ return result
39
45
  end
40
46
 
41
47
  # This prints out the help for the CLI.
@@ -1,5 +1,7 @@
1
1
  require 'log4r'
2
2
 
3
+ require "vagrant/util/safe_puts"
4
+
3
5
  module Vagrant
4
6
  module Command
5
7
  # Base class for any CLI commands.
@@ -7,6 +9,8 @@ module Vagrant
7
9
  # This class provides documentation on the interface as well as helper
8
10
  # functions that a command has.
9
11
  class Base
12
+ include Util::SafePuts
13
+
10
14
  def initialize(argv, env)
11
15
  @argv = argv
12
16
  @env = env
@@ -41,7 +45,7 @@ module Vagrant
41
45
 
42
46
  # Add the help option, which must be on every command.
43
47
  opts.on_tail("-h", "--help", "Print this help") do
44
- puts opts.help
48
+ safe_puts(opts.help)
45
49
  return nil
46
50
  end
47
51
 
@@ -60,32 +64,38 @@ module Vagrant
60
64
  # @param [String] name The name of the VM. Nil if every VM.
61
65
  # @param [Boolean] single_target If true, then an exception will be
62
66
  # raised if more than one target is found.
63
- def with_target_vms(name=nil, options=nil)
67
+ def with_target_vms(names=nil, options=nil)
64
68
  # Using VMs requires a Vagrant environment to be properly setup
65
69
  raise Errors::NoEnvironmentError if !@env.root_path
66
70
 
67
71
  # Setup the options hash
68
72
  options ||= {}
69
73
 
74
+ # Require that names be an array
75
+ names ||= []
76
+ names = [names] if !names.is_a?(Array)
77
+
70
78
  # First determine the proper array of VMs.
71
79
  vms = []
72
- if name
73
- raise Errors::MultiVMEnvironmentRequired if !@env.multivm?
74
-
75
- if name =~ /^\/(.+?)\/$/
76
- # This is a regular expression name, so we convert to a regular
77
- # expression and allow that sort of matching.
78
- regex = Regexp.new($1.to_s)
79
-
80
- @env.vms.each do |name, vm|
81
- vms << vm if name =~ regex
80
+ if names.length > 0
81
+ names.each do |name|
82
+ raise Errors::MultiVMEnvironmentRequired if !@env.multivm?
83
+
84
+ if name =~ /^\/(.+?)\/$/
85
+ # This is a regular expression name, so we convert to a regular
86
+ # expression and allow that sort of matching.
87
+ regex = Regexp.new($1.to_s)
88
+
89
+ @env.vms.each do |name, vm|
90
+ vms << vm if name =~ regex
91
+ end
92
+
93
+ raise Errors::VMNoMatchError if vms.empty?
94
+ else
95
+ # String name, just look for a specific VM
96
+ vms << @env.vms[name.to_sym]
97
+ raise Errors::VMNotFoundError, :name => name if !vms[0]
82
98
  end
83
-
84
- raise Errors::VMNoMatchError if vms.empty?
85
- else
86
- # String name, just look for a specific VM
87
- vms << @env.vms[name.to_sym]
88
- raise Errors::VMNotFoundError, :name => name if !vms[0]
89
99
  end
90
100
  else
91
101
  vms = @env.vms_ordered
@@ -28,6 +28,9 @@ module Vagrant
28
28
  end
29
29
 
30
30
  @env.boxes.add(argv[0], argv[1])
31
+
32
+ # Success, exit status 0
33
+ 0
31
34
  end
32
35
  end
33
36
  end
@@ -19,7 +19,10 @@ module Vagrant
19
19
  return @env.ui.warn(I18n.t("vagrant.commands.box.no_installed_boxes"), :prefix => false)
20
20
  end
21
21
  boxes.each { |b| @env.ui.info(b.name, :prefix => false) }
22
- end
22
+
23
+ # Success, exit status 0
24
+ 0
25
+ end
23
26
  end
24
27
  end
25
28
  end
@@ -18,7 +18,10 @@ module Vagrant
18
18
  b = @env.boxes.find(argv[0])
19
19
  raise Errors::BoxNotFound, :name => argv[0] if !b
20
20
  b.destroy
21
- end
21
+
22
+ # Success, exit status 0
23
+ 0
24
+ end
22
25
  end
23
26
  end
24
27
  end
@@ -18,7 +18,10 @@ module Vagrant
18
18
  b = @env.boxes.find(argv[0])
19
19
  raise Errors::BoxNotFound, :name => argv[0] if !b
20
20
  b.repackage
21
- end
21
+
22
+ # Success, exit status 0
23
+ 0
24
+ end
22
25
  end
23
26
  end
24
27
  end
@@ -20,7 +20,7 @@ module Vagrant
20
20
  return if !argv
21
21
 
22
22
  @logger.debug("'Destroy' each target VM...")
23
- with_target_vms(argv[0], :reverse => true) do |vm|
23
+ with_target_vms(argv, :reverse => true) do |vm|
24
24
  if vm.created?
25
25
  # Boolean whether we should actually go through with the destroy
26
26
  # or not. This is true only if the "--force" flag is set or if the
@@ -55,7 +55,10 @@ module Vagrant
55
55
  vm.ui.info I18n.t("vagrant.commands.common.vm_not_created")
56
56
  end
57
57
  end
58
- end
58
+
59
+ # Success, exit status 0
60
+ 0
61
+ end
59
62
  end
60
63
  end
61
64
  end
@@ -1,9 +1,13 @@
1
1
  require "rubygems"
2
2
  require "rubygems/gem_runner"
3
3
 
4
+ require "vagrant/util/safe_puts"
5
+
4
6
  module Vagrant
5
7
  module Command
6
8
  class Gem < Base
9
+ include Util::SafePuts
10
+
7
11
  def execute
8
12
  # Bundler sets up its own custom gem load paths such that our
9
13
  # own gems are never loaded. Therefore, give an error if a user
@@ -20,7 +24,7 @@ module Vagrant
20
24
  if @argv.empty? || @argv.include?("-h") || @argv.include?("--help")
21
25
  @env.ui.info(I18n.t("vagrant.commands.gem.help_preamble"),
22
26
  :prefix => false)
23
- puts
27
+ safe_puts
24
28
  end
25
29
 
26
30
  # We just proxy the arguments onto a real RubyGems command
@@ -21,7 +21,7 @@ module Vagrant
21
21
  return if !argv
22
22
 
23
23
  @logger.debug("Halt command: #{argv.inspect} #{options.inspect}")
24
- with_target_vms(argv[0]) do |vm|
24
+ with_target_vms(argv) do |vm|
25
25
  if vm.created?
26
26
  @logger.info("Halting #{vm.name}")
27
27
  vm.halt(:force => options[:force])
@@ -30,7 +30,10 @@ module Vagrant
30
30
  vm.ui.info I18n.t("vagrant.commands.common.vm_not_created")
31
31
  end
32
32
  end
33
- end
33
+
34
+ # Success, exit status 0
35
+ 0
36
+ end
34
37
  end
35
38
  end
36
39
  end
@@ -31,7 +31,10 @@ module Vagrant
31
31
 
32
32
  @env.ui.info(I18n.t("vagrant.commands.init.success"),
33
33
  :prefix => false)
34
- end
34
+
35
+ # Success, exit status 0
36
+ 0
37
+ end
35
38
  end
36
39
  end
37
40
  end
@@ -39,7 +39,10 @@ module Vagrant
39
39
  else
40
40
  package_target(argv[0], options)
41
41
  end
42
- end
42
+
43
+ # Success, exit status 0
44
+ 0
45
+ end
43
46
 
44
47
  protected
45
48
 
@@ -16,7 +16,8 @@ module Vagrant
16
16
 
17
17
  # Go over each VM and provision!
18
18
  @logger.debug("'provision' each target VM...")
19
- with_target_vms(argv[0]) do |vm|
19
+ with_target_vms(argv) do |vm|
20
+
20
21
  if vm.created?
21
22
  if vm.state == :running
22
23
  @logger.info("Provisioning: #{vm.name}")
@@ -30,7 +31,10 @@ module Vagrant
30
31
  vm.ui.info I18n.t("vagrant.commands.common.vm_not_created")
31
32
  end
32
33
  end
33
- end
34
+
35
+ # Success, exit status 0
36
+ 0
37
+ end
34
38
  end
35
39
  end
36
40
  end
@@ -9,7 +9,8 @@ module Vagrant
9
9
 
10
10
  def execute
11
11
  options = {}
12
- opts = OptionParser.new do |opts|
12
+
13
+ opts = OptionParser.new do |opts|
13
14
  opts.banner = "Usage: vagrant reload [vm-name]"
14
15
  opts.separator ""
15
16
  build_start_options(opts, options)
@@ -20,7 +21,7 @@ module Vagrant
20
21
  return if !argv
21
22
 
22
23
  @logger.debug("'reload' each target VM...")
23
- with_target_vms(argv[0]) do |vm|
24
+ with_target_vms(argv) do |vm|
24
25
  if vm.created?
25
26
  @logger.info("Reloading: #{vm.name}")
26
27
  vm.reload(options)
@@ -29,7 +30,10 @@ module Vagrant
29
30
  vm.ui.info I18n.t("vagrant.commands.common.vm_not_created")
30
31
  end
31
32
  end
32
- end
33
+
34
+ # Success, exit status 0
35
+ 0
36
+ end
33
37
  end
34
38
  end
35
39
  end
@@ -15,7 +15,7 @@ module Vagrant
15
15
  return if !argv
16
16
 
17
17
  @logger.debug("'resume' each target VM...")
18
- with_target_vms(argv[0]) do |vm|
18
+ with_target_vms(argv) do |vm|
19
19
  if vm.created?
20
20
  @logger.info("Resume: #{vm.name}")
21
21
  vm.resume
@@ -24,7 +24,10 @@ module Vagrant
24
24
  vm.ui.info I18n.t("vagrant.commands.common.vm_not_created")
25
25
  end
26
26
  end
27
- end
27
+
28
+ # Success, exit status 0
29
+ 0
30
+ end
28
31
  end
29
32
  end
30
33
  end
@@ -36,7 +36,7 @@ module Vagrant
36
36
  argv = [] if argv == ssh_args
37
37
 
38
38
  # Execute the actual SSH
39
- with_target_vms(argv[0], :single_target => true) do |vm|
39
+ with_target_vms(argv, :single_target => true) do |vm|
40
40
  # Basic checks that are required for proper SSH
41
41
  raise Errors::VMNotCreatedError if !vm.created?
42
42
  raise Errors::VMInaccessible if !vm.state == :inaccessible
@@ -53,7 +53,10 @@ module Vagrant
53
53
  ssh_connect(vm, opts)
54
54
  end
55
55
  end
56
- end
56
+
57
+ # Success, exit status 0
58
+ 0
59
+ end
57
60
 
58
61
  protected
59
62
 
@@ -1,8 +1,12 @@
1
1
  require 'optparse'
2
2
 
3
+ require "vagrant/util/safe_puts"
4
+
3
5
  module Vagrant
4
6
  module Command
5
7
  class SSHConfig < Base
8
+ include Util::SafePuts
9
+
6
10
  def execute
7
11
  options = {}
8
12
 
@@ -19,7 +23,7 @@ module Vagrant
19
23
  argv = parse_options(opts)
20
24
  return if !argv
21
25
 
22
- with_target_vms(argv[0], :single_target => true) do |vm|
26
+ with_target_vms(argv, :single_target => true) do |vm|
23
27
  raise Errors::VMNotCreatedError if !vm.created?
24
28
  raise Errors::VMInaccessible if !vm.state == :inaccessible
25
29
 
@@ -36,9 +40,12 @@ module Vagrant
36
40
 
37
41
  # Render the template and output directly to STDOUT
38
42
  template = "commands/ssh_config/config"
39
- $stdout.puts(Util::TemplateRenderer.render(template, variables))
43
+ safe_puts(Util::TemplateRenderer.render(template, variables))
40
44
  end
41
- end
45
+
46
+ # Success, exit status 0
47
+ 0
48
+ end
42
49
  end
43
50
  end
44
51
  end
@@ -16,7 +16,7 @@ module Vagrant
16
16
 
17
17
  state = nil
18
18
  results = []
19
- with_target_vms(argv[0]) do |vm|
19
+ with_target_vms(argv) do |vm|
20
20
  state = vm.state.to_s if !state
21
21
  results << "#{vm.name.to_s.ljust(25)}#{vm.state.to_s.gsub("_", " ")}"
22
22
  end
@@ -27,7 +27,10 @@ module Vagrant
27
27
  :states => results.join("\n"),
28
28
  :message => I18n.t("vagrant.commands.status.#{state}")),
29
29
  :prefix => false)
30
- end
30
+
31
+ # Success, exit status 0
32
+ 0
33
+ end
31
34
  end
32
35
  end
33
36
  end
@@ -15,7 +15,7 @@ module Vagrant
15
15
  return if !argv
16
16
 
17
17
  @logger.debug("'suspend' each target VM...")
18
- with_target_vms(argv[0]) do |vm|
18
+ with_target_vms(argv) do |vm|
19
19
  if vm.created?
20
20
  @logger.info("Suspending: #{vm.name}")
21
21
  vm.suspend
@@ -24,7 +24,10 @@ module Vagrant
24
24
  vm.ui.info I18n.t("vagrant.commands.common.vm_not_created")
25
25
  end
26
26
  end
27
- end
27
+
28
+ # Success, exit status 0
29
+ 0
30
+ end
28
31
  end
29
32
  end
30
33
  end
@@ -21,7 +21,7 @@ module Vagrant
21
21
 
22
22
  # Go over each VM and bring it up
23
23
  @logger.debug("'Up' each target VM...")
24
- with_target_vms(argv[0]) do |vm|
24
+ with_target_vms(argv) do |vm|
25
25
  if vm.created?
26
26
  @logger.info("Booting: #{vm.name}")
27
27
  vm.ui.info I18n.t("vagrant.commands.up.vm_created")
@@ -31,7 +31,10 @@ module Vagrant
31
31
  vm.up(options)
32
32
  end
33
33
  end
34
- end
34
+
35
+ # Success, exit status 0
36
+ 0
37
+ end
35
38
  end
36
39
  end
37
40
  end
@@ -129,10 +129,24 @@ module Vagrant
129
129
  @vm.ssh.check_key_permissions(ssh_info[:private_key_path])
130
130
 
131
131
  # Connect to SSH, giving it a few tries
132
- @logger.info("Connecting to SSH: #{ssh_info[:host]}:#{ssh_info[:port]}")
133
- exceptions = [Errno::ECONNREFUSED, Net::SSH::Disconnect]
134
- connection = retryable(:tries => @vm.config.ssh.max_tries, :on => exceptions) do
135
- Net::SSH.start(ssh_info[:host], ssh_info[:username], opts)
132
+ connection = nil
133
+ begin
134
+ @logger.info("Connecting to SSH: #{ssh_info[:host]}:#{ssh_info[:port]}")
135
+ exceptions = [Errno::ECONNREFUSED, Net::SSH::Disconnect]
136
+ connection = retryable(:tries => @vm.config.ssh.max_tries, :on => exceptions) do
137
+ Net::SSH.start(ssh_info[:host], ssh_info[:username], opts)
138
+ end
139
+ rescue Net::SSH::AuthenticationFailed
140
+ # This happens if authentication failed. We wrap the error in our
141
+ # own exception.
142
+ raise Errors::SSHAuthenticationFailed
143
+ rescue Errno::ECONNREFUSED
144
+ # This is raised if we failed to connect the max amount of times
145
+ raise Errors::SSHConnectionRefused
146
+ rescue NotImplementedError
147
+ # This is raised if a private key type that Net-SSH doesn't support
148
+ # is used. Show a nicer error.
149
+ raise Errors::SSHKeyTypeNotSupported
136
150
  end
137
151
 
138
152
  @connection = connection
@@ -145,14 +159,7 @@ module Vagrant
145
159
  # Yield the connection that is ready to be used and
146
160
  # return the value of the block
147
161
  return yield connection if block_given?
148
- rescue Net::SSH::AuthenticationFailed
149
- # This happens if authentication failed. We wrap the error in our
150
- # own exception.
151
- raise Errors::SSHAuthenticationFailed
152
- rescue Errno::ECONNREFUSED
153
- # This is raised if we failed to connect the max amount of times
154
- raise Errors::SSHConnectionRefused
155
- end
162
+ end
156
163
 
157
164
  # Executes the command on an SSH connection within a login shell.
158
165
  def shell_execute(connection, command, sudo=false)
@@ -18,7 +18,7 @@ module Vagrant
18
18
  errors.add(I18n.t("vagrant.config.common.error_empty", :field => field)) if !instance_variable_get("@#{field}".to_sym)
19
19
  end
20
20
 
21
- if private_key_path && !File.file?(private_key_path)
21
+ if private_key_path && !File.file?(File.expand_path(private_key_path, env.root_path))
22
22
  errors.add(I18n.t("vagrant.config.ssh.private_key_missing", :path => private_key_path))
23
23
  end
24
24
  end
@@ -318,6 +318,11 @@ module Vagrant
318
318
  error_key(:ssh_key_bad_permissions)
319
319
  end
320
320
 
321
+ class SSHKeyTypeNotSupported < VagrantError
322
+ status_code(76)
323
+ error_key(:ssh_key_type_not_supported)
324
+ end
325
+
321
326
  class SSHPortNotDetected < VagrantError
322
327
  status_code(50)
323
328
  error_key(:ssh_port_not_detected)
@@ -388,6 +393,11 @@ module Vagrant
388
393
  error_key(:failed_to_boot, "vagrant.actions.vm.boot")
389
394
  end
390
395
 
396
+ class VMFailedToRun < VagrantError
397
+ status_code(77)
398
+ error_key(:failed_to_run, "vagrant.actions.vm.boot")
399
+ end
400
+
391
401
  class VMGuestError < VagrantError
392
402
  status_code(39)
393
403
  error_namespace("vagrant.errors.guest")
@@ -33,6 +33,14 @@ module Vagrant
33
33
  vm.channel.sudo("/etc/init.d/net.eth#{network[:interface]} start")
34
34
  end
35
35
  end
36
+
37
+ def change_host_name(name)
38
+ if !vm.channel.test("sudo hostname --fqdn | grep '#{name}'")
39
+ vm.channel.sudo("echo 'hostname=#{name.split('.')[0]}' > /etc/conf.d/hostname")
40
+ vm.channel.sudo("sed -i 's@^\\(127[.]0[.]1[.]1[[:space:]]\\+\\)@\\1#{name} #{name.split('.')[0]} @' /etc/hosts")
41
+ vm.channel.sudo("hostname #{name.split('.')[0]}")
42
+ end
43
+ end
36
44
  end
37
45
  end
38
46
  end
@@ -15,6 +15,10 @@ module Vagrant
15
15
  attr_accessor :data_bags_path
16
16
  attr_accessor :recipe_url
17
17
  attr_accessor :nfs
18
+ attr_accessor :encrypted_data_bag_secret_key_path
19
+ attr_accessor :encrypted_data_bag_secret
20
+
21
+ def encrypted_data_bag_secret; @encrypted_data_bag_secret || "/tmp/encrypted_data_bag_secret"; end
18
22
 
19
23
  def initialize
20
24
  super
@@ -86,6 +90,7 @@ module Vagrant
86
90
 
87
91
  verify_binary(chef_binary_path("chef-solo"))
88
92
  chown_provisioning_folder
93
+ upload_encrypted_data_bag_secret if config.encrypted_data_bag_secret_key_path
89
94
  setup_json
90
95
  setup_solo_config
91
96
  run_chef_solo
@@ -155,6 +160,12 @@ module Vagrant
155
160
  end
156
161
  end
157
162
 
163
+ def upload_encrypted_data_bag_secret
164
+ env[:ui].info I18n.t("vagrant.provisioners.chef.upload_encrypted_data_bag_secret_key")
165
+ env[:vm].channel.upload(encrypted_data_bag_secret_key_path,
166
+ config.encrypted_data_bag_secret)
167
+ end
168
+
158
169
  def setup_solo_config
159
170
  cookbooks_path = guest_paths(@cookbook_folders)
160
171
  roles_path = guest_paths(@role_folders).first
@@ -167,6 +178,7 @@ module Vagrant
167
178
  :recipe_url => config.recipe_url,
168
179
  :roles_path => roles_path,
169
180
  :data_bags_path => data_bags_path,
181
+ :encrypted_data_bag_secret => config.encrypted_data_bag_secret,
170
182
  })
171
183
  end
172
184
 
@@ -207,6 +219,10 @@ module Vagrant
207
219
  end
208
220
  end
209
221
 
222
+ def encrypted_data_bag_secret_key_path
223
+ File.expand_path(config.encrypted_data_bag_secret_key_path, env[:root_path])
224
+ end
225
+
210
226
  protected
211
227
 
212
228
  # Extracts only the remote paths from a list of folders
@@ -76,8 +76,11 @@ module Vagrant
76
76
 
77
77
  # Command line options
78
78
  command_options = ["-p", options[:port].to_s, "-o", "UserKnownHostsFile=/dev/null",
79
- "-o", "StrictHostKeyChecking=no", "-o", "IdentitiesOnly=yes",
80
- "-o", "LogLevel=ERROR"]
79
+ "-o", "StrictHostKeyChecking=no", "-o", "LogLevel=ERROR"]
80
+
81
+ # Solaris/OpenSolaris/Illumos uses SunSSH which doesn't support the IdentitiesOnly option
82
+ command_options += ["-o", "IdentitiesOnly=yes"] unless Util::Platform.solaris?
83
+
81
84
  command_options += ["-i", options[:private_key_path]] if !plain_mode
82
85
  command_options += ["-o", "ForwardAgent=yes"] if ssh_info[:forward_agent]
83
86
 
@@ -1,5 +1,7 @@
1
1
  require "log4r"
2
2
 
3
+ require "vagrant/util/safe_puts"
4
+
3
5
  module Vagrant
4
6
  module UI
5
7
  # Vagrant UIs handle communication with the outside world (typically
@@ -43,6 +45,8 @@ module Vagrant
43
45
  # This is a UI implementation that outputs the text as is. It
44
46
  # doesn't add any color.
45
47
  class Basic < Interface
48
+ include Util::SafePuts
49
+
46
50
  # Use some light meta-programming to create the various methods to
47
51
  # output text to the UI. These all delegate the real functionality
48
52
  # to `say`.
@@ -112,7 +116,8 @@ module Vagrant
112
116
  channel = type == :error || opts[:channel] == :error ? $stderr : $stdout
113
117
 
114
118
  # Output!
115
- channel.send(printer, format_message(type, message, opts))
119
+ safe_puts(format_message(type, message, opts),
120
+ :io => channel, :printer => printer)
116
121
  end
117
122
 
118
123
  # This is called by `say` to format the message for output.
@@ -0,0 +1,38 @@
1
+ require "socket"
2
+ require "timeout"
3
+
4
+ module Vagrant
5
+ module Util
6
+ # Contains the method {#is_ruby_open?} to check if a port is open
7
+ # (listening) or closed (not in use). This method isn't completely
8
+ # fool-proof, but it works enough of the time to be useful.
9
+ module IsPortOpen
10
+ # Checks if a port is open (listening) on a given host and port.
11
+ #
12
+ # @param [String] host Hostname or IP address.
13
+ # @param [Integer] port Port to check.
14
+ # @return [Boolean] `true` if the port is open (listening), `false`
15
+ # otherwise.
16
+ def is_port_open?(host, port)
17
+ # We wrap this in a timeout because once in awhile the TCPSocket
18
+ # _will_ hang, but this signals that the port is closed.
19
+ Timeout.timeout(1) do
20
+ # Attempt to make a connection
21
+ s = TCPSocket.new(host, port)
22
+
23
+ # A connection was made! Properly clean up the socket, not caring
24
+ # at all if any exception is raised, because we already know the
25
+ # result.
26
+ s.close rescue nil
27
+
28
+ # The port is open if we reached this point, since we were able
29
+ # to connect.
30
+ return true
31
+ end
32
+ rescue Timeout::Error, Errno::ECONNREFUSED, Errno::EHOSTUNREACH
33
+ # Any of the above exceptions signal that the port is closed.
34
+ return false
35
+ end
36
+ end
37
+ end
38
+ end
@@ -14,7 +14,7 @@ module Vagrant
14
14
  platform.include?("darwin9")
15
15
  end
16
16
 
17
- [:darwin, :bsd, :freebsd, :linux].each do |type|
17
+ [:darwin, :bsd, :freebsd, :linux, :solaris].each do |type|
18
18
  define_method("#{type}?") do
19
19
  platform.include?(type.to_s)
20
20
  end
@@ -0,0 +1,31 @@
1
+ module Vagrant
2
+ module Util
3
+ # This module provides a `safe_puts` method which outputs to
4
+ # the given IO object, and rescues any broken pipe errors and
5
+ # ignores them. This is useful in cases where you're outputting
6
+ # to stdout, for example, and the stdout is closed, but you want to
7
+ # keep running.
8
+ module SafePuts
9
+ # Uses `puts` on the given IO object and safely ignores any
10
+ # Errno::EPIPE.
11
+ #
12
+ # @param [String] message Message to output.
13
+ # @param [Hash] opts Options hash.
14
+ def safe_puts(message=nil, opts=nil)
15
+ message ||= ""
16
+ opts = {
17
+ :io => $stdout,
18
+ :printer => :puts
19
+ }.merge(opts || {})
20
+
21
+ begin
22
+ opts[:io].send(opts[:printer], message)
23
+ rescue Errno::EPIPE
24
+ # This is what makes this a `safe` puts.
25
+ return
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
31
+
@@ -2,5 +2,5 @@ module Vagrant
2
2
  # This will always be up to date with the current version of Vagrant,
3
3
  # since it is used to generate the gemspec and is also the source of
4
4
  # the version for `vagrant -v`
5
- VERSION = "1.0.1"
5
+ VERSION = "1.0.2"
6
6
  end
@@ -49,11 +49,11 @@ module Vagrant
49
49
  @logger.info("Loading guest: #{guest}")
50
50
 
51
51
  if guest.is_a?(Class)
52
- raise Errors::VMGuestError, :_key => :invalid_class, :system => guest.to_s if !(guest <= Guest::Base)
52
+ raise Errors::VMGuestError, :_key => :invalid_class, :guest => guest.to_s if !(guest <= Guest::Base)
53
53
  @guest = guest.new(self)
54
54
  elsif guest.is_a?(Symbol)
55
55
  guest_klass = Vagrant.guests.get(guest)
56
- raise Errors::VMGuestError, :_key => :unknown_type, :system => guest.to_s if !guest_klass
56
+ raise Errors::VMGuestError, :_key => :unknown_type, :guest => guest.to_s if !guest_klass
57
57
  @guest = guest_klass.new(self)
58
58
  else
59
59
  raise Errors::VMGuestError, :unspecified
@@ -59,11 +59,14 @@ Vagrant::Config.run do |config|
59
59
  # puppet.manifest_file = "<%= box_name %>.pp"
60
60
  # end
61
61
 
62
- # Enable provisioning with chef solo, specifying a cookbooks path (relative
63
- # to this Vagrantfile), and adding some recipes and/or roles.
62
+ # Enable provisioning with chef solo, specifying a cookbooks path, roles
63
+ # path, and data_bags path (all relative to this Vagrantfile), and adding
64
+ # some recipes and/or roles.
64
65
  #
65
66
  # config.vm.provision :chef_solo do |chef|
66
- # chef.cookbooks_path = "cookbooks"
67
+ # chef.cookbooks_path = "../my-recipes/cookbooks"
68
+ # chef.roles_path = "../my-recipes/roles"
69
+ # chef.data_bags_path = "../my-recipes/data_bags"
67
70
  # chef.add_recipe "mysql"
68
71
  # chef.add_role "web"
69
72
  #
@@ -124,6 +124,10 @@ en:
124
124
  permissions on the following file to 0600 and then try running this command again:
125
125
 
126
126
  %{key_path}
127
+ ssh_key_type_not_supported: |-
128
+ The private key you're attempting to use with this Vagrant box uses
129
+ an unsupported encryption type. The SSH library Vagrant uses does not support
130
+ this key type. Please use `ssh-rsa` or `ssh-dss` instead.
127
131
  ssh_port_not_detected: |-
128
132
  Vagrant couldn't determine the SSH port for your VM! Vagrant attempts to
129
133
  automatically find a forwarded port that matches your `config.ssh.guest_port`
@@ -327,6 +331,11 @@ en:
327
331
  failed_to_boot: |-
328
332
  Failed to connect to VM via SSH. Please verify the VM successfully booted
329
333
  by looking at the VirtualBox GUI.
334
+ failed_to_run: |-
335
+ The VM failed to remain in the "running" state while attempting to boot.
336
+ This is normally caused by a misconfiguration or host system incompatibilities.
337
+ Please open the VirtualBox GUI and attempt to boot the virtual machine
338
+ manually to get a more informative error message.
330
339
  bridged_networking:
331
340
  available: |-
332
341
  Available bridged network interfaces:
@@ -6,6 +6,8 @@ cookbook_path <%= cookbooks_path.inspect %>
6
6
  role_path <%= roles_path.inspect %>
7
7
  log_level <%= log_level.inspect %>
8
8
 
9
+ encrypted_data_bag_secret "<%= encrypted_data_bag_secret %>"
10
+
9
11
  <% if data_bags_path -%>
10
12
  data_bag_path <%= data_bags_path.inspect %>
11
13
  <% end %>
@@ -33,7 +33,7 @@ describe Vagrant::Command::Base do
33
33
  ["-h", "--help"].each do |help_string|
34
34
  it "returns nil and prints the help if '#{help_string}' is given" do
35
35
  instance = klass.new([help_string], nil)
36
- instance.should_receive(:puts)
36
+ instance.should_receive(:safe_puts)
37
37
  instance.parse_options(OptionParser.new).should be_nil
38
38
  end
39
39
  end
@@ -0,0 +1,53 @@
1
+ require File.expand_path("../../../base", __FILE__)
2
+
3
+ require "socket"
4
+
5
+ require "vagrant/util/is_port_open"
6
+
7
+ describe Vagrant::Util::IsPortOpen do
8
+ let(:klass) do
9
+ Class.new do
10
+ extend Vagrant::Util::IsPortOpen
11
+ end
12
+ end
13
+
14
+ let(:open_port) { 52811 }
15
+ let(:closed_port) { 52811 }
16
+
17
+ it "should report open ports" do
18
+ # Start a thread which listens on a port
19
+ thr = Thread.new do
20
+ server = TCPServer.new(open_port)
21
+ Thread.current[:running] = true
22
+
23
+ # Wait until we're told to die
24
+ Thread.current[:die] = false
25
+ while !Thread.current[:die]
26
+ Thread.pass
27
+ end
28
+
29
+ # Die!
30
+ server.close
31
+ end
32
+
33
+ # Wait until the server is running
34
+ while !thr[:running]
35
+ Thread.pass
36
+ end
37
+
38
+ # Verify that we report the port is open
39
+ klass.is_port_open?("localhost", open_port).should be
40
+
41
+ # Kill the thread
42
+ thr[:die] = true
43
+ thr.join
44
+ end
45
+
46
+ it "should report closed ports" do
47
+ # This CAN fail, since port 52811 might actually be in use, but I'm
48
+ # not sure what to do except choose some random port and hope for the
49
+ # best, really.
50
+ klass.is_port_open?("localhost", closed_port).should_not be
51
+ end
52
+ end
53
+
@@ -87,7 +87,8 @@ class ChefSoloProvisionerTest < Test::Unit::TestCase
87
87
  :cookbooks_path => @action.guest_paths(@action.cookbook_folders),
88
88
  :recipe_url => @config.recipe_url,
89
89
  :roles_path => @action.guest_paths(@action.role_folders).first,
90
- :data_bags_path => @action.guest_paths(@action.data_bags_folders).first
90
+ :data_bags_path => @action.guest_paths(@action.data_bags_folders).first,
91
+ :encrypted_data_bag_secret => @config.encrypted_data_bag_secret
91
92
  })
92
93
 
93
94
  @action.setup_solo_config
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: vagrant
3
3
  version: !ruby/object:Gem::Version
4
- hash: 21
4
+ hash: 19
5
5
  prerelease:
6
6
  segments:
7
7
  - 1
8
8
  - 0
9
- - 1
10
- version: 1.0.1
9
+ - 2
10
+ version: 1.0.2
11
11
  platform: ruby
12
12
  authors:
13
13
  - Mitchell Hashimoto
@@ -16,7 +16,7 @@ autorequire:
16
16
  bindir: bin
17
17
  cert_chain: []
18
18
 
19
- date: 2012-03-12 00:00:00 Z
19
+ date: 2012-03-25 00:00:00 Z
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
22
22
  name: archive-tar-minitar
@@ -323,6 +323,7 @@ files:
323
323
  - lib/vagrant/action/vm/provisioner_cleanup.rb
324
324
  - lib/vagrant/action/vm/prune_nfs_exports.rb
325
325
  - lib/vagrant/action/vm/resume.rb
326
+ - lib/vagrant/action/vm/sane_defaults.rb
326
327
  - lib/vagrant/action/vm/setup_package_files.rb
327
328
  - lib/vagrant/action/vm/share_folders.rb
328
329
  - lib/vagrant/action/vm/suspend.rb
@@ -424,11 +425,13 @@ files:
424
425
  - lib/vagrant/util/file_checksum.rb
425
426
  - lib/vagrant/util/file_mode.rb
426
427
  - lib/vagrant/util/hash_with_indifferent_access.rb
428
+ - lib/vagrant/util/is_port_open.rb
427
429
  - lib/vagrant/util/line_ending_helpers.rb
428
430
  - lib/vagrant/util/network_ip.rb
429
431
  - lib/vagrant/util/platform.rb
430
432
  - lib/vagrant/util/retryable.rb
431
433
  - lib/vagrant/util/safe_exec.rb
434
+ - lib/vagrant/util/safe_puts.rb
432
435
  - lib/vagrant/util/stacked_proc_runner.rb
433
436
  - lib/vagrant/util/subprocess.rb
434
437
  - lib/vagrant/util/template_renderer.rb
@@ -587,6 +590,7 @@ files:
587
590
  - test/unit/vagrant/util/ansi_escape_code_remover_test.rb
588
591
  - test/unit/vagrant/util/file_checksum_test.rb
589
592
  - test/unit/vagrant/util/hash_with_indifferent_access_test.rb
593
+ - test/unit/vagrant/util/is_port_open_test.rb
590
594
  - test/unit/vagrant/util/line_endings_helper_test.rb
591
595
  - test/unit/vagrant/util/network_ip_test.rb
592
596
  - test/unit/vagrant/util/retryable_test.rb