vagrantup 0.8.7 → 0.8.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (131) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +21 -0
  3. data/CHANGELOG.md +25 -0
  4. data/README.md +38 -8
  5. data/Rakefile +13 -6
  6. data/bin/vagrant +6 -1
  7. data/config/default.rb +2 -2
  8. data/lib/vagrant/action/box/download.rb +14 -2
  9. data/lib/vagrant/action/vm/check_box.rb +8 -1
  10. data/lib/vagrant/action/vm/check_guest_additions.rb +6 -3
  11. data/lib/vagrant/action/vm/share_folders.rb +12 -1
  12. data/lib/vagrant/command/init.rb +1 -1
  13. data/lib/vagrant/downloaders/http.rb +29 -2
  14. data/lib/vagrant/hosts.rb +1 -0
  15. data/lib/vagrant/hosts/bsd.rb +1 -0
  16. data/lib/vagrant/hosts/freebsd.rb +51 -0
  17. data/lib/vagrant/provisioners/chef.rb +6 -5
  18. data/lib/vagrant/provisioners/chef_client.rb +1 -1
  19. data/lib/vagrant/provisioners/chef_solo.rb +13 -4
  20. data/lib/vagrant/ssh.rb +24 -49
  21. data/lib/vagrant/ssh/session.rb +1 -1
  22. data/lib/vagrant/systems/solaris.rb +57 -11
  23. data/lib/vagrant/test_helpers.rb +23 -0
  24. data/lib/vagrant/ui.rb +1 -1
  25. data/lib/vagrant/util.rb +0 -1
  26. data/lib/vagrant/util/file_checksum.rb +38 -0
  27. data/lib/vagrant/util/platform.rb +1 -1
  28. data/lib/vagrant/util/safe_exec.rb +2 -1
  29. data/lib/vagrant/version.rb +1 -1
  30. data/tasks/acceptance.rake +113 -0
  31. data/tasks/bundler.rake +3 -0
  32. data/tasks/test.rake +15 -0
  33. data/templates/commands/init/Vagrantfile.erb +3 -0
  34. data/templates/locales/en.yml +1 -1
  35. data/test/acceptance/base.rb +48 -0
  36. data/test/acceptance/box_test.rb +77 -0
  37. data/test/acceptance/destroy_test.rb +37 -0
  38. data/test/acceptance/halt_test.rb +72 -0
  39. data/test/acceptance/init_test.rb +33 -0
  40. data/test/acceptance/resume_test.rb +17 -0
  41. data/test/acceptance/ssh_test.rb +41 -0
  42. data/test/acceptance/support/config.rb +42 -0
  43. data/test/acceptance/support/isolated_environment.rb +226 -0
  44. data/test/acceptance/support/matchers/have_color.rb +9 -0
  45. data/test/acceptance/support/matchers/match_output.rb +14 -0
  46. data/test/acceptance/support/output.rb +87 -0
  47. data/test/acceptance/support/shared/base_context.rb +65 -0
  48. data/test/acceptance/support/shared/command_examples.rb +33 -0
  49. data/test/acceptance/support/tempdir.rb +34 -0
  50. data/test/acceptance/support/virtualbox.rb +36 -0
  51. data/test/acceptance/suspend_test.rb +56 -0
  52. data/test/acceptance/up_basic_test.rb +58 -0
  53. data/test/acceptance/up_with_box_url.rb +40 -0
  54. data/test/acceptance/vagrant_test.rb +47 -0
  55. data/test/acceptance/version_test.rb +20 -0
  56. data/test/buildbot/README.md +72 -0
  57. data/test/buildbot/buildbot_config/__init__.py +0 -0
  58. data/test/buildbot/buildbot_config/config/__init__.py +0 -0
  59. data/test/buildbot/buildbot_config/config/loader.py +24 -0
  60. data/test/buildbot/buildbot_config/config/master.py +24 -0
  61. data/test/buildbot/buildbot_config/config/slave.py +22 -0
  62. data/test/buildbot/buildbot_config/master/__init__.py +6 -0
  63. data/test/buildbot/buildbot_config/master/builders.py +78 -0
  64. data/test/buildbot/buildbot_config/master/buildsteps.py +100 -0
  65. data/test/buildbot/buildbot_config/master/change_sources.py +8 -0
  66. data/test/buildbot/buildbot_config/master/schedulers.py +32 -0
  67. data/test/buildbot/buildbot_config/master/slaves.py +60 -0
  68. data/test/buildbot/buildbot_config/master/status.py +52 -0
  69. data/test/buildbot/master/Makefile.sample +28 -0
  70. data/test/buildbot/master/buildbot.tac +36 -0
  71. data/test/buildbot/master/master.cfg +67 -0
  72. data/test/buildbot/master/public_html/bg_gradient.jpg +0 -0
  73. data/test/buildbot/master/public_html/default.css +545 -0
  74. data/test/buildbot/master/public_html/favicon.ico +0 -0
  75. data/test/buildbot/master/public_html/robots.txt +10 -0
  76. data/test/buildbot/master/public_html/static/css/bootstrap-1.4.0.min.css +356 -0
  77. data/test/buildbot/master/public_html/static/css/prettify.css +97 -0
  78. data/test/buildbot/master/public_html/static/css/syntax.css +60 -0
  79. data/test/buildbot/master/public_html/static/css/vagrant.base.css +205 -0
  80. data/test/buildbot/master/public_html/static/images/base_box_mac.jpg +0 -0
  81. data/test/buildbot/master/public_html/static/images/getting-started/success.jpg +0 -0
  82. data/test/buildbot/master/public_html/static/images/icons/error.png +0 -0
  83. data/test/buildbot/master/public_html/static/images/vagrant_chilling.png +0 -0
  84. data/test/buildbot/master/public_html/static/images/vagrant_holding.png +0 -0
  85. data/test/buildbot/master/public_html/static/images/vagrant_looking.png +0 -0
  86. data/test/buildbot/master/public_html/static/images/windows/alter_path.jpg +0 -0
  87. data/test/buildbot/master/public_html/static/images/windows/edit_path.jpg +0 -0
  88. data/test/buildbot/master/public_html/static/images/windows/environment_variables_button.jpg +0 -0
  89. data/test/buildbot/master/public_html/static/images/windows/port_and_ppk_path.jpg +0 -0
  90. data/test/buildbot/master/public_html/static/images/windows/ppk_selection.jpg +0 -0
  91. data/test/buildbot/master/public_html/static/images/windows/putty_first_screen.jpg +0 -0
  92. data/test/buildbot/master/public_html/static/images/windows/save_result.jpg +0 -0
  93. data/test/buildbot/master/public_html/static/images/windows/vbox_manage_default_location.jpg +0 -0
  94. data/test/buildbot/master/public_html/static/js/bootstrap-tabs.js +80 -0
  95. data/test/buildbot/master/public_html/static/js/jquery-1.7.min.js +4 -0
  96. data/test/buildbot/master/templates/authfail.html +9 -0
  97. data/test/buildbot/master/templates/build.html +205 -0
  98. data/test/buildbot/master/templates/builder.html +118 -0
  99. data/test/buildbot/master/templates/builders.html +33 -0
  100. data/test/buildbot/master/templates/buildslave.html +72 -0
  101. data/test/buildbot/master/templates/buildslaves.html +70 -0
  102. data/test/buildbot/master/templates/change.html +15 -0
  103. data/test/buildbot/master/templates/layouts/base.html +58 -0
  104. data/test/buildbot/master/templates/macros/box.html +37 -0
  105. data/test/buildbot/master/templates/macros/build_line.html +50 -0
  106. data/test/buildbot/master/templates/macros/change.html +81 -0
  107. data/test/buildbot/master/templates/macros/forms.html +300 -0
  108. data/test/buildbot/master/templates/root.html +42 -0
  109. data/test/buildbot/master/templates/waterfall.html +53 -0
  110. data/test/buildbot/requirements.txt +4 -0
  111. data/test/buildbot/scripts/deploy.sh +38 -0
  112. data/test/buildbot/scripts/setup.sh +107 -0
  113. data/test/buildbot/slave/buildbot.tac +43 -0
  114. data/test/buildbot/slave/info/admin +1 -0
  115. data/test/buildbot/slave/info/host +1 -0
  116. data/test/buildbot/tests/__init__.py +0 -0
  117. data/test/buildbot/tests/master/__init__.py +0 -0
  118. data/test/buildbot/tests/master/test_slaves.py +41 -0
  119. data/test/buildbot/vendor/choices-0.4.0.tar.gz +0 -0
  120. data/test/config/acceptance_boxes.yml +7 -0
  121. data/test/unit/test_helper.rb +4 -0
  122. data/test/unit/vagrant/action/box/download_test.rb +2 -2
  123. data/test/unit/vagrant/action/vm/check_box_test.rb +6 -1
  124. data/test/unit/vagrant/action/vm/share_folders_test.rb +1 -1
  125. data/test/unit/vagrant/command/init_test.rb +10 -0
  126. data/test/unit/vagrant/downloaders/http_test.rb +12 -1
  127. data/test/unit/vagrant/provisioners/chef_test.rb +7 -0
  128. data/test/unit/vagrant/ssh/session_test.rb +2 -2
  129. data/test/unit/vagrant/ssh_test.rb +5 -8
  130. data/vagrant.gemspec +6 -0
  131. metadata +177 -1
@@ -26,7 +26,7 @@ module Vagrant
26
26
  @file_cache_path = "/srv/chef/file_store"
27
27
  @file_backup_path = "/srv/chef/cache"
28
28
  @encrypted_data_bag_secret_key_path = nil
29
- @encrypted_data_bag_secret = "/etc/chef/encrypted_data_bag_secret"
29
+ @encrypted_data_bag_secret = "/tmp/encrypted_data_bag_secret"
30
30
  end
31
31
 
32
32
  def validate(errors)
@@ -36,9 +36,9 @@ module Vagrant
36
36
  attr_reader :data_bags_folders
37
37
 
38
38
  def prepare
39
- @cookbook_folders = expanded_folders(config.cookbooks_path)
40
- @role_folders = expanded_folders(config.roles_path)
41
- @data_bags_folders = expanded_folders(config.data_bags_path)
39
+ @cookbook_folders = expanded_folders(config.cookbooks_path, "cookbooks")
40
+ @role_folders = expanded_folders(config.roles_path, "roles")
41
+ @data_bags_folders = expanded_folders(config.data_bags_path, "data_bags")
42
42
 
43
43
  share_folders("csc", @cookbook_folders)
44
44
  share_folders("csr", @role_folders)
@@ -54,7 +54,7 @@ module Vagrant
54
54
  end
55
55
 
56
56
  # Converts paths to a list of properly expanded paths with types.
57
- def expanded_folders(paths)
57
+ def expanded_folders(paths, appended_folder=nil)
58
58
  return [] if paths.nil?
59
59
 
60
60
  # Convert the path to an array if it is a string or just a single
@@ -77,8 +77,17 @@ module Vagrant
77
77
  # Path already exists on the virtual machine. Expand it
78
78
  # relative to where we're provisioning.
79
79
  remote_path = File.expand_path(path, config.provisioning_path)
80
+
81
+ # Remove drive letter if running on a windows host. This is a bit
82
+ # of a hack but is the most portable way I can think of at the moment
83
+ # to achieve this. Otherwise, Vagrant attempts to share at some crazy
84
+ # path like /home/vagrant/c:/foo/bar
85
+ remote_path = remote_path.gsub(/^[a-zA-Z]:/, "")
80
86
  end
81
87
 
88
+ # If we have specified a folder name to append then append it
89
+ remote_path += "/#{appended_folder}" if appended_folder
90
+
82
91
  # Return the result
83
92
  [type, local_path, remote_path]
84
93
  end
@@ -19,7 +19,6 @@ module Vagrant
19
19
 
20
20
  def initialize(environment)
21
21
  @env = environment
22
- @current_session = nil
23
22
  end
24
23
 
25
24
  # Connects to the environment's virtual machine, replacing the ruby
@@ -53,9 +52,6 @@ module Vagrant
53
52
  command_options << "-o ForwardX11Trusted=yes"
54
53
  end
55
54
 
56
- # Some hackery going on here. On Mac OS X Leopard (10.5), exec fails
57
- # (GH-51). As a workaround, we fork and wait. On all other platforms,
58
- # we simply exec.
59
55
  command = "ssh #{command_options.join(" ")} #{options[:username]}@#{options[:host]}".strip
60
56
  env.logger.info("ssh") { "Invoking SSH: #{command}" }
61
57
  safe_exec(command)
@@ -72,47 +68,22 @@ module Vagrant
72
68
  opts[:forward_agent] = true if env.config.ssh.forward_agent
73
69
  opts[:port] ||= port
74
70
 
75
- # Check if we have a currently open SSH session which has the
76
- # same options, and use that if possible.
77
- #
78
- # NOTE: This is experimental and unstable. Therefore it is disabled
79
- # by default.
80
- session, options = nil
81
- session, options = @current_session if env.config.vagrant.ssh_session_cache
82
-
83
- if session && options == opts
84
- # Verify that the SSH session is still valid
85
- begin
86
- session.exec!("echo foo")
87
- rescue IOError
88
- # Reset the session, we need to reconnect
89
- session = nil
90
- end
91
- end
92
-
93
- if !session || options != opts
94
- env.logger.info("ssh") { "Connecting to SSH: #{env.config.ssh.host} #{opts[:port]}" }
95
-
96
- # The exceptions which are acceptable to retry on during
97
- # attempts to connect to SSH
98
- exceptions = [Errno::ECONNREFUSED, Net::SSH::Disconnect]
99
-
100
- # Connect to SSH and gather the session
101
- session = retryable(:tries => 5, :on => exceptions) do
102
- connection = Net::SSH.start(env.config.ssh.host,
103
- env.config.ssh.username,
104
- opts.merge( :keys => [env.config.ssh.private_key_path],
105
- :keys_only => true,
106
- :user_known_hosts_file => [],
107
- :paranoid => false,
108
- :config => false))
109
- SSH::Session.new(connection, env)
110
- end
111
-
112
- # Save the new session along with the options which created it
113
- @current_session = [session, opts]
114
- else
115
- env.logger.info("ssh") { "Using cached SSH session: #{session}" }
71
+ env.logger.info("ssh") { "Connecting to SSH: #{env.config.ssh.host} #{opts[:port]}" }
72
+
73
+ # The exceptions which are acceptable to retry on during
74
+ # attempts to connect to SSH
75
+ exceptions = [Errno::ECONNREFUSED, Net::SSH::Disconnect]
76
+
77
+ # Connect to SSH and gather the session
78
+ session = retryable(:tries => env.config.ssh.max_tries, :on => exceptions) do
79
+ connection = Net::SSH.start(env.config.ssh.host,
80
+ env.config.ssh.username,
81
+ opts.merge( :keys => [env.config.ssh.private_key_path],
82
+ :keys_only => true,
83
+ :user_known_hosts_file => [],
84
+ :paranoid => false,
85
+ :config => false))
86
+ SSH::Session.new(connection, env)
116
87
  end
117
88
 
118
89
  # Yield our session for executing
@@ -144,15 +115,19 @@ module Vagrant
144
115
 
145
116
  require 'timeout'
146
117
  Timeout.timeout(env.config.ssh.timeout) do
147
- execute(:timeout => env.config.ssh.timeout,
148
- :port => ssh_port) { |ssh| }
118
+ execute(:timeout => env.config.ssh.timeout, :port => ssh_port) do |ssh|
119
+ # We run a basic command to test that the shell is up and
120
+ # ready to receive commands. Only then is our SSH connection
121
+ # truly "up"
122
+ return ssh.exec!("echo hello") == "hello\n"
123
+ end
149
124
  end
150
125
 
151
- true
126
+ false
152
127
  rescue Net::SSH::AuthenticationFailed
153
128
  raise Errors::SSHAuthenticationFailed
154
129
  rescue Timeout::Error, Errno::ECONNREFUSED, Net::SSH::Disconnect,
155
- Errors::SSHConnectionRefused, Net::SSH::AuthenticationFailed
130
+ Errors::SSHConnectionRefused
156
131
  return false
157
132
  end
158
133
 
@@ -61,7 +61,7 @@ module Vagrant
61
61
  # the actual `exec!` implementation, except that this
62
62
  # implementation also reports `:exit_status` to the block if given.
63
63
  def exec!(commands, options=nil, &block)
64
- retryable(:tries => 5, :on => [IOError, Net::SSH::Disconnect], :sleep => 1.0) do
64
+ retryable(:tries => env.config.ssh.max_tries, :on => [IOError, Net::SSH::Disconnect], :sleep => 1.0) do
65
65
  metach = session.open_channel do |ch|
66
66
  ch.exec("#{env.config.ssh.shell} -l") do |ch2, success|
67
67
  # Set the terminal
@@ -15,11 +15,13 @@ module Vagrant
15
15
  attr_accessor :halt_check_interval
16
16
  # This sets the command to use to execute items as a superuser. sudo is default
17
17
  attr_accessor :suexec_cmd
18
+ attr_accessor :device
18
19
 
19
20
  def initialize
20
21
  @halt_timeout = 30
21
22
  @halt_check_interval = 1
22
23
  @suexec_cmd = 'sudo'
24
+ @device = "e1000g"
23
25
  end
24
26
  end
25
27
 
@@ -28,6 +30,33 @@ module Vagrant
28
30
  error_namespace("vagrant.systems.solaris")
29
31
  end
30
32
 
33
+ def prepare_host_only_network(net_options=nil)
34
+ end
35
+
36
+ def enable_host_only_network(net_options)
37
+ device = "#{vm.env.config.solaris.device}#{net_options[:adapter]}"
38
+ su_cmd = vm.env.config.solaris.suexec_cmd
39
+ ifconfig_cmd = "#{su_cmd} /sbin/ifconfig #{device}"
40
+ vm.ssh.execute do |ssh|
41
+ ssh.exec!("#{ifconfig_cmd} plumb")
42
+ ssh.exec!("#{ifconfig_cmd} inet #{net_options[:ip]} netmask #{net_options[:netmask]}")
43
+ ssh.exec!("#{ifconfig_cmd} up")
44
+ ssh.exec!("#{su_cmd} sh -c \"echo '#{net_options[:ip]}' > /etc/hostname.#{device}\"")
45
+ end
46
+ end
47
+
48
+ def change_host_name(name)
49
+ su_cmd = vm.env.config.solaris.suexec_cmd
50
+ vm.ssh.execute do |ssh|
51
+ # Only do this if the hostname is not already set
52
+ if !ssh.test?("#{su_cmd} hostname | grep '#{name}'")
53
+ ssh.exec!("#{su_cmd} sh -c \"echo '#{name}' > /etc/nodename\"")
54
+ ssh.exec!("#{su_cmd} uname -S #{name}")
55
+ end
56
+ end
57
+ end
58
+
59
+
31
60
  # There should be an exception raised if the line
32
61
  #
33
62
  # vagrant::::profiles=Primary Administrator
@@ -36,19 +65,36 @@ module Vagrant
36
65
  def halt
37
66
  vm.env.ui.info I18n.t("vagrant.systems.solaris.attempting_halt")
38
67
  vm.ssh.execute do |ssh|
39
- ssh.exec!("#{vm.env.config.solaris.suexec_cmd} /usr/sbin/poweroff")
40
- end
68
+ # Wait until the VM's state is actually powered off. If this doesn't
69
+ # occur within a reasonable amount of time (15 seconds by default),
70
+ # then simply return and allow Vagrant to kill the machine.
71
+ count = 0
72
+ last_error = nil
73
+ while vm.vm.state != :powered_off
74
+ begin
75
+ ssh.exec!("#{vm.env.config.solaris.suexec_cmd} /usr/sbin/poweroff")
76
+ rescue IOError => e
77
+ # Save the last error; if it's not shutdown in a reasonable amount
78
+ # of attempts we will re-raise the error so it's not hidden for
79
+ # all time
80
+ last_error = e
81
+ end
41
82
 
42
- # Wait until the VM's state is actually powered off. If this doesn't
43
- # occur within a reasonable amount of time (15 seconds by default),
44
- # then simply return and allow Vagrant to kill the machine.
45
- count = 0
46
- while vm.vm.state != :powered_off
47
- count += 1
83
+ count += 1
84
+ if count >= vm.env.config.solaris.halt_timeout
85
+ # Check for last error and re-raise it
86
+ if last_error != nil
87
+ raise last_error
88
+ else
89
+ # Otherwise, just return
90
+ return
91
+ end
92
+ end
48
93
 
49
- return if count >= vm.env.config.solaris.halt_timeout
50
- sleep vm.env.config.solaris.halt_check_interval
51
- end
94
+ # Still opportunities remaining; sleep and loop
95
+ sleep vm.env.config.solaris.halt_check_interval
96
+ end # while
97
+ end # do
52
98
  end
53
99
 
54
100
  def mount_shared_folder(ssh, name, guestpath, owner, group)
@@ -84,6 +84,29 @@ module Vagrant
84
84
  [app, env]
85
85
  end
86
86
 
87
+ # Utility method for capturing output streams.
88
+ # @example Evaluate the output
89
+ # output = capture(:stdout){ env.cli("foo") }
90
+ # assert_equal "bar", output
91
+ # @example Silence the output
92
+ # silence(:stdout){ env.cli("init") }
93
+ # @param [:stdout, :stderr] stream The stream to capture
94
+ # @yieldreturn String
95
+ # @see https://github.com/wycats/thor/blob/master/spec/spec_helper.rb
96
+ def capture(stream)
97
+ begin
98
+ stream = stream.to_s
99
+ eval "$#{stream} = StringIO.new"
100
+ yield
101
+ result = eval("$#{stream}").string
102
+ ensure
103
+ eval("$#{stream} = #{stream.upcase}")
104
+ end
105
+
106
+ result
107
+ end
108
+ alias :silence :capture
109
+
87
110
  #------------------------------------------------------------
88
111
  # Path helpers
89
112
  #------------------------------------------------------------
@@ -10,7 +10,7 @@ module Vagrant
10
10
  end
11
11
 
12
12
  [:warn, :error, :info, :confirm].each do |method|
13
- define_method(method) do |message|
13
+ define_method(method) do |message, *opts|
14
14
  # Log normal console messages
15
15
  env.logger.info("ui") { message }
16
16
  end
@@ -2,7 +2,6 @@ module Vagrant
2
2
  module Util
3
3
  autoload :Busy, 'vagrant/util/busy'
4
4
  autoload :Counter, 'vagrant/util/counter'
5
- autoload :GlobLoader, 'vagrant/util/glob_loader'
6
5
  autoload :HashWithIndifferentAccess, 'vagrant/util/hash_with_indifferent_access'
7
6
  autoload :Platform, 'vagrant/util/platform'
8
7
  autoload :Retryable, 'vagrant/util/retryable'
@@ -0,0 +1,38 @@
1
+ # This is an "interface" that should be implemented by any digest class
2
+ # passed into FileChecksum. Note that this isn't strictly enforced at
3
+ # the moment, and this class isn't directly used. It is merely here for
4
+ # documentation of structure of the class.
5
+ class DigestClass
6
+ def update(string); end
7
+ def hexdigest; end
8
+ end
9
+
10
+ class FileChecksum
11
+ BUFFER_SIZE = 1024
12
+
13
+ # Initializes an object to calculate the checksum of a file. The given
14
+ # ``digest_klass`` should implement the ``DigestClass`` interface. Note
15
+ # that the built-in Ruby digest classes duck type this properly:
16
+ # Digest::MD5, Digest::SHA1, etc.
17
+ def initialize(path, digest_klass)
18
+ @digest_klass = digest_klass
19
+ @path = path
20
+ end
21
+
22
+ # This calculates the checksum of the file and returns it as a
23
+ # string.
24
+ #
25
+ # @return [String]
26
+ def checksum
27
+ digest= @digest_klass.new
28
+
29
+ File.open(@path, "r") do |f|
30
+ while !f.eof
31
+ buf = f.readpartial(BUFFER_SIZE)
32
+ digest.update(buf)
33
+ end
34
+ end
35
+
36
+ return digest.hexdigest
37
+ end
38
+ end
@@ -13,7 +13,7 @@ module Vagrant
13
13
  platform.include?("darwin9")
14
14
  end
15
15
 
16
- [:darwin, :bsd, :linux].each do |type|
16
+ [:darwin, :bsd, :freebsd, :linux].each do |type|
17
17
  define_method("#{type}?") do
18
18
  platform.include?(type.to_s)
19
19
  end
@@ -2,7 +2,7 @@ module Vagrant
2
2
  module Util
3
3
  # This module provies a `safe_exec` method which is a drop-in
4
4
  # replacement for `Kernel.exec` which addresses a specific issue
5
- # which manifests on OS X 10.5 and perhaps other operating systems.
5
+ # which manifests on OS X 10.5 (GH-51) and perhaps other operating systems.
6
6
  # This issue causes `exec` to fail if there is more than one system
7
7
  # thread. In that case, `safe_exec` automatically falls back to
8
8
  # forking.
@@ -14,6 +14,7 @@ module Vagrant
14
14
  rescue_from = []
15
15
  rescue_from << Errno::EOPNOTSUPP if defined?(Errno::EOPNOTSUPP)
16
16
  rescue_from << Errno::E045 if defined?(Errno::E045)
17
+ rescue_from << SystemCallError
17
18
 
18
19
  fork_instead = false
19
20
  begin
@@ -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 = "0.8.7"
5
+ VERSION = "0.8.8"
6
6
  end
@@ -0,0 +1,113 @@
1
+ require 'digest/sha1'
2
+ require 'net/http'
3
+ require 'pathname'
4
+ require 'uri'
5
+ require 'yaml'
6
+
7
+ require 'childprocess'
8
+
9
+ require 'vagrant/util/file_checksum'
10
+
11
+ namespace :acceptance do
12
+ desc "Downloads the boxes required for running the acceptance tests."
13
+ task :boxes, :directory do |t, args|
14
+ # Create the directory where the boxes will be downloaded
15
+ box_dir = Pathname.new(args[:directory] || File.expand_path("../../test/tmp/boxes", __FILE__))
16
+ box_dir.mkpath
17
+ puts "Boxes will be placed in: #{box_dir}"
18
+
19
+ # Load the required boxes
20
+ boxes = YAML.load_file(File.expand_path("../../test/config/acceptance_boxes.yml", __FILE__))
21
+
22
+ boxes.each do |box|
23
+ puts "Box: #{box["name"]}"
24
+ box_file = box_dir.join("#{box["name"]}.box")
25
+ checksum = FileChecksum.new(box_file, Digest::SHA1)
26
+
27
+ # If the box exists, we need to check the checksum and determine if we need
28
+ # to redownload the file.
29
+ if box_file.exist?
30
+ print "Box exists, checking SHA1 sum... "
31
+ if checksum.checksum == box["checksum"]
32
+ print "OK\n"
33
+ next
34
+ else
35
+ print "FAIL\n"
36
+ end
37
+ end
38
+
39
+ # Download the file. Note that this has no error checking and just uses
40
+ # pure net/http. There could be a better way.
41
+ puts "Downloading: #{box["url"]}"
42
+ destination = box_file.open("wb")
43
+ uri = URI.parse(box["url"])
44
+ Net::HTTP.new(uri.host, uri.port).start do |http|
45
+ http.request_get(uri.request_uri) do |response|
46
+ total = response.content_length
47
+ progress = 0
48
+ count = 0
49
+
50
+ response.read_body do |segment|
51
+ # Really elementary progress meter
52
+ progress += segment.length
53
+ count += 1
54
+ puts "Progress: #{(progress.to_f / total.to_f) * 100}%" if count % 300 == 0
55
+
56
+ # Write out to the destination file
57
+ destination.write(segment)
58
+ end
59
+ end
60
+ end
61
+
62
+ destination.close
63
+
64
+ # Check the checksum of the new file to verify that it
65
+ # downloaded properly. This shouldn't happen, but it can!
66
+ if checksum.checksum != box["checksum"]
67
+ puts "Checksum didn't match! Download was corrupt!"
68
+ abort
69
+ end
70
+ end
71
+ end
72
+
73
+ desc "Generates the configuration for acceptance tests from current source."
74
+ task :config, :box_dir do |t, args|
75
+ require File.expand_path("../../lib/vagrant/version", __FILE__)
76
+ require File.expand_path('../../test/acceptance/support/tempdir', __FILE__)
77
+
78
+ # Get the directory for the boxes
79
+ box_dir = Pathname.new(args[:box_dir] || File.expand_path("../../test/tmp/boxes", __FILE__))
80
+
81
+ # Generate the binstubs for the Vagrant binary
82
+ tempdir = Tempdir.new
83
+ process = ChildProcess.build("bundle", "install", "--binstubs", tempdir.path)
84
+ process.io.inherit!
85
+ process.start
86
+ process.poll_for_exit(64000)
87
+ if process.exit_code != 0
88
+ # Bundle install failed...
89
+ puts "Bundle install failed!"
90
+ abort
91
+ end
92
+
93
+ # Generate the actual configuration
94
+ config = {
95
+ "vagrant_path" => File.join(tempdir.path, "vagrant"),
96
+ "vagrant_version" => Vagrant::VERSION,
97
+ "env" => {
98
+ "BUNDLE_GEMFILE" => File.expand_path("../../Gemfile", __FILE__)
99
+ },
100
+ "box_directory" => box_dir.to_s
101
+ }
102
+
103
+ File.open("acceptance_config.yml", "w+") do |f|
104
+ f.write(YAML.dump(config))
105
+ end
106
+
107
+ puts <<-OUTPUT
108
+ Acceptance test configuration is now in this directory in
109
+ "acceptance_config.yml." Set your ACCEPTANCE_CONFIG environmental
110
+ variable to this file and run any of the acceptance tests now.
111
+ OUTPUT
112
+ end
113
+ end