From 409be1146f94ea4d6f0847e6402bc8869ea6e8bd Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Fri, 9 Jul 2010 10:14:26 -0700 Subject: [PATCH] Clear forwarded ports middleware --- lib/vagrant/action/builtin.rb | 1 + .../action/vm/clear_forwarded_ports.rb | 39 +++++++ lib/vagrant/action/vm/forward_ports.rb | 41 +------ .../action/vm/forward_ports_helpers.rb | 28 +++++ .../action/vm/clear_forwarded_ports_test.rb | 72 +++++++++++++ .../action/vm/forward_ports_helpers_test.rb | 70 ++++++++++++ test/vagrant/action/vm/forward_ports_test.rb | 102 ------------------ vagrant.gemspec | 8 +- 8 files changed, 221 insertions(+), 140 deletions(-) create mode 100644 lib/vagrant/action/vm/clear_forwarded_ports.rb create mode 100644 lib/vagrant/action/vm/forward_ports_helpers.rb create mode 100644 test/vagrant/action/vm/clear_forwarded_ports_test.rb create mode 100644 test/vagrant/action/vm/forward_ports_helpers_test.rb diff --git a/lib/vagrant/action/builtin.rb b/lib/vagrant/action/builtin.rb index 6992b1f2b..41ee1e70d 100644 --- a/lib/vagrant/action/builtin.rb +++ b/lib/vagrant/action/builtin.rb @@ -16,6 +16,7 @@ module Vagrant # environment. start = Builder.new do use VM::Customize + use VM::ClearForwardedPorts use VM::ForwardPorts use VM::Provision use VM::ClearSharedFolders diff --git a/lib/vagrant/action/vm/clear_forwarded_ports.rb b/lib/vagrant/action/vm/clear_forwarded_ports.rb new file mode 100644 index 000000000..6a985adf7 --- /dev/null +++ b/lib/vagrant/action/vm/clear_forwarded_ports.rb @@ -0,0 +1,39 @@ +require File.join(File.dirname(__FILE__), 'forward_ports_helpers') + +module Vagrant + class Action + module VM + class ClearForwardedPorts + include ForwardPortsHelpers + + def initialize(app, env) + @app = app + @env = env + end + + def call(env) + @env = env + clear + @app.call(env) + end + + def clear + if used_ports.length > 0 + @env.logger.info "Deleting any previously set forwarded ports..." + clear_ports + @env["vm"].reload! + end + end + + # Deletes existing forwarded ports. + def clear_ports + @env["vm"].vm.network_adapters.each do |na| + na.nat_driver.forwarded_ports.dup.each do |fp| + fp.destroy + end + end + end + end + end + end +end diff --git a/lib/vagrant/action/vm/forward_ports.rb b/lib/vagrant/action/vm/forward_ports.rb index 804803bdb..d828cff78 100644 --- a/lib/vagrant/action/vm/forward_ports.rb +++ b/lib/vagrant/action/vm/forward_ports.rb @@ -1,7 +1,11 @@ +require File.join(File.dirname(__FILE__), 'forward_ports_helpers') + module Vagrant class Action module VM class ForwardPorts + include ForwardPortsHelpers + def initialize(app,env) @app = app @env = env @@ -63,20 +67,11 @@ module Vagrant def call(env) @env = env - clear forward_ports @app.call(env) end - def clear - if used_ports.length > 0 - @env.logger.info "Deleting any previously set forwarded ports..." - clear_ports - @env["vm"].reload! - end - end - def forward_ports @env.logger.info "Forwarding ports..." @@ -103,34 +98,6 @@ module Vagrant # General Helpers #-------------------------------------------------------------- - # Returns an array of used ports. This method is implemented - # differently depending on the VirtualBox version, but the - # behavior is the same. - # - # @return [Array] - def used_ports - result = VirtualBox::VM.all.collect do |vm| - if vm.running? && vm.uuid != @env["vm"].uuid - vm.network_adapters.collect do |na| - na.nat_driver.forwarded_ports.collect do |fp| - fp.hostport.to_s - end - end - end - end - - result.flatten.uniq - end - - # Deletes existing forwarded ports. - def clear_ports - @env["vm"].vm.network_adapters.each do |na| - na.nat_driver.forwarded_ports.dup.each do |fp| - fp.destroy - end - end - end - # Forwards a port. def forward_port(name, options) port = VirtualBox::NATForwardedPort.new diff --git a/lib/vagrant/action/vm/forward_ports_helpers.rb b/lib/vagrant/action/vm/forward_ports_helpers.rb new file mode 100644 index 000000000..5204237a0 --- /dev/null +++ b/lib/vagrant/action/vm/forward_ports_helpers.rb @@ -0,0 +1,28 @@ +module Vagrant + class Action + module VM + # Helper methods for forwarding ports. Requires that the environment + # is set to the `@env` instance variable. + module ForwardPortsHelpers + # Returns an array of used ports. This method is implemented + # differently depending on the VirtualBox version, but the + # behavior is the same. + # + # @return [Array] + def used_ports + result = VirtualBox::VM.all.collect do |vm| + if vm.running? && vm.uuid != @env["vm"].uuid + vm.network_adapters.collect do |na| + na.nat_driver.forwarded_ports.collect do |fp| + fp.hostport.to_s + end + end + end + end + + result.flatten.uniq + end + end + end + end +end diff --git a/test/vagrant/action/vm/clear_forwarded_ports_test.rb b/test/vagrant/action/vm/clear_forwarded_ports_test.rb new file mode 100644 index 000000000..96328baf8 --- /dev/null +++ b/test/vagrant/action/vm/clear_forwarded_ports_test.rb @@ -0,0 +1,72 @@ +require File.join(File.dirname(__FILE__), '..', '..', '..', 'test_helper') + +class ClearForwardedPortsVMActionTest < Test::Unit::TestCase + setup do + @klass = Vagrant::Action::VM::ClearForwardedPorts + @app, @env = mock_action_data + + @vm = mock("vm") + @vm.stubs(:name).returns("foo") + @env["vm"] = @vm + + @instance = @klass.new(@app, @env) + end + + context "calling" do + should "call the proper methods and continue chain" do + seq = sequence('seq') + @instance.expects(:clear).in_sequence(seq) + @app.expects(:call).with(@env).in_sequence(seq) + @instance.call(@env) + end + end + + context "clearing forwarded ports" do + setup do + @instance.stubs(:used_ports).returns([:a]) + @instance.stubs(:clear_ports) + end + + should "call destroy on all forwarded ports" do + @instance.expects(:clear_ports).once + @vm.expects(:reload!) + @instance.clear + end + + should "do nothing if there are no forwarded ports" do + @instance.stubs(:used_ports).returns([]) + @vm.expects(:reload!).never + @instance.clear + end + end + + context "clearing ports" do + def mock_fp + fp = mock("fp") + fp.expects(:destroy).once + fp + end + + setup do + VirtualBox.stubs(:version).returns("3.2.8") + @adapters = [] + @internal_vm = mock("internal_vm") + @internal_vm.stubs(:network_adapters).returns(@adapters) + @vm.stubs(:vm).returns(@internal_vm) + end + + def mock_adapter + na = mock("adapter") + engine = mock("engine") + engine.stubs(:forwarded_ports).returns([mock_fp]) + na.stubs(:nat_driver).returns(engine) + na + end + + should "destroy each forwarded port" do + @adapters << mock_adapter + @adapters << mock_adapter + @instance.clear_ports + end + end +end diff --git a/test/vagrant/action/vm/forward_ports_helpers_test.rb b/test/vagrant/action/vm/forward_ports_helpers_test.rb new file mode 100644 index 000000000..bfa26036a --- /dev/null +++ b/test/vagrant/action/vm/forward_ports_helpers_test.rb @@ -0,0 +1,70 @@ +require File.join(File.dirname(__FILE__), '..', '..', '..', 'test_helper') + +class ForwardPortsHelpersVMActionTest < Test::Unit::TestCase + setup do + @klass = Class.new do + def initialize(env); @env = env; end + end + + @klass.send(:include, Vagrant::Action::VM::ForwardPortsHelpers) + @app, @env = mock_action_data + + @vm = mock("vm") + @vm.stubs(:name).returns("foo") + @env["vm"] = @vm + + @instance = @klass.new(@env) + end + + context "getting list of used ports" do + setup do + @vms = [] + VirtualBox::VM.stubs(:all).returns(@vms) + VirtualBox.stubs(:version).returns("3.1.0") + @vm.stubs(:uuid).returns(:bar) + end + + def mock_vm(options={}) + options = { + :running? => true, + :uuid => :foo + }.merge(options) + + vm = mock("vm") + options.each do |k,v| + vm.stubs(k).returns(v) + end + + vm + end + + def mock_fp(hostport) + fp = mock("fp") + fp.stubs(:hostport).returns(hostport.to_s) + fp + end + + should "ignore VMs which aren't running" do + @vms << mock_vm(:running? => false) + @vms[0].expects(:forwarded_ports).never + @instance.used_ports + end + + should "ignore VMs of the same uuid" do + @vms << mock_vm(:uuid => @vm.uuid) + @vms[0].expects(:forwarded_ports).never + @instance.used_ports + end + + should "return the forwarded ports for VB 3.2.x" do + VirtualBox.stubs(:version).returns("3.2.4") + fps = [mock_fp(2222), mock_fp(80)] + na = mock("na") + ne = mock("ne") + na.stubs(:nat_driver).returns(ne) + ne.stubs(:forwarded_ports).returns(fps) + @vms << mock_vm(:network_adapters => [na]) + assert_equal %W[2222 80], @instance.used_ports + end + end +end diff --git a/test/vagrant/action/vm/forward_ports_test.rb b/test/vagrant/action/vm/forward_ports_test.rb index 94490517d..429623ac0 100644 --- a/test/vagrant/action/vm/forward_ports_test.rb +++ b/test/vagrant/action/vm/forward_ports_test.rb @@ -97,7 +97,6 @@ class ForwardPortsVMActionTest < Test::Unit::TestCase context "calling" do should "clear all previous ports and forward new ports" do exec_seq = sequence("exec_seq") - @instance.expects(:clear).once.in_sequence(exec_seq) @instance.expects(:forward_ports).once.in_sequence(exec_seq) @app.expects(:call).once.with(@env).in_sequence(exec_seq) @instance.call(@env) @@ -135,107 +134,6 @@ class ForwardPortsVMActionTest < Test::Unit::TestCase end end - context "clearing forwarded ports" do - setup do - @instance.stubs(:used_ports).returns([:a]) - @instance.stubs(:clear_ports) - end - - should "call destroy on all forwarded ports" do - @instance.expects(:clear_ports).once - @vm.expects(:reload!) - @instance.clear - end - - should "do nothing if there are no forwarded ports" do - @instance.stubs(:used_ports).returns([]) - @vm.expects(:reload!).never - @instance.clear - end - end - - context "getting list of used ports" do - setup do - @vms = [] - VirtualBox::VM.stubs(:all).returns(@vms) - VirtualBox.stubs(:version).returns("3.1.0") - @vm.stubs(:uuid).returns(:bar) - end - - def mock_vm(options={}) - options = { - :running? => true, - :uuid => :foo - }.merge(options) - - vm = mock("vm") - options.each do |k,v| - vm.stubs(k).returns(v) - end - - vm - end - - def mock_fp(hostport) - fp = mock("fp") - fp.stubs(:hostport).returns(hostport.to_s) - fp - end - - should "ignore VMs which aren't running" do - @vms << mock_vm(:running? => false) - @vms[0].expects(:forwarded_ports).never - @instance.used_ports - end - - should "ignore VMs of the same uuid" do - @vms << mock_vm(:uuid => @vm.uuid) - @vms[0].expects(:forwarded_ports).never - @instance.used_ports - end - - should "return the forwarded ports for VB 3.2.x" do - VirtualBox.stubs(:version).returns("3.2.4") - fps = [mock_fp(2222), mock_fp(80)] - na = mock("na") - ne = mock("ne") - na.stubs(:nat_driver).returns(ne) - ne.stubs(:forwarded_ports).returns(fps) - @vms << mock_vm(:network_adapters => [na]) - assert_equal %W[2222 80], @instance.used_ports - end - end - - context "clearing ports" do - def mock_fp - fp = mock("fp") - fp.expects(:destroy).once - fp - end - - setup do - VirtualBox.stubs(:version).returns("3.2.8") - @adapters = [] - @internal_vm = mock("internal_vm") - @internal_vm.stubs(:network_adapters).returns(@adapters) - @vm.stubs(:vm).returns(@internal_vm) - end - - def mock_adapter - na = mock("adapter") - engine = mock("engine") - engine.stubs(:forwarded_ports).returns([mock_fp]) - na.stubs(:nat_driver).returns(engine) - na - end - - should "destroy each forwarded port" do - @adapters << mock_adapter - @adapters << mock_adapter - @instance.clear_ports - end - end - context "forwarding ports implementation" do setup do VirtualBox.stubs(:version).returns("3.2.8") diff --git a/vagrant.gemspec b/vagrant.gemspec index 19da757dd..27ba07434 100644 --- a/vagrant.gemspec +++ b/vagrant.gemspec @@ -9,7 +9,7 @@ Gem::Specification.new do |s| s.required_rubygems_version = Gem::Requirement.new("> 1.3.1") if s.respond_to? :required_rubygems_version= s.authors = ["Mitchell Hashimoto", "John Bender"] - s.date = %q{2010-07-08} + s.date = %q{2010-07-09} s.default_executable = %q{vagrant} s.description = %q{Vagrant is a tool for building and distributing virtualized development environments.} s.email = ["mitchell.hashimoto@gmail.com", "john.m.bender@gmail.com"] @@ -46,12 +46,14 @@ Gem::Specification.new do |s| "lib/vagrant/action/exception_catcher.rb", "lib/vagrant/action/vm/boot.rb", "lib/vagrant/action/vm/check_guest_additions.rb", + "lib/vagrant/action/vm/clear_forwarded_ports.rb", "lib/vagrant/action/vm/clear_shared_folders.rb", "lib/vagrant/action/vm/customize.rb", "lib/vagrant/action/vm/destroy.rb", "lib/vagrant/action/vm/destroy_unused_network_interfaces.rb", "lib/vagrant/action/vm/export.rb", "lib/vagrant/action/vm/forward_ports.rb", + "lib/vagrant/action/vm/forward_ports_helpers.rb", "lib/vagrant/action/vm/halt.rb", "lib/vagrant/action/vm/import.rb", "lib/vagrant/action/vm/match_mac_address.rb", @@ -126,11 +128,13 @@ Gem::Specification.new do |s| "test/vagrant/action/exception_catcher_test.rb", "test/vagrant/action/vm/boot_test.rb", "test/vagrant/action/vm/check_guest_additions_test.rb", + "test/vagrant/action/vm/clear_forwarded_ports_test.rb", "test/vagrant/action/vm/clear_shared_folders_test.rb", "test/vagrant/action/vm/customize_test.rb", "test/vagrant/action/vm/destroy_test.rb", "test/vagrant/action/vm/destroy_unused_network_interfaces_test.rb", "test/vagrant/action/vm/export_test.rb", + "test/vagrant/action/vm/forward_ports_helpers_test.rb", "test/vagrant/action/vm/forward_ports_test.rb", "test/vagrant/action/vm/halt_test.rb", "test/vagrant/action/vm/import_test.rb", @@ -204,11 +208,13 @@ Gem::Specification.new do |s| "test/vagrant/action/exception_catcher_test.rb", "test/vagrant/action/vm/boot_test.rb", "test/vagrant/action/vm/check_guest_additions_test.rb", + "test/vagrant/action/vm/clear_forwarded_ports_test.rb", "test/vagrant/action/vm/clear_shared_folders_test.rb", "test/vagrant/action/vm/customize_test.rb", "test/vagrant/action/vm/destroy_test.rb", "test/vagrant/action/vm/destroy_unused_network_interfaces_test.rb", "test/vagrant/action/vm/export_test.rb", + "test/vagrant/action/vm/forward_ports_helpers_test.rb", "test/vagrant/action/vm/forward_ports_test.rb", "test/vagrant/action/vm/halt_test.rb", "test/vagrant/action/vm/import_test.rb",