Skip to content
This repository
Browse code

Merge branch 'machine-abstraction'

This branch brings in the "machine abstraction" code. This is a major
milestone in the development of Vagrant as it abstracts all of the
VirtualBox-specific code out into a plugin. There is zero VirtualBox
specific code in the core ("lib/") directory at this point. Read on for
important points.

== Gotchas

White it is technically possible now to write plugins for other
providers, there is still major work to be done to make this feasible.
The plugin interface itself is pretty much done, but there are some
issues:

* ":virtualbox" is the hardcoded provider to be used at the moment.

* There is no way to configure a provider. For example,
  `config.vm.customize` would never work for anything other than
  VirtualBox, so there needs to be a way to have provider-specific
  configuration. This will come soon.

* Shared folders and networking need to be rearchitected to be friendly
  for multiple providers, since it is unrealistic that a provider such as
  EC2 could provide the same level of networking, for example.

* There is no way easy way (like `vagrant package --base`) to create
  boxes for providers other than VirtualBox. This will be addressed in a
  whole new feature of Vagrant probably in a future release after
  provider stuff has shipped.

== Writing a Provider

To write a provider, you create a Vagrant plugin that defines a
"provider". See the "plugins/providers/virtualbox/plugin.rb" for more
details. Providers themselves have an exremely simple API. The burden
for writing providers mostly rests on the fact that you must define
complex middleware sequences.

Lots more work to come in the future, but this is a BIG MILESTONE!
  • Loading branch information...
commit 391dc392675c73518ebf04252d824fe916e8860b 2 parents de73b65 + 1cdd69b
Mitchell Hashimoto authored August 19, 2012

Showing 122 changed files with 4,156 additions and 2,915 deletions. Show diff stats Hide diff stats

  1. 25  lib/vagrant.rb
  2. 61  lib/vagrant/action.rb
  3. 31  lib/vagrant/action/box/add.rb
  4. 84  lib/vagrant/action/box/download.rb
  5. 24  lib/vagrant/action/box/verify.rb
  6. 22  lib/vagrant/action/builder.rb
  7. 157  lib/vagrant/action/builtin.rb
  8. 75  lib/vagrant/action/builtin/box_add.rb
  9. 53  lib/vagrant/action/builtin/call.rb
  10. 28  lib/vagrant/action/builtin/confirm.rb
  11. 24  lib/vagrant/action/builtin/env_set.rb
  12. 38  lib/vagrant/action/builtin/ssh_exec.rb
  13. 43  lib/vagrant/action/builtin/ssh_run.rb
  14. 21  lib/vagrant/action/env/set.rb
  15. 28  lib/vagrant/action/general/check_virtualbox.rb
  16. 5  lib/vagrant/action/general/validate.rb
  17. 30  lib/vagrant/action/runner.rb
  18. 20  lib/vagrant/action/vm/destroy_unused_network_interfaces.rb
  19. 22  lib/vagrant/action/vm/discard_state.rb
  20. 26  lib/vagrant/action/vm/provisioner_cleanup.rb
  21. 7  lib/vagrant/communication.rb
  22. 63  lib/vagrant/communication/base.rb
  23. 3  lib/vagrant/downloaders/base.rb
  24. 4  lib/vagrant/downloaders/file.rb
  25. 7  lib/vagrant/driver.rb
  26. 140  lib/vagrant/driver/virtualbox.rb
  27. 474  lib/vagrant/driver/virtualbox_4_0.rb
  28. 474  lib/vagrant/driver/virtualbox_4_1.rb
  29. 326  lib/vagrant/driver/virtualbox_base.rb
  30. 37  lib/vagrant/environment.rb
  31. 12  lib/vagrant/errors.rb
  32. 296  lib/vagrant/machine.rb
  33. 2  lib/vagrant/plugin/v1.rb
  34. 98  lib/vagrant/plugin/v1/communicator.rb
  35. 5  lib/vagrant/plugin/v1/guest.rb
  36. 31  lib/vagrant/plugin/v1/plugin.rb
  37. 68  lib/vagrant/plugin/v1/provider.rb
  38. 128  lib/vagrant/ssh.rb
  39. 4  lib/vagrant/util/safe_exec.rb
  40. 119  lib/vagrant/util/ssh.rb
  41. 205  lib/vagrant/vm.rb
  42. 11  plugins/commands/box/command/add.rb
  43. 50  plugins/commands/destroy/command.rb
  44. 9  plugins/commands/halt/command.rb
  45. 36  plugins/commands/package/command.rb
  46. 24  plugins/commands/provision/command.rb
  47. 20  plugins/commands/reload/command.rb
  48. 18  plugins/commands/resume/command.rb
  49. 52  plugins/commands/ssh/command.rb
  50. 20  plugins/commands/ssh_config/command.rb
  51. 16  plugins/commands/suspend/command.rb
  52. 21  plugins/commands/up/command.rb
  53. 60  lib/vagrant/communication/ssh.rb → plugins/communicators/ssh/communicator.rb
  54. 19  plugins/communicators/ssh/plugin.rb
  55. 34  plugins/guests/linux/guest.rb
  56. 289  plugins/providers/virtualbox/action.rb
  57. 23  {lib/vagrant/action/vm → plugins/providers/virtualbox/action}/boot.rb
  58. 10  {lib/vagrant/action/vm → plugins/providers/virtualbox/action}/check_accessible.rb
  59. 18  {lib/vagrant/action/vm → plugins/providers/virtualbox/action}/check_box.rb
  60. 21  plugins/providers/virtualbox/action/check_created.rb
  61. 14  {lib/vagrant/action/vm → plugins/providers/virtualbox/action}/check_guest_additions.rb
  62. 36  {lib/vagrant/action/vm → plugins/providers/virtualbox/action}/check_port_collisions.rb
  63. 21  plugins/providers/virtualbox/action/check_running.rb
  64. 22  plugins/providers/virtualbox/action/check_virtualbox.rb
  65. 10  {lib/vagrant/action/vm → plugins/providers/virtualbox/action}/clean_machine_folder.rb
  66. 8  {lib/vagrant/action/vm → plugins/providers/virtualbox/action}/clear_forwarded_ports.rb
  67. 8  {lib/vagrant/action/vm → plugins/providers/virtualbox/action}/clear_network_interfaces.rb
  68. 9  {lib/vagrant/action/vm → plugins/providers/virtualbox/action}/clear_shared_folders.rb
  69. 20  plugins/providers/virtualbox/action/created.rb
  70. 12  {lib/vagrant/action/vm → plugins/providers/virtualbox/action}/customize.rb
  71. 10  {lib/vagrant/action/vm → plugins/providers/virtualbox/action}/default_name.rb
  72. 10  {lib/vagrant/action/vm → plugins/providers/virtualbox/action}/destroy.rb
  73. 16  plugins/providers/virtualbox/action/destroy_confirm.rb
  74. 16  plugins/providers/virtualbox/action/destroy_unused_network_interfaces.rb
  75. 20  plugins/providers/virtualbox/action/discard_state.rb
  76. 13  {lib/vagrant/action/vm → plugins/providers/virtualbox/action}/export.rb
  77. 14  {lib/vagrant/action/vm → plugins/providers/virtualbox/action}/forward_ports.rb
  78. 19  {lib/vagrant/action/vm → plugins/providers/virtualbox/action}/halt.rb
  79. 10  {lib/vagrant/action/vm → plugins/providers/virtualbox/action}/host_name.rb
  80. 26  {lib/vagrant/action/vm → plugins/providers/virtualbox/action}/import.rb
  81. 20  plugins/providers/virtualbox/action/is_running.rb
  82. 20  plugins/providers/virtualbox/action/is_saved.rb
  83. 10  {lib/vagrant/action/vm → plugins/providers/virtualbox/action}/match_mac_address.rb
  84. 16  plugins/providers/virtualbox/action/message_not_created.rb
  85. 16  plugins/providers/virtualbox/action/message_not_running.rb
  86. 17  plugins/providers/virtualbox/action/message_will_not_destroy.rb
  87. 46  {lib/vagrant/action/vm → plugins/providers/virtualbox/action}/network.rb
  88. 43  {lib/vagrant/action/vm → plugins/providers/virtualbox/action}/nfs.rb
  89. 11  {lib/vagrant/action/vm → plugins/providers/virtualbox/action}/package.rb
  90. 13  {lib/vagrant/action/vm → plugins/providers/virtualbox/action}/package_vagrantfile.rb
  91. 9  {lib/vagrant/action/vm → plugins/providers/virtualbox/action}/provision.rb
  92. 25  plugins/providers/virtualbox/action/provisioner_cleanup.rb
  93. 8  {lib/vagrant/action/vm → plugins/providers/virtualbox/action}/prune_nfs_exports.rb
  94. 8  {lib/vagrant/action/vm → plugins/providers/virtualbox/action}/resume.rb
  95. 19  {lib/vagrant/action/vm → plugins/providers/virtualbox/action}/sane_defaults.rb
  96. 13  {lib/vagrant/action/vm → plugins/providers/virtualbox/action}/setup_package_files.rb
  97. 23  {lib/vagrant/action/vm → plugins/providers/virtualbox/action}/share_folders.rb
  98. 10  {lib/vagrant/action/vm → plugins/providers/virtualbox/action}/suspend.rb
  99. 327  plugins/providers/virtualbox/driver/base.rb
  100. 139  plugins/providers/virtualbox/driver/meta.rb
  101. 476  plugins/providers/virtualbox/driver/version_4_0.rb
  102. 476  plugins/providers/virtualbox/driver/version_4_1.rb
  103. 28  plugins/providers/virtualbox/plugin.rb
  104. 83  plugins/providers/virtualbox/provider.rb
  105. 17  templates/locales/en.yml
  106. 26  test/unit/support/shared/base_context.rb
  107. 24  test/unit/vagrant/action/builder_test.rb
  108. 55  test/unit/vagrant/action/builtin/call_test.rb
  109. 21  test/unit/vagrant/action/builtin/confirm_test.rb
  110. 20  test/unit/vagrant/action/builtin/env_set_test.rb
  111. 55  test/unit/vagrant/action/builtin/ssh_exec_test.rb
  112. 24  test/unit/vagrant/action/runner_test.rb
  113. 4  test/unit/vagrant/downloaders/base_test.rb
  114. 26  test/unit/vagrant/downloaders/file_test.rb
  115. 25  test/unit/vagrant/environment_test.rb
  116. 388  test/unit/vagrant/machine_test.rb
  117. 9  test/unit/vagrant/plugin/v1/communicator_test.rb
  118. 56  test/unit/vagrant/plugin/v1/plugin_test.rb
  119. 18  test/unit/vagrant/plugin/v1/provider_test.rb
  120. 30  test/unit/vagrant/ssh_test.rb
  121. 30  test/unit/vagrant/util/ssh_test.rb
  122. 2  test/unit/vagrant_test.rb
25  lib/vagrant.rb
@@ -66,7 +66,6 @@ module Vagrant
66 66
   autoload :BoxCollection, 'vagrant/box_collection'
67 67
   autoload :CLI,           'vagrant/cli'
68 68
   autoload :Command,       'vagrant/command'
69  
-  autoload :Communication, 'vagrant/communication'
70 69
   autoload :Config,        'vagrant/config'
71 70
   autoload :DataStore,     'vagrant/data_store'
72 71
   autoload :Downloaders,   'vagrant/downloaders'
@@ -76,27 +75,23 @@ module Vagrant
76 75
   autoload :Errors,        'vagrant/errors'
77 76
   autoload :Guest,         'vagrant/guest'
78 77
   autoload :Hosts,         'vagrant/hosts'
  78
+  autoload :Machine,       'vagrant/machine'
79 79
   autoload :Plugin,        'vagrant/plugin'
80  
-  autoload :SSH,           'vagrant/ssh'
81 80
   autoload :TestHelpers,   'vagrant/test_helpers'
82 81
   autoload :UI,            'vagrant/ui'
83 82
   autoload :Util,          'vagrant/util'
84  
-  autoload :VM,            'vagrant/vm'
85 83
 
86 84
   # These are the various plugin versions and their components in
87 85
   # a lazy loaded Hash-like structure.
88  
-  c = PLUGIN_COMPONENTS = Registry.new
89  
-  c.register(:"1")                 { Plugin::V1::Plugin }
90  
-  c.register([:"1", :command])     { Plugin::V1::Command }
91  
-  c.register([:"1", :config])      { Plugin::V1::Config }
92  
-  c.register([:"1", :guest])       { Plugin::V1::Guest }
93  
-  c.register([:"1", :host])        { Plugin::V1::Host }
94  
-  c.register([:"1", :provisioner]) { Plugin::V1::Provisioner }
95  
-
96  
-  # Returns a `Vagrant::Registry` object that contains all the built-in
97  
-  # middleware stacks.
98  
-  def self.actions
99  
-    @actions ||= Vagrant::Action::Builtin.new
  86
+  PLUGIN_COMPONENTS = Registry.new.tap do |c|
  87
+    c.register(:"1")                  { Plugin::V1::Plugin }
  88
+    c.register([:"1", :command])      { Plugin::V1::Command }
  89
+    c.register([:"1", :communicator]) { Plugin::V1::Communicator }
  90
+    c.register([:"1", :config])       { Plugin::V1::Config }
  91
+    c.register([:"1", :guest])        { Plugin::V1::Guest }
  92
+    c.register([:"1", :host])         { Plugin::V1::Host }
  93
+    c.register([:"1", :provider])     { Plugin::V1::Provider }
  94
+    c.register([:"1", :provisioner])  { Plugin::V1::Provisioner }
100 95
   end
101 96
 
102 97
   # The source root is the path to the root directory of
61  lib/vagrant/action.rb
@@ -2,60 +2,35 @@
2 2
 
3 3
 module Vagrant
4 4
   module Action
5  
-    autoload :Builtin,     'vagrant/action/builtin'
6 5
     autoload :Environment, 'vagrant/action/environment'
7 6
     autoload :Runner,      'vagrant/action/runner'
8 7
     autoload :Warden,      'vagrant/action/warden'
9 8
 
10  
-    module Box
11  
-      autoload :Add,       'vagrant/action/box/add'
12  
-      autoload :Download,  'vagrant/action/box/download'
13  
-      autoload :Verify,    'vagrant/action/box/verify'
14  
-    end
15  
-
16  
-    module Env
17  
-      autoload :Set, 'vagrant/action/env/set'
  9
+    # Builtin contains middleware classes that are shipped with Vagrant-core
  10
+    # and are thus available to all plugins as a "standard library" of sorts.
  11
+    module Builtin
  12
+      autoload :BoxAdd,  "vagrant/action/builtin/box_add"
  13
+      autoload :Call,    "vagrant/action/builtin/call"
  14
+      autoload :Confirm, "vagrant/action/builtin/confirm"
  15
+      autoload :EnvSet,  "vagrant/action/builtin/env_set"
  16
+      autoload :SSHExec, "vagrant/action/builtin/ssh_exec"
  17
+      autoload :SSHRun,  "vagrant/action/builtin/ssh_run"
18 18
     end
19 19
 
20 20
     module General
21  
-      autoload :CheckVirtualbox, 'vagrant/action/general/check_virtualbox'
22 21
       autoload :Package,  'vagrant/action/general/package'
23 22
       autoload :Validate, 'vagrant/action/general/validate'
24 23
     end
25 24
 
26  
-    module VM
27  
-      autoload :Boot,                'vagrant/action/vm/boot'
28  
-      autoload :CheckAccessible,     'vagrant/action/vm/check_accessible'
29  
-      autoload :CheckBox,            'vagrant/action/vm/check_box'
30  
-      autoload :CheckGuestAdditions, 'vagrant/action/vm/check_guest_additions'
31  
-      autoload :CheckPortCollisions, 'vagrant/action/vm/check_port_collisions'
32  
-      autoload :CleanMachineFolder,  'vagrant/action/vm/clean_machine_folder'
33  
-      autoload :ClearForwardedPorts, 'vagrant/action/vm/clear_forwarded_ports'
34  
-      autoload :ClearNetworkInterfaces, 'vagrant/action/vm/clear_network_interfaces'
35  
-      autoload :ClearSharedFolders,  'vagrant/action/vm/clear_shared_folders'
36  
-      autoload :Customize,           'vagrant/action/vm/customize'
37  
-      autoload :DefaultName,         'vagrant/action/vm/default_name'
38  
-      autoload :Destroy,             'vagrant/action/vm/destroy'
39  
-      autoload :DestroyUnusedNetworkInterfaces, 'vagrant/action/vm/destroy_unused_network_interfaces'
40  
-      autoload :DiscardState,        'vagrant/action/vm/discard_state'
41  
-      autoload :Export,              'vagrant/action/vm/export'
42  
-      autoload :ForwardPorts,        'vagrant/action/vm/forward_ports'
43  
-      autoload :Halt,                'vagrant/action/vm/halt'
44  
-      autoload :HostName,            'vagrant/action/vm/host_name'
45  
-      autoload :Import,              'vagrant/action/vm/import'
46  
-      autoload :MatchMACAddress,     'vagrant/action/vm/match_mac_address'
47  
-      autoload :Network,             'vagrant/action/vm/network'
48  
-      autoload :NFS,                 'vagrant/action/vm/nfs'
49  
-      autoload :Package,             'vagrant/action/vm/package'
50  
-      autoload :PackageVagrantfile,  'vagrant/action/vm/package_vagrantfile'
51  
-      autoload :Provision,           'vagrant/action/vm/provision'
52  
-      autoload :ProvisionerCleanup,  'vagrant/action/vm/provisioner_cleanup'
53  
-      autoload :PruneNFSExports,     'vagrant/action/vm/prune_nfs_exports'
54  
-      autoload :Resume,              'vagrant/action/vm/resume'
55  
-      autoload :SaneDefaults,        'vagrant/action/vm/sane_defaults'
56  
-      autoload :ShareFolders,        'vagrant/action/vm/share_folders'
57  
-      autoload :SetupPackageFiles,   'vagrant/action/vm/setup_package_files'
58  
-      autoload :Suspend,             'vagrant/action/vm/suspend'
  25
+    # This is the action that will add a box from a URL. This middleware
  26
+    # sequence is built-in to Vagrant. Plugins can hook into this like any
  27
+    # other middleware sequence. This is particularly useful for provider
  28
+    # plugins, which can hook in to do things like verification of boxes
  29
+    # that are downloaded.
  30
+    def self.action_box_add
  31
+      Builder.new.tap do |b|
  32
+        b.use Builtin::BoxAdd
  33
+      end
59 34
     end
60 35
   end
61 36
 end
31  lib/vagrant/action/box/add.rb
... ...
@@ -1,31 +0,0 @@
1  
-module Vagrant
2  
-  module Action
3  
-    module Box
4  
-      # Adds a downloaded box file to the environment's box collection.
5  
-      # This handles unpacking the box. See {BoxCollection#add} for more
6  
-      # information.
7  
-      class Add
8  
-        def initialize(app, env)
9  
-          @app = app
10  
-          @env = env
11  
-        end
12  
-
13  
-        def call(env)
14  
-          @env[:ui].info I18n.t("vagrant.actions.box.add.adding", :name => env[:box_name])
15  
-
16  
-          begin
17  
-            env[:box_collection].add(env[:box_download_temp_path], env[:box_name])
18  
-          rescue Vagrant::Errors::BoxUpgradeRequired
19  
-            # Upgrade the box
20  
-            env[:box_collection].upgrade(env[:box_name])
21  
-
22  
-            # Try adding it again
23  
-            retry
24  
-          end
25  
-
26  
-          @app.call(env)
27  
-        end
28  
-      end
29  
-    end
30  
-  end
31  
-end
84  lib/vagrant/action/box/download.rb
... ...
@@ -1,84 +0,0 @@
1  
-module Vagrant
2  
-  module Action
3  
-    module Box
4  
-      class Download
5  
-        BASENAME = "box"
6  
-
7  
-        include Util
8  
-
9  
-        attr_reader :temp_path
10  
-
11  
-        def initialize(app, env)
12  
-          @app = app
13  
-          @env = env
14  
-          @env["download.classes"] ||= []
15  
-          @env["download.classes"] += [Downloaders::HTTP, Downloaders::File]
16  
-          @downloader = nil
17  
-        end
18  
-
19  
-        def call(env)
20  
-          @env = env
21  
-
22  
-          download if instantiate_downloader
23  
-          @app.call(@env)
24  
-
25  
-          recover(env) # called in both cases to cleanup workspace
26  
-        end
27  
-
28  
-        def instantiate_downloader
29  
-          # Assign to a temporary variable since this is easier to type out,
30  
-          # since it is used so many times.
31  
-          classes = @env["download.classes"]
32  
-
33  
-          # Find the class to use.
34  
-          classes.each_index do |i|
35  
-            klass = classes[i]
36  
-
37  
-            # Use the class if it matches the given URI or if this
38  
-            # is the last class...
39  
-            if classes.length == (i + 1) || klass.match?(@env[:box_url])
40  
-              @env[:ui].info I18n.t("vagrant.actions.box.download.with", :class => klass.to_s)
41  
-              @downloader = klass.new(@env[:ui])
42  
-              break
43  
-            end
44  
-          end
45  
-
46  
-          # This line should never be reached, but we'll keep this here
47  
-          # just in case for now.
48  
-          raise Errors::BoxDownloadUnknownType if !@downloader
49  
-
50  
-          @downloader.prepare(@env[:box_url])
51  
-          true
52  
-        end
53  
-
54  
-        def download
55  
-          with_tempfile do |tempfile|
56  
-            download_to(tempfile)
57  
-            @temp_path = @env[:box_download_temp_path] = tempfile.path
58  
-          end
59  
-        end
60  
-
61  
-        def recover(env)
62  
-          if temp_path && File.exist?(temp_path)
63  
-            env[:ui].info I18n.t("vagrant.actions.box.download.cleaning")
64  
-            File.unlink(temp_path)
65  
-          end
66  
-        end
67  
-
68  
-        def with_tempfile
69  
-          File.open(box_temp_path, Platform.tar_file_options) do |tempfile|
70  
-            yield tempfile
71  
-          end
72  
-        end
73  
-
74  
-        def box_temp_path
75  
-          @env[:tmp_path].join(BASENAME + Time.now.to_i.to_s)
76  
-        end
77  
-
78  
-        def download_to(f)
79  
-          @downloader.download!(@env[:box_url], f)
80  
-        end
81  
-      end
82  
-    end
83  
-  end
84  
-end
24  lib/vagrant/action/box/verify.rb
... ...
@@ -1,24 +0,0 @@
1  
-module Vagrant
2  
-  module Action
3  
-    module Box
4  
-      class Verify
5  
-        def initialize(app, env)
6  
-          @app = app
7  
-          @env = env
8  
-        end
9  
-
10  
-        def call(env)
11  
-          @env[:ui].info I18n.t("vagrant.actions.box.verify.verifying")
12  
-
13  
-          box    = env[:box_collection].find(env[:box_name], :virtualbox)
14  
-          driver = Driver::VirtualBox.new(nil)
15  
-          if !driver.verify_image(box.directory.join("box.ovf").to_s)
16  
-            raise Errors::BoxVerificationFailed
17  
-          end
18  
-
19  
-          @app.call(env)
20  
-        end
21  
-      end
22  
-    end
23  
-  end
24  
-end
22  lib/vagrant/action/builder.rb
@@ -9,18 +9,21 @@ module Action
9 9
     #
10 10
     # Building an action sequence is very easy:
11 11
     #
12  
-    #     app = Vagrant::Action::Builder.new do
13  
-    #       use MiddlewareA
14  
-    #       use MiddlewareB
  12
+    #     app = Vagrant::Action::Builder.new.tap do |b|
  13
+    #       b.use MiddlewareA
  14
+    #       b.use MiddlewareB
15 15
     #     end
16 16
     #
17 17
     #     Vagrant::Action.run(app)
18 18
     #
19 19
     class Builder
20  
-      # Initializes the builder. An optional block can be passed which
21  
-      # will be evaluated in the context of the instance.
22  
-      def initialize(&block)
23  
-        instance_eval(&block) if block_given?
  20
+      # This is a shortcut for a middleware sequence with only one item
  21
+      # in it. For a description of the arguments and the documentation, please
  22
+      # see {#use} instead.
  23
+      #
  24
+      # @return [Builder]
  25
+      def self.build(middleware, *args, &block)
  26
+        new.use(middleware, *args, &block)
24 27
       end
25 28
 
26 29
       # Returns a mergeable version of the builder. If `use` is called with
@@ -38,11 +41,6 @@ def flatten
38 41
       #
39 42
       # @param [Class] middleware The middleware class
40 43
       def use(middleware, *args, &block)
41  
-        # Prepend with a environment setter if args are given
42  
-        if !args.empty? && args.first.is_a?(Hash) && middleware != Env::Set
43  
-          self.use(Env::Set, args.shift, &block)
44  
-        end
45  
-
46 44
         if middleware.kind_of?(Builder)
47 45
           # Merge in the other builder's stack into our own
48 46
           self.stack.concat(middleware.stack)
157  lib/vagrant/action/builtin.rb
... ...
@@ -1,157 +0,0 @@
1  
-module Vagrant
2  
-  module Action
3  
-    # A registry object containing the built-in middleware stacks.
4  
-    class Builtin < Registry
5  
-      def initialize
6  
-        # Properly initialize the registry object
7  
-        super
8  
-
9  
-        # Register all the built-in stacks
10  
-        register_builtin!
11  
-      end
12  
-
13  
-      protected
14  
-
15  
-      def register_builtin!
16  
-        # We do this so that the blocks below have a variable to access the
17  
-        # outer registry.
18  
-        registry = self
19  
-
20  
-        # provision - Provisions a running VM
21  
-        register(:provision) do
22  
-          Builder.new do
23  
-            use General::CheckVirtualbox
24  
-            use General::Validate
25  
-            use VM::CheckAccessible
26  
-            use VM::Provision
27  
-          end
28  
-        end
29  
-
30  
-        # start - Starts a VM, assuming it already exists on the
31  
-        # environment.
32  
-        register(:start) do
33  
-          Builder.new do
34  
-            use General::CheckVirtualbox
35  
-            use General::Validate
36  
-            use VM::CheckAccessible
37  
-            use VM::CleanMachineFolder
38  
-            use VM::ClearForwardedPorts
39  
-            use VM::CheckPortCollisions, :port_collision_handler => :correct
40  
-            use VM::ForwardPorts
41  
-            use VM::Provision
42  
-            use VM::PruneNFSExports
43  
-            use VM::NFS
44  
-            use VM::ClearSharedFolders
45  
-            use VM::ShareFolders
46  
-            use VM::ClearNetworkInterfaces
47  
-            use VM::Network
48  
-            use VM::HostName
49  
-            use VM::SaneDefaults
50  
-            use VM::Customize
51  
-            use VM::Boot
52  
-          end
53  
-        end
54  
-
55  
-        # halt - Halts the VM, attempting gracefully but then forcing
56  
-        # a restart if fails.
57  
-        register(:halt) do
58  
-          Builder.new do
59  
-            use General::CheckVirtualbox
60  
-            use General::Validate
61  
-            use VM::CheckAccessible
62  
-            use VM::DiscardState
63  
-            use VM::Halt
64  
-          end
65  
-        end
66  
-
67  
-        # suspend - Suspends the VM
68  
-        register(:suspend) do
69  
-          Builder.new do
70  
-            use General::CheckVirtualbox
71  
-            use General::Validate
72  
-            use VM::CheckAccessible
73  
-            use VM::Suspend
74  
-          end
75  
-        end
76  
-
77  
-        # resume - Resume a VM
78  
-        register(:resume) do
79  
-          Builder.new do
80  
-            use General::CheckVirtualbox
81  
-            use General::Validate
82  
-            use VM::CheckAccessible
83  
-            use VM::CheckPortCollisions
84  
-            use VM::Resume
85  
-          end
86  
-        end
87  
-
88  
-        # reload - Halts then restarts the VM
89  
-        register(:reload) do
90  
-          Builder.new do
91  
-            use General::CheckVirtualbox
92  
-            use General::Validate
93  
-            use VM::CheckAccessible
94  
-            use registry.get(:halt)
95  
-            use registry.get(:start)
96  
-          end
97  
-        end
98  
-
99  
-        # up - Imports, prepares, then starts a fresh VM.
100  
-        register(:up) do
101  
-          Builder.new do
102  
-            use General::CheckVirtualbox
103  
-            use General::Validate
104  
-            use VM::CheckAccessible
105  
-            use VM::CheckBox
106  
-            use VM::Import
107  
-            use VM::CheckGuestAdditions
108  
-            use VM::DefaultName
109  
-            use VM::MatchMACAddress
110  
-            use registry.get(:start)
111  
-          end
112  
-        end
113  
-
114  
-        # destroy - Halts, cleans up, and destroys an existing VM
115  
-        register(:destroy) do
116  
-          Builder.new do
117  
-            use General::CheckVirtualbox
118  
-            use General::Validate
119  
-            use VM::CheckAccessible
120  
-            use registry.get(:halt), :force => true
121  
-            use VM::ProvisionerCleanup
122  
-            use VM::PruneNFSExports
123  
-            use VM::Destroy
124  
-            use VM::CleanMachineFolder
125  
-            use VM::DestroyUnusedNetworkInterfaces
126  
-          end
127  
-        end
128  
-
129  
-        # package - Export and package the VM
130  
-        register(:package) do
131  
-          Builder.new do
132  
-            use General::CheckVirtualbox
133  
-            use General::Validate
134  
-            use VM::SetupPackageFiles
135  
-            use VM::CheckAccessible
136  
-            use registry.get(:halt)
137  
-            use VM::ClearForwardedPorts
138  
-            use VM::ClearSharedFolders
139  
-            use VM::Export
140  
-            use VM::PackageVagrantfile
141  
-            use VM::Package
142  
-          end
143  
-        end
144  
-
145  
-        # box_add - Download and add a box.
146  
-        register(:box_add) do
147  
-          Builder.new do
148  
-            use General::CheckVirtualbox
149  
-            use Box::Download
150  
-            use Box::Add
151  
-            use Box::Verify
152  
-          end
153  
-        end
154  
-      end
155  
-    end
156  
-  end
157  
-end
75  lib/vagrant/action/builtin/box_add.rb
... ...
@@ -0,0 +1,75 @@
  1
+require "vagrant/util/platform"
  2
+
  3
+module Vagrant
  4
+  module Action
  5
+    module Builtin
  6
+      # This middleware will download a remote box and add it to the
  7
+      # given box collection.
  8
+      class BoxAdd
  9
+        def initialize(app, env)
  10
+          @app = app
  11
+        end
  12
+
  13
+        def call(env)
  14
+          # Instantiate the downloader
  15
+          downloader = download_klass(env[:box_url]).new(env[:ui])
  16
+          env[:ui].info I18n.t("vagrant.actions.box.download.with",
  17
+                               :class => downloader.class.to_s)
  18
+
  19
+          # Download the box to a temporary path. We store the temporary
  20
+          # path as an instance variable so that the `#recover` method can
  21
+          # access it.
  22
+          @temp_path = env[:tmp_path].join("box" + Time.now.to_i.to_s)
  23
+          File.open(@temp_path, Vagrant::Util::Platform.tar_file_options) do |f|
  24
+            downloader.download!(env[:box_url], f)
  25
+          end
  26
+
  27
+          # Add the box
  28
+          env[:ui].info I18n.t("vagrant.actions.box.add.adding", :name => env[:box_name])
  29
+          begin
  30
+            env[:box_collection].add(@temp_path, env[:box_name])
  31
+          rescue Vagrant::Errors::BoxUpgradeRequired
  32
+            # Upgrade the box
  33
+            env[:box_collection].upgrade(env[:box_name])
  34
+
  35
+            # Try adding it again
  36
+            retry
  37
+          end
  38
+
  39
+          # Call the 'recover' method in all cases to clean up the
  40
+          # downloaded temporary file.
  41
+          recover(env)
  42
+
  43
+          # Carry on!
  44
+          @app.call(env)
  45
+        end
  46
+
  47
+        def download_klass(url)
  48
+          # This is hardcoded for now. In the future I'd like to make this
  49
+          # pluginnable as well.
  50
+          classes = [Downloaders::HTTP, Downloaders::File]
  51
+
  52
+          # Find the class to use.
  53
+          classes.each_index do |i|
  54
+            klass = classes[i]
  55
+
  56
+            # Use the class if it matches the given URI or if this
  57
+            # is the last class...
  58
+            return klass if classes.length == (i + 1) || klass.match?(url)
  59
+          end
  60
+
  61
+          # If no downloader knows how to download this file, then we
  62
+          # raise an exception.
  63
+          raise Errors::BoxDownloadUnknownType
  64
+        end
  65
+
  66
+        def recover(env)
  67
+          if @temp_path && File.exist?(@temp_path)
  68
+            env[:ui].info I18n.t("vagrant.actions.box.download.cleaning")
  69
+            File.unlink(@temp_path)
  70
+          end
  71
+        end
  72
+      end
  73
+    end
  74
+  end
  75
+end
53  lib/vagrant/action/builtin/call.rb
... ...
@@ -0,0 +1,53 @@
  1
+module Vagrant
  2
+  module Action
  3
+    module Builtin
  4
+      # This middleware class allows a sort of "conditional" run within
  5
+      # a single middlware sequence. It takes another middleware runnable,
  6
+      # runs it with the same environment, then yields the resulting env to a block,
  7
+      # allowing that block to determine the next course of action in the
  8
+      # middleware sequence.
  9
+      #
  10
+      # The first argument to this middleware sequence is anywhere middleware
  11
+      # runnable, whether it be a class, lambda, or something else that
  12
+      # responds to `call`. This middleware runnable is run with the same
  13
+      # environment as this class.
  14
+      #
  15
+      # After running, {Call} takes the environment and yields it to a block
  16
+      # given to initialize the class, along with an instance of {Builder}.
  17
+      # The result is used to build up a new sequence on the given builder.
  18
+      # This builder is then run.
  19
+      class Call
  20
+        # For documentation, read the description of the {Call} class.
  21
+        #
  22
+        # @param [Object] callable A valid middleware runnable object. This
  23
+        #   can be a class, a lambda, or an object that responds to `call`.
  24
+        # @yield [result, builder] This block is expected to build on `builder`
  25
+        #   which is the next middleware sequence that will be run.
  26
+        def initialize(app, env, callable, &block)
  27
+          raise ArgumentError, "A block must be given to Call" if !block
  28
+
  29
+          @app      = app
  30
+          @callable = callable
  31
+          @block    = block
  32
+        end
  33
+
  34
+        def call(env)
  35
+          runner  = Runner.new
  36
+
  37
+          # Run our callable with our environment
  38
+          new_env = runner.run(@callable, env)
  39
+
  40
+          # Build our new builder based on the result
  41
+          builder = Builder.new
  42
+          @block.call(new_env, builder)
  43
+
  44
+          # Run the result with our new environment
  45
+          final_env = runner.run(builder, new_env)
  46
+
  47
+          # Call the next step using our final environment
  48
+          @app.call(final_env)
  49
+        end
  50
+      end
  51
+    end
  52
+  end
  53
+end
28  lib/vagrant/action/builtin/confirm.rb
... ...
@@ -0,0 +1,28 @@
  1
+module Vagrant
  2
+  module Action
  3
+    module Builtin
  4
+      # This class asks the user to confirm some sort of question with
  5
+      # a "Y/N" question. The only parameter is the text to ask the user.
  6
+      # The result is placed in `env[:result]` so that it can be used
  7
+      # with the {Call} class.
  8
+      class Confirm
  9
+        # For documentation, read the description of the {Confirm} class.
  10
+        #
  11
+        # @param [String] message The message to ask the user.
  12
+        def initialize(app, env, message)
  13
+          @app      = app
  14
+          @message  = message
  15
+        end
  16
+
  17
+        def call(env)
  18
+          # Ask the user the message and store the result
  19
+          choice = nil
  20
+          choice = env[:ui].ask(@message)
  21
+          env[:result] = choice && choice.upcase == "Y"
  22
+
  23
+          @app.call(env)
  24
+        end
  25
+      end
  26
+    end
  27
+  end
  28
+end
24  lib/vagrant/action/builtin/env_set.rb
... ...
@@ -0,0 +1,24 @@
  1
+module Vagrant
  2
+  module Action
  3
+    module Builtin
  4
+      # This middleware class allows you to modify the environment hash
  5
+      # in the middle of a middleware sequence. The new environmental data
  6
+      # will take affect at this stage in the middleware and will persist
  7
+      # through.
  8
+      class EnvSet
  9
+        def initialize(app, env, new_env=nil)
  10
+          @app     = app
  11
+          @new_env = new_env || {}
  12
+        end
  13
+
  14
+        def call(env)
  15
+          # Merge in the new data
  16
+          env.merge!(@new_env)
  17
+
  18
+          # Carry on
  19
+          @app.call(env)
  20
+        end
  21
+      end
  22
+    end
  23
+  end
  24
+end
38  lib/vagrant/action/builtin/ssh_exec.rb
... ...
@@ -0,0 +1,38 @@
  1
+require "vagrant/util/ssh"
  2
+
  3
+module Vagrant
  4
+  module Action
  5
+    module Builtin
  6
+      # This class will exec into a full fledged SSH console into the
  7
+      # remote machine. This middleware assumes that the VM is running and
  8
+      # ready for SSH, and uses the {Machine#ssh_info} method to retrieve
  9
+      # SSH information necessary to connect.
  10
+      #
  11
+      # Note: If there are any middleware after `SSHExec`, they will **not**
  12
+      # run, since exec replaces the currently running process.
  13
+      class SSHExec
  14
+        # For quick access to the `SSH` class.
  15
+        include Vagrant::Util
  16
+
  17
+        def initialize(app, env)
  18
+          @app = app
  19
+        end
  20
+
  21
+        def call(env)
  22
+          # Grab the SSH info from the machine
  23
+          info = env[:machine].ssh_info
  24
+
  25
+          # If the result is nil, then the machine is telling us that it is
  26
+          # not yet ready for SSH, so we raise this exception.
  27
+          raise Errors::SSHNotReady if info.nil?
  28
+
  29
+          # Check the SSH key permissions
  30
+          SSH.check_key_permissions(info[:private_key_path])
  31
+
  32
+          # Exec!
  33
+          SSH.exec(info, env[:ssh_opts])
  34
+        end
  35
+      end
  36
+    end
  37
+  end
  38
+end
43  lib/vagrant/action/builtin/ssh_run.rb
... ...
@@ -0,0 +1,43 @@
  1
+require "log4r"
  2
+
  3
+module Vagrant
  4
+  module Action
  5
+    module Builtin
  6
+      # This class will run a single command on the remote machine and will
  7
+      # mirror the output to the UI. The resulting exit status of the command
  8
+      # will exist in the `:ssh_run_exit_status` key in the environment.
  9
+      class SSHRun
  10
+        def initialize(app, env)
  11
+          @app    = app
  12
+          @logger = Log4r::Logger.new("vagrant::action::builtin::ssh_run")
  13
+        end
  14
+
  15
+        def call(env)
  16
+          command = env[:ssh_run_command]
  17
+
  18
+          @logger.debug("Executing command: #{command}")
  19
+          exit_status = 0
  20
+          exit_status = env[:machine].communicate.execute(command, :error_check => false) do |type, data|
  21
+            # Determine the proper channel to send the output onto depending
  22
+            # on the type of data we are receiving.
  23
+            channel = type == :stdout ? :out : :error
  24
+
  25
+            # Print the output as it comes in, but don't prefix it and don't
  26
+            # force a new line so that the output is properly preserved however
  27
+            # it may be formatted.
  28
+            env[:ui].info(data.to_s,
  29
+                          :prefix => false,
  30
+                          :new_line => false,
  31
+                          :channel => channel)
  32
+          end
  33
+
  34
+          # Set the exit status on a known environmental variable
  35
+          env[:ssh_run_exit_status] = exit_status
  36
+
  37
+          # Call the next middleware
  38
+          @app.call(env)
  39
+        end
  40
+      end
  41
+    end
  42
+  end
  43
+end
21  lib/vagrant/action/env/set.rb
... ...
@@ -1,21 +0,0 @@
1  
-module Vagrant
2  
-  module Action
3  
-    module Env
4  
-      # A middleware which just sets up the environment with some
5  
-      # options which are passed to it.
6  
-      class Set
7  
-        def initialize(app, env, options=nil)
8  
-          @app     = app
9  
-          @options = options || {}
10  
-        end
11  
-
12  
-        def call(env)
13  
-          # Merge the options that were given to us
14  
-          env.merge!(@options)
15  
-
16  
-          @app.call(env)
17  
-        end
18  
-      end
19  
-    end
20  
-  end
21  
-end
28  lib/vagrant/action/general/check_virtualbox.rb
... ...
@@ -1,28 +0,0 @@
1  
-module Vagrant
2  
-  module Action
3  
-    module General
4  
-      # Checks that virtualbox is installed and ready to be used.
5  
-      class CheckVirtualbox
6  
-        def initialize(app, env)
7  
-          @app = app
8  
-        end
9  
-
10  
-        def call(env)
11  
-          # Certain actions may not actually have a VM, and thus no
12  
-          # driver, so we have to be clever about obtaining an instance
13  
-          # of the driver.
14  
-          driver = nil
15  
-          driver = env[:vm].driver if env[:vm]
16  
-          driver = Driver::VirtualBox.new(nil) if !driver
17  
-
18  
-          # Verify that it is ready to go! This will raise an exception
19  
-          # if anything goes wrong.
20  
-          driver.verify!
21  
-
22  
-          # Carry on.
23  
-          @app.call(env)
24  
-        end
25  
-      end
26  
-    end
27  
-  end
28  
-end
5  lib/vagrant/action/general/validate.rb
@@ -9,7 +9,10 @@ def initialize(app, env)
9 9
         end
10 10
 
11 11
         def call(env)
12  
-          env[:vm].config.validate!(env[:vm].env) if !env.has_key?("validate") || env["validate"]
  12
+          if !env.has_key?(:validate) || env[:validate]
  13
+            env[:machine].config.validate!(env[:machine].env)
  14
+          end
  15
+
13 16
           @app.call(env)
14 17
         end
15 18
       end
30  lib/vagrant/action/runner.rb
@@ -10,8 +10,7 @@ module Action
10 10
     class Runner
11 11
       @@reported_interrupt = false
12 12
 
13  
-      def initialize(registry, globals=nil, &block)
14  
-        @registry     = registry
  13
+      def initialize(globals=nil, &block)
15 14
         @globals      = globals || {}
16 15
         @lazy_globals = block
17 16
         @logger       = Log4r::Logger.new("vagrant::action::runner")
@@ -19,8 +18,7 @@ def initialize(registry, globals=nil, &block)
19 18
 
20 19
       def run(callable_id, options=nil)
21 20
         callable = callable_id
22  
-        callable = Builder.new.use(callable_id) if callable_id.kind_of?(Class)
23  
-        callable = registry_sequence(callable_id) if callable_id.kind_of?(Symbol)
  21
+        callable = Builder.build(callable_id) if callable_id.kind_of?(Class)
24 22
         raise ArgumentError, "Argument to run must be a callable object or registered action." if !callable || !callable.respond_to?(:call)
25 23
 
26 24
         # Create the initial environment with the options given
@@ -47,28 +45,10 @@ def run(callable_id, options=nil)
47 45
         # We place a process lock around every action that is called
48 46
         @logger.info("Running action: #{callable_id}")
49 47
         Util::Busy.busy(int_callback) { callable.call(environment) }
50  
-      end
51  
-
52  
-      protected
53  
-
54  
-      def registry_sequence(id)
55  
-        # Attempt to get the sequence
56  
-        seq = @registry.get(id)
57  
-        return nil if !seq
58  
-
59  
-        # Go through all the registered plugins and get all the hooks
60  
-        # for this sequence.
61  
-        Vagrant.plugin("1").registered.each do |plugin|
62  
-          hooks  = plugin.action_hook(Vagrant::Plugin::V1::Plugin::ALL_ACTIONS)
63  
-          hooks += plugin.action_hook(id)
64  
-
65  
-          hooks.each do |hook|
66  
-            hook.call(seq)
67  
-          end
68  
-        end
69 48
 
70  
-        # Return the sequence
71  
-        seq
  49
+        # Return the environment in case there are things in there that
  50
+        # the caller wants to use.
  51
+        environment
72 52
       end
73 53
     end
74 54
   end
20  lib/vagrant/action/vm/destroy_unused_network_interfaces.rb
... ...
@@ -1,20 +0,0 @@
1  
-module Vagrant
2  
-  module Action
3  
-    module VM
4  
-      # Destroys the unused host only interfaces. This middleware cleans
5  
-      # up any created host only networks.
6  
-      class DestroyUnusedNetworkInterfaces
7  
-        def initialize(app, env)
8  
-          @app = app
9  
-        end
10  
-
11  
-        def call(env)
12  
-          env[:vm].driver.delete_unused_host_only_networks
13  
-
14  
-          # Continue along
15  
-          @app.call(env)
16  
-        end
17  
-      end
18  
-    end
19  
-  end
20  
-end
22  lib/vagrant/action/vm/discard_state.rb
... ...
@@ -1,22 +0,0 @@
1  
-module Vagrant
2  
-  module Action
3  
-    module VM
4  
-      # Discards the saved state of the VM if its saved. If its
5  
-      # not saved, does nothing.
6  
-      class DiscardState
7  
-        def initialize(app, env)
8  
-          @app = app
9  
-        end
10  
-
11  
-        def call(env)
12  
-          if env[:vm].state == :saved
13  
-            env[:ui].info I18n.t("vagrant.actions.vm.discard_state.discarding")
14  
-            env[:vm].driver.discard_saved_state
15  
-          end
16  
-
17  
-          @app.call(env)
18  
-        end
19  
-      end
20  
-    end
21  
-  end
22  
-end
26  lib/vagrant/action/vm/provisioner_cleanup.rb
... ...
@@ -1,26 +0,0 @@
1  
-module Vagrant
2  
-  module Action
3  
-    module VM
4  
-      class ProvisionerCleanup
5  
-        def initialize(app, env)
6  
-          @app = app
7  
-          @env = env
8  
-        end
9  
-
10  
-        def call(env)
11  
-          enabled_provisioners.each do |instance|
12  
-            instance.cleanup
13  
-          end
14  
-
15  
-          @app.call(env)
16  
-        end
17  
-
18  
-        def enabled_provisioners
19  
-          @env[:vm].config.vm.provisioners.map do |provisioner|
20  
-            provisioner.provisioner.new(@env, provisioner.config)
21  
-          end
22  
-        end
23  
-      end
24  
-    end
25  
-  end
26  
-end
7  lib/vagrant/communication.rb
... ...
@@ -1,7 +0,0 @@
1  
-module Vagrant
2  
-  module Communication
3  
-    autoload :Base, 'vagrant/communication/base'
4  
-
5  
-    autoload :SSH,  'vagrant/communication/ssh'
6  
-  end
7  
-end
63  lib/vagrant/communication/base.rb
... ...
@@ -1,63 +0,0 @@
1  
-module Vagrant
2  
-  module Communication
3  
-    # The base class for any classes that provide an API for communicating
4  
-    # with the virtual machine.
5  
-    #
6  
-    # There are various stages that require Vagrant to copy files or
7  
-    # run commands on the target system, and communication classes provide
8  
-    # the abstraction necessary to perform these tasks, via SSH or some
9  
-    # other mechanism.
10  
-    #
11  
-    # Any subclasses of this class **must** implement all of the methods
12  
-    # below.
13  
-    class Base
14  
-      # Checks if the target machine is ready for communication.
15  
-      #
16  
-      # @return [Boolean]
17  
-      def ready?
18  
-      end
19  
-
20  
-      # Download a file from the virtual machine to the local machine.
21  
-      #
22  
-      # @param [String] from Path of the file on the virtual machine.
23  
-      # @param [String] to Path to where to save the remote file.
24  
-      def download(from, to)
25  
-      end
26  
-
27  
-      # Upload a file to the virtual machine.
28  
-      #
29  
-      # @param [String] from Path to a file to upload.
30  
-      # @param [String] to Path to where to save this file.
31  
-      def upload(from, to)
32  
-      end
33  
-
34  
-      # Execute a command on the remote machine.
35  
-      #
36  
-      # @param [String] command Command to execute.
37  
-      # @yield [type, data] Realtime output of the command being executed.
38  
-      # @yieldparam [String] type Type of the output, `:stdout`, `:stderr`, etc.
39  
-      # @yieldparam [String] data Data for the given output.
40  
-      # @return [Integer] Exit code of the command.
41  
-      def execute(command, opts=nil)
42  
-      end
43  
-
44  
-      # Execute a comand with super user privileges.
45  
-      #
46  
-      # See #execute for parameter information.
47  
-      def sudo(command, opts=nil)
48  
-      end
49  
-
50  
-      # Executes a command and returns a boolean statement if it was successful
51  
-      # or not.
52  
-      #
53  
-      # This is implemented by default as expecting `execute` to return 0.
54  
-      def test(command, opts=nil)
55  
-        # Disable error checking no matter what
56  
-        opts = (opts || {}).merge(:error_check => false)
57  
-
58  
-        # Successful if the exit status is 0
59  
-        execute(command, opts) == 0
60  
-      end
61  
-    end
62  
-  end
63  
-end
3  lib/vagrant/downloaders/base.rb
@@ -14,9 +14,6 @@ def initialize(ui)
14 14
       # handle.
15 15
       def self.match?(url); false; end
16 16
 
17  
-      # Called prior to execution so any error checks can be done
18  
-      def prepare(source_url); end
19  
-
20 17
       # Downloads the source file to the destination file. It is up to
21 18
       # implementors of this class to handle the logic.
22 19
       def download!(source_url, destination_file); end
4  lib/vagrant/downloaders/file.rb
@@ -9,11 +9,9 @@ def self.match?(uri)
9 9
         ::File.file?(::File.expand_path(uri))
10 10
       end
11 11