vagrantup 0.8.7 → 0.8.8

Sign up to get free protection for your applications and to get access to all the features.
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