vagrantup 0.3.4 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (125) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +2 -2
  3. data/README.md +2 -2
  4. data/Rakefile +1 -1
  5. data/VERSION +1 -1
  6. data/config/default.rb +13 -3
  7. data/lib/vagrant.rb +10 -13
  8. data/lib/vagrant/actions/base.rb +14 -2
  9. data/lib/vagrant/actions/box/download.rb +2 -7
  10. data/lib/vagrant/actions/box/verify.rb +1 -1
  11. data/lib/vagrant/actions/runner.rb +0 -1
  12. data/lib/vagrant/actions/vm/boot.rb +2 -6
  13. data/lib/vagrant/actions/vm/customize.rb +7 -5
  14. data/lib/vagrant/actions/vm/destroy.rb +4 -3
  15. data/lib/vagrant/actions/vm/down.rb +6 -3
  16. data/lib/vagrant/actions/vm/export.rb +2 -4
  17. data/lib/vagrant/actions/vm/forward_ports.rb +77 -16
  18. data/lib/vagrant/actions/vm/halt.rb +10 -2
  19. data/lib/vagrant/actions/vm/import.rb +2 -4
  20. data/lib/vagrant/actions/vm/move_hard_drive.rb +2 -2
  21. data/lib/vagrant/actions/vm/network.rb +120 -0
  22. data/lib/vagrant/actions/vm/package.rb +11 -7
  23. data/lib/vagrant/actions/vm/provision.rb +3 -3
  24. data/lib/vagrant/actions/vm/reload.rb +2 -9
  25. data/lib/vagrant/actions/vm/shared_folders.rb +19 -39
  26. data/lib/vagrant/actions/vm/start.rb +10 -2
  27. data/lib/vagrant/actions/vm/up.rb +5 -6
  28. data/lib/vagrant/active_list.rb +23 -13
  29. data/lib/vagrant/box.rb +2 -2
  30. data/lib/vagrant/busy.rb +3 -3
  31. data/lib/vagrant/command.rb +2 -2
  32. data/lib/vagrant/commands/base.rb +40 -20
  33. data/lib/vagrant/commands/destroy.rb +17 -3
  34. data/lib/vagrant/commands/halt.rb +23 -3
  35. data/lib/vagrant/commands/package.rb +54 -14
  36. data/lib/vagrant/commands/provision.rb +31 -0
  37. data/lib/vagrant/commands/reload.rb +16 -3
  38. data/lib/vagrant/commands/resume.rb +16 -3
  39. data/lib/vagrant/commands/ssh.rb +25 -3
  40. data/lib/vagrant/commands/ssh_config.rb +20 -5
  41. data/lib/vagrant/commands/status.rb +107 -40
  42. data/lib/vagrant/commands/suspend.rb +16 -3
  43. data/lib/vagrant/commands/up.rb +26 -7
  44. data/lib/vagrant/config.rb +82 -12
  45. data/lib/vagrant/downloaders/base.rb +8 -1
  46. data/lib/vagrant/downloaders/http.rb +31 -19
  47. data/lib/vagrant/environment.rb +146 -49
  48. data/lib/vagrant/provisioners/base.rb +19 -5
  49. data/lib/vagrant/provisioners/chef.rb +12 -4
  50. data/lib/vagrant/provisioners/chef_server.rb +13 -6
  51. data/lib/vagrant/provisioners/chef_solo.rb +7 -3
  52. data/lib/vagrant/resource_logger.rb +126 -0
  53. data/lib/vagrant/ssh.rb +109 -8
  54. data/lib/vagrant/systems/base.rb +70 -0
  55. data/lib/vagrant/systems/linux.rb +137 -0
  56. data/lib/vagrant/util.rb +1 -45
  57. data/lib/vagrant/util/error_helper.rb +13 -0
  58. data/lib/vagrant/util/glob_loader.rb +22 -0
  59. data/lib/vagrant/util/output_helper.rb +9 -0
  60. data/lib/vagrant/util/plain_logger.rb +12 -0
  61. data/lib/vagrant/util/platform.rb +7 -2
  62. data/lib/vagrant/util/template_renderer.rb +2 -2
  63. data/lib/vagrant/util/translator.rb +35 -0
  64. data/lib/vagrant/vm.rb +91 -10
  65. data/templates/crontab_entry.erb +1 -0
  66. data/templates/network_entry.erb +8 -0
  67. data/templates/ssh_config.erb +1 -0
  68. data/templates/{errors.yml → strings.yml} +111 -3
  69. data/templates/sync.erb +14 -0
  70. data/test/test_helper.rb +46 -3
  71. data/test/vagrant/actions/box/download_test.rb +0 -17
  72. data/test/vagrant/actions/vm/boot_test.rb +3 -10
  73. data/test/vagrant/actions/vm/customize_test.rb +6 -0
  74. data/test/vagrant/actions/vm/destroy_test.rb +6 -5
  75. data/test/vagrant/actions/vm/down_test.rb +5 -11
  76. data/test/vagrant/actions/vm/export_test.rb +1 -0
  77. data/test/vagrant/actions/vm/forward_ports_test.rb +92 -15
  78. data/test/vagrant/actions/vm/halt_test.rb +36 -4
  79. data/test/vagrant/actions/vm/import_test.rb +2 -0
  80. data/test/vagrant/actions/vm/network_test.rb +237 -0
  81. data/test/vagrant/actions/vm/package_test.rb +35 -5
  82. data/test/vagrant/actions/vm/provision_test.rb +3 -3
  83. data/test/vagrant/actions/vm/reload_test.rb +1 -1
  84. data/test/vagrant/actions/vm/shared_folders_test.rb +41 -74
  85. data/test/vagrant/actions/vm/start_test.rb +41 -3
  86. data/test/vagrant/actions/vm/up_test.rb +10 -21
  87. data/test/vagrant/active_list_test.rb +28 -43
  88. data/test/vagrant/commands/base_test.rb +25 -4
  89. data/test/vagrant/commands/destroy_test.rb +24 -12
  90. data/test/vagrant/commands/halt_test.rb +33 -11
  91. data/test/vagrant/commands/package_test.rb +77 -57
  92. data/test/vagrant/commands/provision_test.rb +50 -0
  93. data/test/vagrant/commands/reload_test.rb +27 -11
  94. data/test/vagrant/commands/resume_test.rb +25 -14
  95. data/test/vagrant/commands/ssh_config_test.rb +40 -17
  96. data/test/vagrant/commands/ssh_test.rb +52 -13
  97. data/test/vagrant/commands/status_test.rb +21 -1
  98. data/test/vagrant/commands/suspend_test.rb +25 -14
  99. data/test/vagrant/commands/up_test.rb +25 -19
  100. data/test/vagrant/config_test.rb +74 -18
  101. data/test/vagrant/downloaders/base_test.rb +2 -1
  102. data/test/vagrant/downloaders/http_test.rb +18 -8
  103. data/test/vagrant/environment_test.rb +245 -77
  104. data/test/vagrant/provisioners/base_test.rb +4 -4
  105. data/test/vagrant/provisioners/chef_server_test.rb +18 -7
  106. data/test/vagrant/provisioners/chef_solo_test.rb +17 -7
  107. data/test/vagrant/provisioners/chef_test.rb +22 -9
  108. data/test/vagrant/resource_logger_test.rb +144 -0
  109. data/test/vagrant/ssh_session_test.rb +46 -0
  110. data/test/vagrant/ssh_test.rb +42 -2
  111. data/test/vagrant/systems/linux_test.rb +174 -0
  112. data/test/vagrant/util/error_helper_test.rb +5 -0
  113. data/test/vagrant/util/output_helper_test.rb +5 -0
  114. data/test/vagrant/util/plain_logger_test.rb +17 -0
  115. data/test/vagrant/util/platform_test.rb +18 -0
  116. data/test/vagrant/util/{errors_test.rb → translator_test.rb} +25 -21
  117. data/test/vagrant/util_test.rb +12 -49
  118. data/test/vagrant/vm_test.rb +133 -11
  119. data/vagrant.gemspec +39 -15
  120. metadata +38 -14
  121. data/lib/vagrant/commands/down.rb +0 -16
  122. data/lib/vagrant/util/errors.rb +0 -36
  123. data/lib/vagrant/util/progress_meter.rb +0 -33
  124. data/test/vagrant/commands/down_test.rb +0 -17
  125. data/test/vagrant/util/progress_meter_test.rb +0 -33
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 75d7f6caf3965877101637e6f2cb3ee6ced49b1e
4
- data.tar.gz: 39079d5d36170a7a7102ba6e4afb2c844f7e96b8
3
+ metadata.gz: e41154f52bf6a4b2430e4a0379724a60e8a9cf1f
4
+ data.tar.gz: 27f8d0113ce763fb341d7c4ae2b8681940975df1
5
5
  SHA512:
6
- metadata.gz: bc84dea264681fd479cf5779eb9b343d5b3bbf923d72d7c41ae865ddd2f4d7aa6cf770278747d170ca514dcd9f6fc4fdc52c480c2ef4a03c58fb4ce8a3b2e77e
7
- data.tar.gz: 7d345a62e190667a22e6d6f15eb14e96df6a8c840955d5383c28482891fb4654c187a62c383711b044c94c5705c0380c3eed3e40dddc80ad1843ad04064689e2
6
+ metadata.gz: 584124eb45e846e4f96b0154fd107b9e85c7d4c14c19df9d8a3c0f072fa38d6c2a8cf671b960827acc918cad7559377f8a0fbaceea0e6670555f7e8e0c175a54
7
+ data.tar.gz: 41f131c34146def153f0945557edb9b443c0e347752f24d5a0d8b8e5f796144ac7b90e3306e7e4ca87fdfdf65a9be043cda26e292b4a475fe723bca96a35a8e3
data/Gemfile CHANGED
@@ -1,4 +1,4 @@
1
- source :gemcutter
1
+ source "http://rubygems.org"
2
2
 
3
3
  # Gems required for the lib to even run
4
4
  gem "virtualbox", :git => "git://github.com/mitchellh/virtualbox.git"
@@ -7,7 +7,6 @@ gem "net-scp", ">= 1.0.2"
7
7
  gem "json", ">= 1.2.4"
8
8
  gem "archive-tar-minitar", "= 0.5.2"
9
9
  gem "mario", "~> 0.0.6"
10
- gem "jeweler", "~> 1.4.0"
11
10
 
12
11
  # Gems required for testing only. To install run
13
12
  # gem bundle test
@@ -15,4 +14,5 @@ group :test do
15
14
  gem "contest", ">= 0.1.2"
16
15
  gem "mocha"
17
16
  gem "ruby-debug", ">= 0.10.3" if RUBY_VERSION < '1.9'
17
+ gem "jeweler", "~> 1.4.0"
18
18
  end
data/README.md CHANGED
@@ -6,7 +6,7 @@
6
6
 
7
7
  Vagrant is a tool for building and distributing virtualized development environments.
8
8
 
9
- By providing automated creation and provisioning of virtual machines using [Sun’s VirtualBox](http://www.virtualbox.org),
9
+ By providing automated creation and provisioning of virtual machines using [Oracle’s VirtualBox](http://www.virtualbox.org),
10
10
  Vagrant provides the tools to create and configure lightweight, reproducible, and portable
11
11
  virtual environments. For more information, see the part of the getting started guide
12
12
  on ”[Why Vagrant?](http://vagrantup.com/docs/getting-started/index.html)”
@@ -48,6 +48,6 @@ To hack on vagrant, you'll need [bundler](http://github.com/carlhuda/bundler) wh
48
48
  be installed with a simple `sudo gem install bundler`. Afterwords, do the following:
49
49
 
50
50
  bundle install
51
- rake
51
+ bundle exec rake
52
52
 
53
53
  This will run the test suite, which should come back all green! Then you're good to go!
data/Rakefile CHANGED
@@ -10,7 +10,7 @@ begin
10
10
  gemspec.homepage = "http://github.com/mitchellh/vagrant"
11
11
  gemspec.authors = ["Mitchell Hashimoto", "John Bender"]
12
12
 
13
- gemspec.add_dependency('virtualbox', '~> 0.6.1')
13
+ gemspec.add_dependency('virtualbox', '~> 0.7.0')
14
14
  gemspec.add_dependency('net-ssh', '>= 2.0.19')
15
15
  gemspec.add_dependency('net-scp', '>= 1.0.2')
16
16
  gemspec.add_dependency('json', '>= 1.2.0')
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.3.4
1
+ 0.4.0
data/config/default.rb CHANGED
@@ -5,22 +5,32 @@ Vagrant::Config.run do |config|
5
5
  config.vagrant.home = "~/.vagrant"
6
6
 
7
7
  config.ssh.username = "vagrant"
8
- config.ssh.password = "vagrant"
9
8
  config.ssh.host = "localhost"
9
+ config.ssh.port = 22
10
10
  config.ssh.forwarded_port_key = "ssh"
11
11
  config.ssh.max_tries = 10
12
12
  config.ssh.timeout = 30
13
13
  config.ssh.private_key_path = File.join(PROJECT_ROOT, 'keys', 'vagrant')
14
14
 
15
+ config.vm.auto_port_range = (2200..2250)
15
16
  config.vm.box_ovf = "box.ovf"
16
17
  config.vm.base_mac = "0800279C2E42"
17
- config.vm.project_directory = "/vagrant"
18
- config.vm.forward_port("ssh", 22, 2222)
18
+ config.vm.forward_port("ssh", 22, 2222, :auto => true)
19
19
  config.vm.disk_image_format = 'VMDK'
20
20
  config.vm.provisioner = nil
21
21
  config.vm.shared_folder_uid = nil
22
22
  config.vm.shared_folder_gid = nil
23
23
  config.vm.boot_mode = "vrdp"
24
+ config.vm.system = :linux
25
+
26
+ # Share the root folder. This can then be overridden by
27
+ # other Vagrantfiles, if they wish.
28
+ config.vm.share_folder("v-root", "/vagrant", ".")
29
+
30
+ # TODO new config class
31
+ config.vm.sync_opts = "-terse -group -owner -batch -silent"
32
+ config.vm.sync_script = "/tmp/sync"
33
+ config.vm.sync_crontab_entry_file = "/tmp/crontab-entry"
24
34
 
25
35
  config.package.name = 'vagrant'
26
36
  config.package.extension = '.box'
data/lib/vagrant.rb CHANGED
@@ -1,19 +1,16 @@
1
- libdir = File.dirname(__FILE__)
2
- PROJECT_ROOT = File.join(libdir, '..') unless defined?(PROJECT_ROOT)
1
+ libdir = File.join(File.dirname(__FILE__), "vagrant")
2
+ PROJECT_ROOT = File.join(libdir, '..', "..") unless defined?(PROJECT_ROOT)
3
3
 
4
- # The libs which must be loaded prior to the rest
5
- %w{tempfile open-uri json pathname logger uri net/http virtualbox net/ssh archive/tar/minitar
4
+ # First, load the various libs which Vagrant requires
5
+ %w{tempfile json pathname logger virtualbox net/ssh archive/tar/minitar
6
6
  net/scp fileutils mario}.each do |lib|
7
7
  require lib
8
8
  end
9
9
 
10
- # The vagrant specific files which must be loaded prior to the rest
11
- %w{vagrant/util vagrant/util/stacked_proc_runner vagrant/util/progress_meter vagrant/actions/base vagrant/downloaders/base vagrant/actions/collection
12
- vagrant/actions/runner vagrant/config vagrant/provisioners/base vagrant/provisioners/chef vagrant/commands/base vagrant/commands/box}.each do |f|
13
- require File.expand_path(f, libdir)
14
- end
10
+ # Then load the glob loader, which will handle loading everything else
11
+ require File.expand_path("util/glob_loader", libdir)
15
12
 
16
- # Glob require the rest
17
- Dir[File.join(libdir, "vagrant", "**", "*.rb")].each do |f|
18
- require File.expand_path(f)
19
- end
13
+ # Load them up
14
+ Vagrant::GlobLoader.glob_require(libdir, %w{util/stacked_proc_runner
15
+ actions/base downloaders/base actions/collection actions/runner config
16
+ provisioners/base provisioners/chef systems/base commands/base commands/box})
@@ -26,14 +26,26 @@ module Vagrant
26
26
  # The {Runner runner} which is executing the action
27
27
  attr_reader :runner
28
28
 
29
+ # Any options which are passed into the initializer as a hash.
30
+ attr_reader :options
31
+
29
32
  # Included so subclasses don't need to include it themselves.
30
33
  include Vagrant::Util
31
34
 
35
+ # A helper method for logging which simply gets the logger from
36
+ # the runner. Since actions tend to log quite a bit, this
37
+ # removes the need to prefix `logger` with `@runner` over and
38
+ # over.
39
+ def logger
40
+ runner.env.logger
41
+ end
42
+
32
43
  # Initialization of the action, passing any arguments which may have
33
44
  # been given to the {Runner runner}. This method can be used by subclasses
34
45
  # to save any of the configuration options which are passed in.
35
- def initialize(runner, *args)
46
+ def initialize(runner, options=nil)
36
47
  @runner = runner
48
+ @options = options || {}
37
49
  end
38
50
 
39
51
  # This method is called once per action, allowing the action
@@ -110,7 +122,7 @@ module Vagrant
110
122
  @key = key
111
123
  @data = data
112
124
 
113
- message = Vagrant::Util::Errors.error_string(key, data)
125
+ message = Vagrant::Util::Translator.t(key, data)
114
126
  super(message)
115
127
  end
116
128
  end
@@ -18,7 +18,7 @@ module Vagrant
18
18
  [Downloaders::HTTP, Downloaders::File].each do |dler|
19
19
  if dler.match?(@runner.uri)
20
20
  logger.info "Downloading via #{dler}..."
21
- @downloader = dler.new
21
+ @downloader = dler.new(@runner.env)
22
22
  end
23
23
  end
24
24
 
@@ -48,15 +48,10 @@ module Vagrant
48
48
 
49
49
  def with_tempfile
50
50
  logger.info "Creating tempfile for storing box file..."
51
- File.open(box_temp_path, file_options) do |tempfile|
51
+ File.open(box_temp_path, Platform.tar_file_options) do |tempfile|
52
52
  yield tempfile
53
53
  end
54
54
  end
55
-
56
- def file_options
57
- # create, write only, fail if the file exists, binary if windows
58
- File::WRONLY|File::EXCL|File::CREAT|(Mario::Platform.windows? ? File::BINARY : 0)
59
- end
60
55
 
61
56
  def box_temp_path
62
57
  File.join(@runner.env.tmp_path, BASENAME + Time.now.to_i.to_s)
@@ -23,7 +23,7 @@ module Vagrant
23
23
  def verify_appliance
24
24
  # We now try to read the applince. If it succeeds, we return true.
25
25
  VirtualBox::Appliance.new(@runner.ovf_file)
26
- rescue VirtualBox::Exceptions::FileErrorException
26
+ rescue Exception
27
27
  raise ActionException.new(:box_verification_failed)
28
28
  end
29
29
  end
@@ -69,7 +69,6 @@ module Vagrant
69
69
  # to execute a single action on an instance. The syntax for executing a
70
70
  # single method on an instance is the same as the {execute!} class method.
71
71
  def execute!(single_action=nil, *args)
72
-
73
72
  if single_action
74
73
  actions.clear
75
74
  add_action(single_action, *args)
@@ -2,10 +2,6 @@ module Vagrant
2
2
  module Actions
3
3
  module VM
4
4
  class Boot < Base
5
- def prepare
6
- @runner.env.config.vm.share_folder("v-root", @runner.env.config.vm.project_directory, @runner.env.root_path)
7
- end
8
-
9
5
  def execute!
10
6
  @runner.invoke_around_callback(:boot) do
11
7
  # Startup the VM
@@ -28,9 +24,9 @@ module Vagrant
28
24
  logger.info "Waiting for VM to boot..."
29
25
 
30
26
  @runner.env.config.ssh.max_tries.to_i.times do |i|
31
- logger.info "Trying to connect (attempt ##{i+1} of #{Vagrant.config[:ssh][:max_tries]})..."
27
+ logger.info "Trying to connect (attempt ##{i+1} of #{@runner.env.config[:ssh][:max_tries]})..."
32
28
 
33
- if @runner.env.ssh.up?
29
+ if @runner.ssh.up?
34
30
  logger.info "VM booted and ready for use!"
35
31
  return true
36
32
  end
@@ -3,13 +3,15 @@ module Vagrant
3
3
  module VM
4
4
  class Customize < Base
5
5
  def execute!
6
- logger.info "Running any VM customizations..."
6
+ if !runner.env.config.vm.proc_stack.empty?
7
+ logger.info "Running any VM customizations..."
7
8
 
8
- # Run the customization procs over the VM
9
- @runner.env.config.vm.run_procs!(@runner.vm)
9
+ # Run the customization procs over the VM
10
+ runner.env.config.vm.run_procs!(@runner.vm)
10
11
 
11
- # Save the vm
12
- @runner.vm.save
12
+ # Save the vm
13
+ runner.vm.save
14
+ end
13
15
  end
14
16
  end
15
17
  end
@@ -5,17 +5,18 @@ module Vagrant
5
5
  def execute!
6
6
  @runner.invoke_around_callback(:destroy) do
7
7
  destroy_vm
8
- depersist
8
+ update_dotfile
9
9
  end
10
10
  end
11
11
 
12
12
  def destroy_vm
13
13
  logger.info "Destroying VM and associated drives..."
14
14
  @runner.vm.destroy(:destroy_medium => :delete)
15
+ @runner.vm = nil
15
16
  end
16
17
 
17
- def depersist
18
- @runner.env.depersist_vm
18
+ def update_dotfile
19
+ @runner.env.update_dotfile
19
20
  end
20
21
  end
21
22
  end
@@ -3,15 +3,18 @@ module Vagrant
3
3
  module VM
4
4
  class Down < Base
5
5
  def prepare
6
- @runner.add_action(Halt) if @runner.vm.running?
6
+ # The true as the 2nd parameter always forces the shutdown so its
7
+ # fast (since we're destroying anyways)
8
+ @runner.add_action(Halt, :force => true) if @runner.vm.running?
9
+ @runner.add_action(Network)
7
10
  @runner.add_action(Destroy)
8
11
  end
9
12
 
10
13
  def after_halt
11
- # This sleep is necessary to wait for the GUI to clean itself up.
14
+ # This sleep is necessary to wait for the VM to clean itself up.
12
15
  # There appears to be nothing in the API that does this "wait"
13
16
  # for us.
14
- Kernel.sleep(1) if @runner.env.config.vm.boot_mode == "gui"
17
+ Kernel.sleep(1)
15
18
  end
16
19
  end
17
20
  end
@@ -2,8 +2,6 @@ module Vagrant
2
2
  module Actions
3
3
  module VM
4
4
  class Export < Base
5
- include Util::ProgressMeter
6
-
7
5
  attr_reader :temp_dir
8
6
 
9
7
  def execute!
@@ -36,10 +34,10 @@ module Vagrant
36
34
  def export
37
35
  logger.info "Exporting VM to #{ovf_path}..."
38
36
  @runner.vm.export(ovf_path) do |progress|
39
- update_progress(progress.percent, 100, false)
37
+ logger.report_progress(progress.percent, 100, false)
40
38
  end
41
39
 
42
- complete_progress
40
+ logger.clear_progress
43
41
  end
44
42
  end
45
43
  end
@@ -3,17 +3,62 @@ module Vagrant
3
3
  module VM
4
4
  class ForwardPorts < Base
5
5
  def prepare
6
- VirtualBox::VM.all.each do |vm|
7
- next if !vm.running? || vm.uuid == @runner.uuid
8
-
9
- vm.forwarded_ports.each do |fp|
10
- @runner.env.config.vm.forwarded_ports.each do |name, options|
11
- if fp.hostport.to_s == options[:hostport].to_s
12
- raise ActionException.new(:vm_port_collision, :name => name, :hostport => fp.hostport.to_s, :guestport => options[:guestport].to_s)
13
- end
6
+ external_collision_check
7
+ end
8
+
9
+ # This method checks for any port collisions with any VMs
10
+ # which are already created (by Vagrant or otherwise).
11
+ # report the collisions detected or will attempt to fix them
12
+ # automatically if the port is configured to do so.
13
+ def external_collision_check
14
+ # Flatten all the already-created forwarded ports into a
15
+ # flat list.
16
+ used_ports = VirtualBox::VM.all.collect do |vm|
17
+ if vm.running? && vm.uuid != runner.uuid
18
+ vm.forwarded_ports.collect do |fp|
19
+ fp.hostport.to_s
14
20
  end
15
21
  end
16
22
  end
23
+
24
+ used_ports.flatten!
25
+ used_ports.uniq!
26
+
27
+ runner.env.config.vm.forwarded_ports.each do |name, options|
28
+ if used_ports.include?(options[:hostport].to_s)
29
+ handle_collision(name, options, used_ports)
30
+ end
31
+ end
32
+ end
33
+
34
+ # Handles any collisions. This method will either attempt to
35
+ # fix the collision automatically or will raise an error if
36
+ # auto fixing is disabled.
37
+ def handle_collision(name, options, used_ports)
38
+ if !options[:auto]
39
+ # Auto fixing is disabled for this port forward, so we
40
+ # must throw an error so the user can fix it.
41
+ raise ActionException.new(:vm_port_collision, :name => name, :hostport => options[:hostport].to_s, :guestport => options[:guestport].to_s, :adapter => options[:adapter])
42
+ end
43
+
44
+ # Get the auto port range and get rid of the used ports and
45
+ # ports which are being used in other forwards so we're just
46
+ # left with available ports.
47
+ range = runner.env.config.vm.auto_port_range.to_a
48
+ range -= runner.env.config.vm.forwarded_ports.collect { |n, o| o[:hostport].to_i }
49
+ range -= used_ports
50
+
51
+ if range.empty?
52
+ raise ActionException.new(:vm_port_auto_empty, :vm_name => @runner.name, :name => name, :options => options)
53
+ end
54
+
55
+ # Set the port up to be the first one and add that port to
56
+ # the used list.
57
+ options[:hostport] = range.shift
58
+ used_ports << options[:hostport]
59
+
60
+ # Notify the user
61
+ logger.info "Fixed port collision: #{name} now on port #{options[:hostport]}"
17
62
  end
18
63
 
19
64
  def execute!
@@ -22,23 +67,39 @@ module Vagrant
22
67
  end
23
68
 
24
69
  def clear
25
- logger.info "Deleting any previously set forwarded ports..."
26
- @runner.vm.forwarded_ports.collect { |p| p.destroy }
70
+ if runner.vm.forwarded_ports.length > 0
71
+ logger.info "Deleting any previously set forwarded ports..."
72
+ fp = runner.vm.forwarded_ports.dup
73
+ fp.collect { |p| p.destroy }
74
+ runner.reload!
75
+ end
27
76
  end
28
77
 
29
78
  def forward_ports
30
79
  logger.info "Forwarding ports..."
31
80
 
32
81
  @runner.env.config.vm.forwarded_ports.each do |name, options|
33
- logger.info "Forwarding \"#{name}\": #{options[:guestport]} => #{options[:hostport]}"
34
- port = VirtualBox::ForwardedPort.new
35
- port.name = name
36
- port.hostport = options[:hostport]
37
- port.guestport = options[:guestport]
38
- @runner.vm.forwarded_ports << port
82
+ adapter = options[:adapter]
83
+
84
+ # Assuming the only reason to establish port forwarding is because the VM is using Virtualbox NAT networking.
85
+ # Host-only or Bridged networking don't require port-forwarding and establishing forwarded ports on these
86
+ # attachment types has uncertain behaviour.
87
+ if @runner.vm.network_adapters[adapter].attachment_type == :nat
88
+ logger.info "Forwarding \"#{name}\": #{options[:guestport]} on adapter \##{adapter+1} => #{options[:hostport]}"
89
+ port = VirtualBox::ForwardedPort.new
90
+ port.name = name
91
+ port.hostport = options[:hostport]
92
+ port.guestport = options[:guestport]
93
+ port.instance = adapter
94
+ @runner.vm.forwarded_ports << port
95
+ else
96
+ logger.info "VirtualBox adapter \##{adapter+1} not configured as \"NAT\"."
97
+ logger.info "Skipped port forwarding \"#{name}\": #{options[:guestport]} on adapter\##{adapter+1} => #{options[:hostport]}"
98
+ end
39
99
  end
40
100
 
41
101
  @runner.vm.save
102
+ @runner.reload!
42
103
  end
43
104
  end
44
105
  end