Permalink
Browse files

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...
2 parents de73b65 + 1cdd69b commit 391dc392675c73518ebf04252d824fe916e8860b @mitchellh committed Aug 20, 2012
Showing with 4,156 additions and 2,915 deletions.
  1. +10 −15 lib/vagrant.rb
  2. +18 −43 lib/vagrant/action.rb
  3. +0 −31 lib/vagrant/action/box/add.rb
  4. +0 −84 lib/vagrant/action/box/download.rb
  5. +0 −24 lib/vagrant/action/box/verify.rb
  6. +10 −12 lib/vagrant/action/builder.rb
  7. +0 −157 lib/vagrant/action/builtin.rb
  8. +75 −0 lib/vagrant/action/builtin/box_add.rb
  9. +53 −0 lib/vagrant/action/builtin/call.rb
  10. +28 −0 lib/vagrant/action/builtin/confirm.rb
  11. +24 −0 lib/vagrant/action/builtin/env_set.rb
  12. +38 −0 lib/vagrant/action/builtin/ssh_exec.rb
  13. +43 −0 lib/vagrant/action/builtin/ssh_run.rb
  14. +0 −21 lib/vagrant/action/env/set.rb
  15. +0 −28 lib/vagrant/action/general/check_virtualbox.rb
  16. +4 −1 lib/vagrant/action/general/validate.rb
  17. +5 −25 lib/vagrant/action/runner.rb
  18. +0 −20 lib/vagrant/action/vm/destroy_unused_network_interfaces.rb
  19. +0 −22 lib/vagrant/action/vm/discard_state.rb
  20. +0 −26 lib/vagrant/action/vm/provisioner_cleanup.rb
  21. +0 −7 lib/vagrant/communication.rb
  22. +0 −63 lib/vagrant/communication/base.rb
  23. +0 −3 lib/vagrant/downloaders/base.rb
  24. +1 −3 lib/vagrant/downloaders/file.rb
  25. +0 −7 lib/vagrant/driver.rb
  26. +0 −140 lib/vagrant/driver/virtualbox.rb
  27. +0 −474 lib/vagrant/driver/virtualbox_4_0.rb
  28. +0 −474 lib/vagrant/driver/virtualbox_4_1.rb
  29. +0 −326 lib/vagrant/driver/virtualbox_base.rb
  30. +23 −14 lib/vagrant/environment.rb
  31. +12 −0 lib/vagrant/errors.rb
  32. +296 −0 lib/vagrant/machine.rb
  33. +2 −0 lib/vagrant/plugin/v1.rb
  34. +98 −0 lib/vagrant/plugin/v1/communicator.rb
  35. +2 −3 lib/vagrant/plugin/v1/guest.rb
  36. +31 −0 lib/vagrant/plugin/v1/plugin.rb
  37. +68 −0 lib/vagrant/plugin/v1/provider.rb
  38. +0 −128 lib/vagrant/ssh.rb
  39. +2 −2 lib/vagrant/util/safe_exec.rb
  40. +119 −0 lib/vagrant/util/ssh.rb
  41. +0 −205 lib/vagrant/vm.rb
  42. +5 −6 plugins/commands/box/command/add.rb
  43. +6 −44 plugins/commands/destroy/command.rb
  44. +2 −7 plugins/commands/halt/command.rb
  45. +22 −14 plugins/commands/package/command.rb
  46. +5 −19 plugins/commands/provision/command.rb
  47. +7 −13 plugins/commands/reload/command.rb
  48. +5 −13 plugins/commands/resume/command.rb
  49. +14 −38 plugins/commands/ssh/command.rb
  50. +9 −11 plugins/commands/ssh_config/command.rb
  51. +4 −12 plugins/commands/suspend/command.rb
  52. +7 −14 plugins/commands/up/command.rb
  53. +36 −24 lib/vagrant/communication/ssh.rb → plugins/communicators/ssh/communicator.rb
  54. +19 −0 plugins/communicators/ssh/plugin.rb
  55. +18 −16 plugins/guests/linux/guest.rb
  56. +289 −0 plugins/providers/virtualbox/action.rb
  57. +9 −14 {lib/vagrant/action/vm → plugins/providers/virtualbox/action}/boot.rb
  58. +5 −5 {lib/vagrant/action/vm → plugins/providers/virtualbox/action}/check_accessible.rb
  59. +9 −9 {lib/vagrant/action/vm → plugins/providers/virtualbox/action}/check_box.rb
  60. +21 −0 plugins/providers/virtualbox/action/check_created.rb
  61. +6 −8 {lib/vagrant/action/vm → plugins/providers/virtualbox/action}/check_guest_additions.rb
  62. +18 −18 {lib/vagrant/action/vm → plugins/providers/virtualbox/action}/check_port_collisions.rb
  63. +21 −0 plugins/providers/virtualbox/action/check_running.rb
  64. +22 −0 plugins/providers/virtualbox/action/check_virtualbox.rb
  65. +5 −5 {lib/vagrant/action/vm → plugins/providers/virtualbox/action}/clean_machine_folder.rb
  66. +4 −4 {lib/vagrant/action/vm → plugins/providers/virtualbox/action}/clear_forwarded_ports.rb
  67. +4 −4 {lib/vagrant/action/vm → plugins/providers/virtualbox/action}/clear_network_interfaces.rb
  68. +4 −5 {lib/vagrant/action/vm → plugins/providers/virtualbox/action}/clear_shared_folders.rb
  69. +20 −0 plugins/providers/virtualbox/action/created.rb
  70. +6 −6 {lib/vagrant/action/vm → plugins/providers/virtualbox/action}/customize.rb
  71. +5 −5 {lib/vagrant/action/vm → plugins/providers/virtualbox/action}/default_name.rb
  72. +5 −5 {lib/vagrant/action/vm → plugins/providers/virtualbox/action}/destroy.rb
  73. +16 −0 plugins/providers/virtualbox/action/destroy_confirm.rb
  74. +16 −0 plugins/providers/virtualbox/action/destroy_unused_network_interfaces.rb
  75. +20 −0 plugins/providers/virtualbox/action/discard_state.rb
  76. +6 −7 {lib/vagrant/action/vm → plugins/providers/virtualbox/action}/export.rb
  77. +7 −7 {lib/vagrant/action/vm → plugins/providers/virtualbox/action}/forward_ports.rb
  78. +9 −10 {lib/vagrant/action/vm → plugins/providers/virtualbox/action}/halt.rb
  79. +5 −5 {lib/vagrant/action/vm → plugins/providers/virtualbox/action}/host_name.rb
  80. +11 −15 {lib/vagrant/action/vm → plugins/providers/virtualbox/action}/import.rb
  81. +20 −0 plugins/providers/virtualbox/action/is_running.rb
  82. +20 −0 plugins/providers/virtualbox/action/is_saved.rb
  83. +5 −5 {lib/vagrant/action/vm → plugins/providers/virtualbox/action}/match_mac_address.rb
  84. +16 −0 plugins/providers/virtualbox/action/message_not_created.rb
  85. +16 −0 plugins/providers/virtualbox/action/message_not_running.rb
  86. +17 −0 plugins/providers/virtualbox/action/message_will_not_destroy.rb
  87. +22 −24 {lib/vagrant/action/vm → plugins/providers/virtualbox/action}/network.rb
  88. +16 −27 {lib/vagrant/action/vm → plugins/providers/virtualbox/action}/nfs.rb
  89. +4 −7 {lib/vagrant/action/vm → plugins/providers/virtualbox/action}/package.rb
  90. +5 −8 {lib/vagrant/action/vm → plugins/providers/virtualbox/action}/package_vagrantfile.rb
  91. +5 −4 {lib/vagrant/action/vm → plugins/providers/virtualbox/action}/provision.rb
  92. +25 −0 plugins/providers/virtualbox/action/provisioner_cleanup.rb
  93. +4 −4 {lib/vagrant/action/vm → plugins/providers/virtualbox/action}/prune_nfs_exports.rb
  94. +4 −4 {lib/vagrant/action/vm → plugins/providers/virtualbox/action}/resume.rb
  95. +8 −11 {lib/vagrant/action/vm → plugins/providers/virtualbox/action}/sane_defaults.rb
  96. +5 −8 {lib/vagrant/action/vm → plugins/providers/virtualbox/action}/setup_package_files.rb
  97. +12 −11 {lib/vagrant/action/vm → plugins/providers/virtualbox/action}/share_folders.rb
  98. +5 −5 {lib/vagrant/action/vm → plugins/providers/virtualbox/action}/suspend.rb
  99. +327 −0 plugins/providers/virtualbox/driver/base.rb
  100. +139 −0 plugins/providers/virtualbox/driver/meta.rb
  101. +476 −0 plugins/providers/virtualbox/driver/version_4_0.rb
  102. +476 −0 plugins/providers/virtualbox/driver/version_4_1.rb
  103. +28 −0 plugins/providers/virtualbox/plugin.rb
  104. +83 −0 plugins/providers/virtualbox/provider.rb
  105. +17 −0 templates/locales/en.yml
  106. +26 −0 test/unit/support/shared/base_context.rb
  107. +12 −12 test/unit/vagrant/action/builder_test.rb
  108. +55 −0 test/unit/vagrant/action/builtin/call_test.rb
  109. +21 −0 test/unit/vagrant/action/builtin/confirm_test.rb
  110. +20 −0 test/unit/vagrant/action/builtin/env_set_test.rb
  111. +55 −0 test/unit/vagrant/action/builtin/ssh_exec_test.rb
  112. +15 −9 test/unit/vagrant/action/runner_test.rb
  113. +0 −4 test/unit/vagrant/downloaders/base_test.rb
  114. +17 −9 test/unit/vagrant/downloaders/file_test.rb
  115. +13 −12 test/unit/vagrant/environment_test.rb
  116. +388 −0 test/unit/vagrant/machine_test.rb
  117. +9 −0 test/unit/vagrant/plugin/v1/communicator_test.rb
  118. +56 −0 test/unit/vagrant/plugin/v1/plugin_test.rb
  119. +18 −0 test/unit/vagrant/plugin/v1/provider_test.rb
  120. +0 −30 test/unit/vagrant/ssh_test.rb
  121. +30 −0 test/unit/vagrant/util/ssh_test.rb
  122. +2 −0 test/unit/vagrant_test.rb
View
@@ -66,7 +66,6 @@ module Vagrant
autoload :BoxCollection, 'vagrant/box_collection'
autoload :CLI, 'vagrant/cli'
autoload :Command, 'vagrant/command'
- autoload :Communication, 'vagrant/communication'
autoload :Config, 'vagrant/config'
autoload :DataStore, 'vagrant/data_store'
autoload :Downloaders, 'vagrant/downloaders'
@@ -76,27 +75,23 @@ module Vagrant
autoload :Errors, 'vagrant/errors'
autoload :Guest, 'vagrant/guest'
autoload :Hosts, 'vagrant/hosts'
+ autoload :Machine, 'vagrant/machine'
autoload :Plugin, 'vagrant/plugin'
- autoload :SSH, 'vagrant/ssh'
autoload :TestHelpers, 'vagrant/test_helpers'
autoload :UI, 'vagrant/ui'
autoload :Util, 'vagrant/util'
- autoload :VM, 'vagrant/vm'
# These are the various plugin versions and their components in
# a lazy loaded Hash-like structure.
- c = PLUGIN_COMPONENTS = Registry.new
- c.register(:"1") { Plugin::V1::Plugin }
- c.register([:"1", :command]) { Plugin::V1::Command }
- c.register([:"1", :config]) { Plugin::V1::Config }
- c.register([:"1", :guest]) { Plugin::V1::Guest }
- c.register([:"1", :host]) { Plugin::V1::Host }
- c.register([:"1", :provisioner]) { Plugin::V1::Provisioner }
-
- # Returns a `Vagrant::Registry` object that contains all the built-in
- # middleware stacks.
- def self.actions
- @actions ||= Vagrant::Action::Builtin.new
+ PLUGIN_COMPONENTS = Registry.new.tap do |c|
+ c.register(:"1") { Plugin::V1::Plugin }
+ c.register([:"1", :command]) { Plugin::V1::Command }
+ c.register([:"1", :communicator]) { Plugin::V1::Communicator }
+ c.register([:"1", :config]) { Plugin::V1::Config }
+ c.register([:"1", :guest]) { Plugin::V1::Guest }
+ c.register([:"1", :host]) { Plugin::V1::Host }
+ c.register([:"1", :provider]) { Plugin::V1::Provider }
+ c.register([:"1", :provisioner]) { Plugin::V1::Provisioner }
end
# The source root is the path to the root directory of
View
@@ -2,60 +2,35 @@
module Vagrant
module Action
- autoload :Builtin, 'vagrant/action/builtin'
autoload :Environment, 'vagrant/action/environment'
autoload :Runner, 'vagrant/action/runner'
autoload :Warden, 'vagrant/action/warden'
- module Box
- autoload :Add, 'vagrant/action/box/add'
- autoload :Download, 'vagrant/action/box/download'
- autoload :Verify, 'vagrant/action/box/verify'
- end
-
- module Env
- autoload :Set, 'vagrant/action/env/set'
+ # Builtin contains middleware classes that are shipped with Vagrant-core
+ # and are thus available to all plugins as a "standard library" of sorts.
+ module Builtin
+ autoload :BoxAdd, "vagrant/action/builtin/box_add"
+ autoload :Call, "vagrant/action/builtin/call"
+ autoload :Confirm, "vagrant/action/builtin/confirm"
+ autoload :EnvSet, "vagrant/action/builtin/env_set"
+ autoload :SSHExec, "vagrant/action/builtin/ssh_exec"
+ autoload :SSHRun, "vagrant/action/builtin/ssh_run"
end
module General
- autoload :CheckVirtualbox, 'vagrant/action/general/check_virtualbox'
autoload :Package, 'vagrant/action/general/package'
autoload :Validate, 'vagrant/action/general/validate'
end
- module VM
- autoload :Boot, 'vagrant/action/vm/boot'
- autoload :CheckAccessible, 'vagrant/action/vm/check_accessible'
- autoload :CheckBox, 'vagrant/action/vm/check_box'
- autoload :CheckGuestAdditions, 'vagrant/action/vm/check_guest_additions'
- autoload :CheckPortCollisions, 'vagrant/action/vm/check_port_collisions'
- autoload :CleanMachineFolder, 'vagrant/action/vm/clean_machine_folder'
- autoload :ClearForwardedPorts, 'vagrant/action/vm/clear_forwarded_ports'
- autoload :ClearNetworkInterfaces, 'vagrant/action/vm/clear_network_interfaces'
- autoload :ClearSharedFolders, 'vagrant/action/vm/clear_shared_folders'
- autoload :Customize, 'vagrant/action/vm/customize'
- autoload :DefaultName, 'vagrant/action/vm/default_name'
- autoload :Destroy, 'vagrant/action/vm/destroy'
- autoload :DestroyUnusedNetworkInterfaces, 'vagrant/action/vm/destroy_unused_network_interfaces'
- autoload :DiscardState, 'vagrant/action/vm/discard_state'
- autoload :Export, 'vagrant/action/vm/export'
- autoload :ForwardPorts, 'vagrant/action/vm/forward_ports'
- autoload :Halt, 'vagrant/action/vm/halt'
- autoload :HostName, 'vagrant/action/vm/host_name'
- autoload :Import, 'vagrant/action/vm/import'
- autoload :MatchMACAddress, 'vagrant/action/vm/match_mac_address'
- autoload :Network, 'vagrant/action/vm/network'
- autoload :NFS, 'vagrant/action/vm/nfs'
- autoload :Package, 'vagrant/action/vm/package'
- autoload :PackageVagrantfile, 'vagrant/action/vm/package_vagrantfile'
- autoload :Provision, 'vagrant/action/vm/provision'
- autoload :ProvisionerCleanup, 'vagrant/action/vm/provisioner_cleanup'
- autoload :PruneNFSExports, 'vagrant/action/vm/prune_nfs_exports'
- autoload :Resume, 'vagrant/action/vm/resume'
- autoload :SaneDefaults, 'vagrant/action/vm/sane_defaults'
- autoload :ShareFolders, 'vagrant/action/vm/share_folders'
- autoload :SetupPackageFiles, 'vagrant/action/vm/setup_package_files'
- autoload :Suspend, 'vagrant/action/vm/suspend'
+ # This is the action that will add a box from a URL. This middleware
+ # sequence is built-in to Vagrant. Plugins can hook into this like any
+ # other middleware sequence. This is particularly useful for provider
+ # plugins, which can hook in to do things like verification of boxes
+ # that are downloaded.
+ def self.action_box_add
+ Builder.new.tap do |b|
+ b.use Builtin::BoxAdd
+ end
end
end
end
@@ -1,31 +0,0 @@
-module Vagrant
- module Action
- module Box
- # Adds a downloaded box file to the environment's box collection.
- # This handles unpacking the box. See {BoxCollection#add} for more
- # information.
- class Add
- def initialize(app, env)
- @app = app
- @env = env
- end
-
- def call(env)
- @env[:ui].info I18n.t("vagrant.actions.box.add.adding", :name => env[:box_name])
-
- begin
- env[:box_collection].add(env[:box_download_temp_path], env[:box_name])
- rescue Vagrant::Errors::BoxUpgradeRequired
- # Upgrade the box
- env[:box_collection].upgrade(env[:box_name])
-
- # Try adding it again
- retry
- end
-
- @app.call(env)
- end
- end
- end
- end
-end
@@ -1,84 +0,0 @@
-module Vagrant
- module Action
- module Box
- class Download
- BASENAME = "box"
-
- include Util
-
- attr_reader :temp_path
-
- def initialize(app, env)
- @app = app
- @env = env
- @env["download.classes"] ||= []
- @env["download.classes"] += [Downloaders::HTTP, Downloaders::File]
- @downloader = nil
- end
-
- def call(env)
- @env = env
-
- download if instantiate_downloader
- @app.call(@env)
-
- recover(env) # called in both cases to cleanup workspace
- end
-
- def instantiate_downloader
- # Assign to a temporary variable since this is easier to type out,
- # since it is used so many times.
- classes = @env["download.classes"]
-
- # Find the class to use.
- classes.each_index do |i|
- klass = classes[i]
-
- # Use the class if it matches the given URI or if this
- # is the last class...
- if classes.length == (i + 1) || klass.match?(@env[:box_url])
- @env[:ui].info I18n.t("vagrant.actions.box.download.with", :class => klass.to_s)
- @downloader = klass.new(@env[:ui])
- break
- end
- end
-
- # This line should never be reached, but we'll keep this here
- # just in case for now.
- raise Errors::BoxDownloadUnknownType if !@downloader
-
- @downloader.prepare(@env[:box_url])
- true
- end
-
- def download
- with_tempfile do |tempfile|
- download_to(tempfile)
- @temp_path = @env[:box_download_temp_path] = tempfile.path
- end
- end
-
- def recover(env)
- if temp_path && File.exist?(temp_path)
- env[:ui].info I18n.t("vagrant.actions.box.download.cleaning")
- File.unlink(temp_path)
- end
- end
-
- def with_tempfile
- File.open(box_temp_path, Platform.tar_file_options) do |tempfile|
- yield tempfile
- end
- end
-
- def box_temp_path
- @env[:tmp_path].join(BASENAME + Time.now.to_i.to_s)
- end
-
- def download_to(f)
- @downloader.download!(@env[:box_url], f)
- end
- end
- end
- end
-end
@@ -1,24 +0,0 @@
-module Vagrant
- module Action
- module Box
- class Verify
- def initialize(app, env)
- @app = app
- @env = env
- end
-
- def call(env)
- @env[:ui].info I18n.t("vagrant.actions.box.verify.verifying")
-
- box = env[:box_collection].find(env[:box_name], :virtualbox)
- driver = Driver::VirtualBox.new(nil)
- if !driver.verify_image(box.directory.join("box.ovf").to_s)
- raise Errors::BoxVerificationFailed
- end
-
- @app.call(env)
- end
- end
- end
- end
-end
@@ -9,18 +9,21 @@ module Action
#
# Building an action sequence is very easy:
#
- # app = Vagrant::Action::Builder.new do
- # use MiddlewareA
- # use MiddlewareB
+ # app = Vagrant::Action::Builder.new.tap do |b|
+ # b.use MiddlewareA
+ # b.use MiddlewareB
# end
#
# Vagrant::Action.run(app)
#
class Builder
- # Initializes the builder. An optional block can be passed which
- # will be evaluated in the context of the instance.
- def initialize(&block)
- instance_eval(&block) if block_given?
+ # This is a shortcut for a middleware sequence with only one item
+ # in it. For a description of the arguments and the documentation, please
+ # see {#use} instead.
+ #
+ # @return [Builder]
+ def self.build(middleware, *args, &block)
+ new.use(middleware, *args, &block)
end
# Returns a mergeable version of the builder. If `use` is called with
@@ -38,11 +41,6 @@ def flatten
#
# @param [Class] middleware The middleware class
def use(middleware, *args, &block)
- # Prepend with a environment setter if args are given
- if !args.empty? && args.first.is_a?(Hash) && middleware != Env::Set
- self.use(Env::Set, args.shift, &block)
- end
-
if middleware.kind_of?(Builder)
# Merge in the other builder's stack into our own
self.stack.concat(middleware.stack)
Oops, something went wrong. Retry.

14 comments on commit 391dc39

@pearkes
Collaborator

🎉

@puffnfresh

👍

@rick
rick commented on 391dc39 Aug 20, 2012

🆒 🤘 🎸 🔥

@auser
auser commented on 391dc39 Aug 20, 2012

YES! CONGRATS!!!!!

@ShepBook

👍

@myusuf3

🍰

@dekz
dekz commented on 391dc39 Aug 20, 2012

Congrats on the milestone

@axsuul
axsuul commented on 391dc39 Aug 20, 2012

Congratulations Mitchell! You're doing great work

@macarthy

Great start, I'll mention that in my vagrant talk next week

@daenney

Way to go!

@dol
dol commented on 391dc39 Aug 20, 2012

👍

@frankscholten

Awesome!

@martinlauer

n1

Please sign in to comment.