Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
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...
commit 391dc392675c73518ebf04252d824fe916e8860b 2 parents de73b65 + 1cdd69b
@mitchellh authored
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
25 lib/vagrant.rb
@@ -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
61 lib/vagrant/action.rb
@@ -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
View
31 lib/vagrant/action/box/add.rb
@@ -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
View
84 lib/vagrant/action/box/download.rb
@@ -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
View
24 lib/vagrant/action/box/verify.rb
@@ -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
View
22 lib/vagrant/action/builder.rb
@@ -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)
View
157 lib/vagrant/action/builtin.rb
@@ -1,157 +0,0 @@
-module Vagrant
- module Action
- # A registry object containing the built-in middleware stacks.
- class Builtin < Registry
- def initialize
- # Properly initialize the registry object
- super
-
- # Register all the built-in stacks
- register_builtin!
- end
-
- protected
-
- def register_builtin!
- # We do this so that the blocks below have a variable to access the
- # outer registry.
- registry = self
-
- # provision - Provisions a running VM
- register(:provision) do
- Builder.new do
- use General::CheckVirtualbox
- use General::Validate
- use VM::CheckAccessible
- use VM::Provision
- end
- end
-
- # start - Starts a VM, assuming it already exists on the
- # environment.
- register(:start) do
- Builder.new do
- use General::CheckVirtualbox
- use General::Validate
- use VM::CheckAccessible
- use VM::CleanMachineFolder
- use VM::ClearForwardedPorts
- use VM::CheckPortCollisions, :port_collision_handler => :correct
- use VM::ForwardPorts
- use VM::Provision
- use VM::PruneNFSExports
- use VM::NFS
- use VM::ClearSharedFolders
- use VM::ShareFolders
- use VM::ClearNetworkInterfaces
- use VM::Network
- use VM::HostName
- use VM::SaneDefaults
- use VM::Customize
- use VM::Boot
- end
- end
-
- # halt - Halts the VM, attempting gracefully but then forcing
- # a restart if fails.
- register(:halt) do
- Builder.new do
- use General::CheckVirtualbox
- use General::Validate
- use VM::CheckAccessible
- use VM::DiscardState
- use VM::Halt
- end
- end
-
- # suspend - Suspends the VM
- register(:suspend) do
- Builder.new do
- use General::CheckVirtualbox
- use General::Validate
- use VM::CheckAccessible
- use VM::Suspend
- end
- end
-
- # resume - Resume a VM
- register(:resume) do
- Builder.new do
- use General::CheckVirtualbox
- use General::Validate
- use VM::CheckAccessible
- use VM::CheckPortCollisions
- use VM::Resume
- end
- end
-
- # reload - Halts then restarts the VM
- register(:reload) do
- Builder.new do
- use General::CheckVirtualbox
- use General::Validate
- use VM::CheckAccessible
- use registry.get(:halt)
- use registry.get(:start)
- end
- end
-
- # up - Imports, prepares, then starts a fresh VM.
- register(:up) do
- Builder.new do
- use General::CheckVirtualbox
- use General::Validate
- use VM::CheckAccessible
- use VM::CheckBox
- use VM::Import
- use VM::CheckGuestAdditions
- use VM::DefaultName
- use VM::MatchMACAddress
- use registry.get(:start)
- end
- end
-
- # destroy - Halts, cleans up, and destroys an existing VM
- register(:destroy) do
- Builder.new do
- use General::CheckVirtualbox
- use General::Validate
- use VM::CheckAccessible
- use registry.get(:halt), :force => true
- use VM::ProvisionerCleanup
- use VM::PruneNFSExports
- use VM::Destroy
- use VM::CleanMachineFolder
- use VM::DestroyUnusedNetworkInterfaces
- end
- end
-
- # package - Export and package the VM
- register(:package) do
- Builder.new do
- use General::CheckVirtualbox
- use General::Validate
- use VM::SetupPackageFiles
- use VM::CheckAccessible
- use registry.get(:halt)
- use VM::ClearForwardedPorts
- use VM::ClearSharedFolders
- use VM::Export
- use VM::PackageVagrantfile
- use VM::Package
- end
- end
-
- # box_add - Download and add a box.
- register(:box_add) do
- Builder.new do
- use General::CheckVirtualbox
- use Box::Download
- use Box::Add
- use Box::Verify
- end
- end
- end
- end
- end
-end
View
75 lib/vagrant/action/builtin/box_add.rb
@@ -0,0 +1,75 @@
+require "vagrant/util/platform"
+
+module Vagrant
+ module Action
+ module Builtin
+ # This middleware will download a remote box and add it to the
+ # given box collection.
+ class BoxAdd
+ def initialize(app, env)
+ @app = app
+ end
+
+ def call(env)
+ # Instantiate the downloader
+ downloader = download_klass(env[:box_url]).new(env[:ui])
+ env[:ui].info I18n.t("vagrant.actions.box.download.with",
+ :class => downloader.class.to_s)
+
+ # Download the box to a temporary path. We store the temporary
+ # path as an instance variable so that the `#recover` method can
+ # access it.
+ @temp_path = env[:tmp_path].join("box" + Time.now.to_i.to_s)
+ File.open(@temp_path, Vagrant::Util::Platform.tar_file_options) do |f|
+ downloader.download!(env[:box_url], f)
+ end
+
+ # Add the box
+ env[:ui].info I18n.t("vagrant.actions.box.add.adding", :name => env[:box_name])
+ begin
+ env[:box_collection].add(@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
+
+ # Call the 'recover' method in all cases to clean up the
+ # downloaded temporary file.
+ recover(env)
+
+ # Carry on!
+ @app.call(env)
+ end
+
+ def download_klass(url)
+ # This is hardcoded for now. In the future I'd like to make this
+ # pluginnable as well.
+ classes = [Downloaders::HTTP, Downloaders::File]
+
+ # 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...
+ return klass if classes.length == (i + 1) || klass.match?(url)
+ end
+
+ # If no downloader knows how to download this file, then we
+ # raise an exception.
+ raise Errors::BoxDownloadUnknownType
+ 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
+ end
+ end
+ end
+end
View
53 lib/vagrant/action/builtin/call.rb
@@ -0,0 +1,53 @@
+module Vagrant
+ module Action
+ module Builtin
+ # This middleware class allows a sort of "conditional" run within
+ # a single middlware sequence. It takes another middleware runnable,
+ # runs it with the same environment, then yields the resulting env to a block,
+ # allowing that block to determine the next course of action in the
+ # middleware sequence.
+ #
+ # The first argument to this middleware sequence is anywhere middleware
+ # runnable, whether it be a class, lambda, or something else that
+ # responds to `call`. This middleware runnable is run with the same
+ # environment as this class.
+ #
+ # After running, {Call} takes the environment and yields it to a block
+ # given to initialize the class, along with an instance of {Builder}.
+ # The result is used to build up a new sequence on the given builder.
+ # This builder is then run.
+ class Call
+ # For documentation, read the description of the {Call} class.
+ #
+ # @param [Object] callable A valid middleware runnable object. This
+ # can be a class, a lambda, or an object that responds to `call`.
+ # @yield [result, builder] This block is expected to build on `builder`
+ # which is the next middleware sequence that will be run.
+ def initialize(app, env, callable, &block)
+ raise ArgumentError, "A block must be given to Call" if !block
+
+ @app = app
+ @callable = callable
+ @block = block
+ end
+
+ def call(env)
+ runner = Runner.new
+
+ # Run our callable with our environment
+ new_env = runner.run(@callable, env)
+
+ # Build our new builder based on the result
+ builder = Builder.new
+ @block.call(new_env, builder)
+
+ # Run the result with our new environment
+ final_env = runner.run(builder, new_env)
+
+ # Call the next step using our final environment
+ @app.call(final_env)
+ end
+ end
+ end
+ end
+end
View
28 lib/vagrant/action/builtin/confirm.rb
@@ -0,0 +1,28 @@
+module Vagrant
+ module Action
+ module Builtin
+ # This class asks the user to confirm some sort of question with
+ # a "Y/N" question. The only parameter is the text to ask the user.
+ # The result is placed in `env[:result]` so that it can be used
+ # with the {Call} class.
+ class Confirm
+ # For documentation, read the description of the {Confirm} class.
+ #
+ # @param [String] message The message to ask the user.
+ def initialize(app, env, message)
+ @app = app
+ @message = message
+ end
+
+ def call(env)
+ # Ask the user the message and store the result
+ choice = nil
+ choice = env[:ui].ask(@message)
+ env[:result] = choice && choice.upcase == "Y"
+
+ @app.call(env)
+ end
+ end
+ end
+ end
+end
View
24 lib/vagrant/action/builtin/env_set.rb
@@ -0,0 +1,24 @@
+module Vagrant
+ module Action
+ module Builtin
+ # This middleware class allows you to modify the environment hash
+ # in the middle of a middleware sequence. The new environmental data
+ # will take affect at this stage in the middleware and will persist
+ # through.
+ class EnvSet
+ def initialize(app, env, new_env=nil)
+ @app = app
+ @new_env = new_env || {}
+ end
+
+ def call(env)
+ # Merge in the new data
+ env.merge!(@new_env)
+
+ # Carry on
+ @app.call(env)
+ end
+ end
+ end
+ end
+end
View
38 lib/vagrant/action/builtin/ssh_exec.rb
@@ -0,0 +1,38 @@
+require "vagrant/util/ssh"
+
+module Vagrant
+ module Action
+ module Builtin
+ # This class will exec into a full fledged SSH console into the
+ # remote machine. This middleware assumes that the VM is running and
+ # ready for SSH, and uses the {Machine#ssh_info} method to retrieve
+ # SSH information necessary to connect.
+ #
+ # Note: If there are any middleware after `SSHExec`, they will **not**
+ # run, since exec replaces the currently running process.
+ class SSHExec
+ # For quick access to the `SSH` class.
+ include Vagrant::Util
+
+ def initialize(app, env)
+ @app = app
+ end
+
+ def call(env)
+ # Grab the SSH info from the machine
+ info = env[:machine].ssh_info
+
+ # If the result is nil, then the machine is telling us that it is
+ # not yet ready for SSH, so we raise this exception.
+ raise Errors::SSHNotReady if info.nil?
+
+ # Check the SSH key permissions
+ SSH.check_key_permissions(info[:private_key_path])
+
+ # Exec!
+ SSH.exec(info, env[:ssh_opts])
+ end
+ end
+ end
+ end
+end
View
43 lib/vagrant/action/builtin/ssh_run.rb
@@ -0,0 +1,43 @@
+require "log4r"
+
+module Vagrant
+ module Action
+ module Builtin
+ # This class will run a single command on the remote machine and will
+ # mirror the output to the UI. The resulting exit status of the command
+ # will exist in the `:ssh_run_exit_status` key in the environment.
+ class SSHRun
+ def initialize(app, env)
+ @app = app
+ @logger = Log4r::Logger.new("vagrant::action::builtin::ssh_run")
+ end
+
+ def call(env)
+ command = env[:ssh_run_command]
+
+ @logger.debug("Executing command: #{command}")
+ exit_status = 0
+ exit_status = env[:machine].communicate.execute(command, :error_check => false) do |type, data|
+ # Determine the proper channel to send the output onto depending
+ # on the type of data we are receiving.
+ channel = type == :stdout ? :out : :error
+
+ # Print the output as it comes in, but don't prefix it and don't
+ # force a new line so that the output is properly preserved however
+ # it may be formatted.
+ env[:ui].info(data.to_s,
+ :prefix => false,
+ :new_line => false,
+ :channel => channel)
+ end
+
+ # Set the exit status on a known environmental variable
+ env[:ssh_run_exit_status] = exit_status
+
+ # Call the next middleware
+ @app.call(env)
+ end
+ end
+ end
+ end
+end
View
21 lib/vagrant/action/env/set.rb
@@ -1,21 +0,0 @@
-module Vagrant
- module Action
- module Env
- # A middleware which just sets up the environment with some
- # options which are passed to it.
- class Set
- def initialize(app, env, options=nil)
- @app = app
- @options = options || {}
- end
-
- def call(env)
- # Merge the options that were given to us
- env.merge!(@options)
-
- @app.call(env)
- end
- end
- end
- end
-end
View
28 lib/vagrant/action/general/check_virtualbox.rb
@@ -1,28 +0,0 @@
-module Vagrant
- module Action
- module General
- # Checks that virtualbox is installed and ready to be used.
- class CheckVirtualbox
- def initialize(app, env)
- @app = app
- end
-
- def call(env)
- # Certain actions may not actually have a VM, and thus no
- # driver, so we have to be clever about obtaining an instance
- # of the driver.
- driver = nil
- driver = env[:vm].driver if env[:vm]
- driver = Driver::VirtualBox.new(nil) if !driver
-
- # Verify that it is ready to go! This will raise an exception
- # if anything goes wrong.
- driver.verify!
-
- # Carry on.
- @app.call(env)
- end
- end
- end
- end
-end
View
5 lib/vagrant/action/general/validate.rb
@@ -9,7 +9,10 @@ def initialize(app, env)
end
def call(env)
- env[:vm].config.validate!(env[:vm].env) if !env.has_key?("validate") || env["validate"]
+ if !env.has_key?(:validate) || env[:validate]
+ env[:machine].config.validate!(env[:machine].env)
+ end
+
@app.call(env)
end
end
View
30 lib/vagrant/action/runner.rb
@@ -10,8 +10,7 @@ module Action
class Runner
@@reported_interrupt = false
- def initialize(registry, globals=nil, &block)
- @registry = registry
+ def initialize(globals=nil, &block)
@globals = globals || {}
@lazy_globals = block
@logger = Log4r::Logger.new("vagrant::action::runner")
@@ -19,8 +18,7 @@ def initialize(registry, globals=nil, &block)
def run(callable_id, options=nil)
callable = callable_id
- callable = Builder.new.use(callable_id) if callable_id.kind_of?(Class)
- callable = registry_sequence(callable_id) if callable_id.kind_of?(Symbol)
+ callable = Builder.build(callable_id) if callable_id.kind_of?(Class)
raise ArgumentError, "Argument to run must be a callable object or registered action." if !callable || !callable.respond_to?(:call)
# Create the initial environment with the options given
@@ -47,28 +45,10 @@ def run(callable_id, options=nil)
# We place a process lock around every action that is called
@logger.info("Running action: #{callable_id}")
Util::Busy.busy(int_callback) { callable.call(environment) }
- end
-
- protected
-
- def registry_sequence(id)
- # Attempt to get the sequence
- seq = @registry.get(id)
- return nil if !seq
-
- # Go through all the registered plugins and get all the hooks
- # for this sequence.
- Vagrant.plugin("1").registered.each do |plugin|
- hooks = plugin.action_hook(Vagrant::Plugin::V1::Plugin::ALL_ACTIONS)
- hooks += plugin.action_hook(id)
-
- hooks.each do |hook|
- hook.call(seq)
- end
- end
- # Return the sequence
- seq
+ # Return the environment in case there are things in there that
+ # the caller wants to use.
+ environment
end
end
end
View
20 lib/vagrant/action/vm/destroy_unused_network_interfaces.rb
@@ -1,20 +0,0 @@
-module Vagrant
- module Action
- module VM
- # Destroys the unused host only interfaces. This middleware cleans
- # up any created host only networks.
- class DestroyUnusedNetworkInterfaces
- def initialize(app, env)
- @app = app
- end
-
- def call(env)
- env[:vm].driver.delete_unused_host_only_networks
-
- # Continue along
- @app.call(env)
- end
- end
- end
- end
-end
View
22 lib/vagrant/action/vm/discard_state.rb
@@ -1,22 +0,0 @@
-module Vagrant
- module Action
- module VM
- # Discards the saved state of the VM if its saved. If its
- # not saved, does nothing.
- class DiscardState
- def initialize(app, env)
- @app = app
- end
-
- def call(env)
- if env[:vm].state == :saved
- env[:ui].info I18n.t("vagrant.actions.vm.discard_state.discarding")
- env[:vm].driver.discard_saved_state
- end
-
- @app.call(env)
- end
- end
- end
- end
-end
View
26 lib/vagrant/action/vm/provisioner_cleanup.rb
@@ -1,26 +0,0 @@
-module Vagrant
- module Action
- module VM
- class ProvisionerCleanup
- def initialize(app, env)
- @app = app
- @env = env
- end
-
- def call(env)
- enabled_provisioners.each do |instance|
- instance.cleanup
- end
-
- @app.call(env)
- end
-
- def enabled_provisioners
- @env[:vm].config.vm.provisioners.map do |provisioner|
- provisioner.provisioner.new(@env, provisioner.config)
- end
- end
- end
- end
- end
-end
View
7 lib/vagrant/communication.rb
@@ -1,7 +0,0 @@
-module Vagrant
- module Communication
- autoload :Base, 'vagrant/communication/base'
-
- autoload :SSH, 'vagrant/communication/ssh'
- end
-end
View
63 lib/vagrant/communication/base.rb
@@ -1,63 +0,0 @@
-module Vagrant
- module Communication
- # The base class for any classes that provide an API for communicating
- # with the virtual machine.
- #
- # There are various stages that require Vagrant to copy files or
- # run commands on the target system, and communication classes provide
- # the abstraction necessary to perform these tasks, via SSH or some
- # other mechanism.
- #
- # Any subclasses of this class **must** implement all of the methods
- # below.
- class Base
- # Checks if the target machine is ready for communication.
- #
- # @return [Boolean]
- def ready?
- end
-
- # Download a file from the virtual machine to the local machine.
- #
- # @param [String] from Path of the file on the virtual machine.
- # @param [String] to Path to where to save the remote file.
- def download(from, to)
- end
-
- # Upload a file to the virtual machine.
- #
- # @param [String] from Path to a file to upload.
- # @param [String] to Path to where to save this file.
- def upload(from, to)
- end
-
- # Execute a command on the remote machine.
- #
- # @param [String] command Command to execute.
- # @yield [type, data] Realtime output of the command being executed.
- # @yieldparam [String] type Type of the output, `:stdout`, `:stderr`, etc.
- # @yieldparam [String] data Data for the given output.
- # @return [Integer] Exit code of the command.
- def execute(command, opts=nil)
- end
-
- # Execute a comand with super user privileges.
- #
- # See #execute for parameter information.
- def sudo(command, opts=nil)
- end
-
- # Executes a command and returns a boolean statement if it was successful
- # or not.
- #
- # This is implemented by default as expecting `execute` to return 0.
- def test(command, opts=nil)
- # Disable error checking no matter what
- opts = (opts || {}).merge(:error_check => false)
-
- # Successful if the exit status is 0
- execute(command, opts) == 0
- end
- end
- end
-end
View
3  lib/vagrant/downloaders/base.rb
@@ -14,9 +14,6 @@ def initialize(ui)
# handle.
def self.match?(url); false; end
- # Called prior to execution so any error checks can be done
- def prepare(source_url); end
-
# Downloads the source file to the destination file. It is up to
# implementors of this class to handle the logic.
def download!(source_url, destination_file); end
View
4 lib/vagrant/downloaders/file.rb
@@ -9,11 +9,9 @@ def self.match?(uri)
::File.file?(::File.expand_path(uri))
end
- def prepare(source_url)
+ def download!(source_url, destination_file)
raise Errors::DownloaderFileDoesntExist if !::File.file?(::File.expand_path(source_url))
- end
- def download!(source_url, destination_file)
@ui.info I18n.t("vagrant.downloaders.file.download")
FileUtils.cp(::File.expand_path(source_url), destination_file.path)
end
View
7 lib/vagrant/driver.rb
@@ -1,7 +0,0 @@
-module Vagrant
- module Driver
- autoload :VirtualBox, 'vagrant/driver/virtualbox'
- autoload :VirtualBox_4_0, 'vagrant/driver/virtualbox_4_0'
- autoload :VirtualBox_4_1, 'vagrant/driver/virtualbox_4_1'
- end
-end
View
140 lib/vagrant/driver/virtualbox.rb
@@ -1,140 +0,0 @@
-require 'forwardable'
-
-require 'log4r'
-
-require 'vagrant/driver/virtualbox_base'
-
-module Vagrant
- module Driver
- # This class contains the logic to drive VirtualBox.
- #
- # Read the VirtualBoxBase source for documentation on each method.
- class VirtualBox < VirtualBoxBase
- # This is raised if the VM is not found when initializing a driver
- # with a UUID.
- class VMNotFound < StandardError; end
-
- # We use forwardable to do all our driver forwarding
- extend Forwardable
-
- # The UUID of the virtual machine we represent
- attr_reader :uuid
-
- # The version of virtualbox that is running.
- attr_reader :version
-
- def initialize(uuid=nil)
- # Setup the base
- super()
-
- @logger = Log4r::Logger.new("vagrant::driver::virtualbox")
- @uuid = uuid
-
- # Read and assign the version of VirtualBox we know which
- # specific driver to instantiate.
- begin
- @version = read_version || ""
- rescue Subprocess::LaunchError
- # This means that VirtualBox was not found, so we raise this
- # error here.
- raise Errors::VirtualBoxNotDetected
- end
-
- # Instantiate the proper version driver for VirtualBox
- @logger.debug("Finding driver for VirtualBox version: #{@version}")
- driver_map = {
- "4.0" => VirtualBox_4_0,
- "4.1" => VirtualBox_4_1
- }
-
- driver_klass = nil
- driver_map.each do |key, klass|
- if @version.start_with?(key)
- driver_klass = klass
- break
- end
- end
-
- if !driver_klass
- supported_versions = driver_map.keys.sort.join(", ")
- raise Errors::VirtualBoxInvalidVersion, :supported_versions => supported_versions
- end
-
- @logger.info("Using VirtualBox driver: #{driver_klass}")
- @driver = driver_klass.new(@uuid)
-
- if @uuid
- # Verify the VM exists, and if it doesn't, then don't worry
- # about it (mark the UUID as nil)
- raise VMNotFound if !@driver.vm_exists?(@uuid)
- end
- end
-
- def_delegators :@driver, :clear_forwarded_ports,
- :clear_shared_folders,
- :create_dhcp_server,
- :create_host_only_network,
- :delete,
- :delete_unused_host_only_networks,
- :discard_saved_state,
- :enable_adapters,
- :execute_command,
- :export,
- :forward_ports,
- :halt,
- :import,
- :read_forwarded_ports,
- :read_bridged_interfaces,
- :read_guest_additions_version,
- :read_host_only_interfaces,
- :read_mac_address,
- :read_mac_addresses,
- :read_machine_folder,
- :read_network_interfaces,
- :read_state,
- :read_used_ports,
- :read_vms,
- :set_mac_address,
- :set_name,
- :share_folders,
- :ssh_port,
- :start,
- :suspend,
- :verify!,
- :verify_image,
- :vm_exists?
-
- protected
-
- # This returns the version of VirtualBox that is running.
- #
- # @return [String]
- def read_version
- # The version string is usually in one of the following formats:
- #
- # * 4.1.8r1234
- # * 4.1.8r1234_OSE
- # * 4.1.8_MacPortsr1234
- #
- # Below accounts for all of these.
-
- # Note: We split this into multiple lines because apparently "".split("_")
- # is [], so we have to check for an empty array in between.
- output = execute("--version")
- if output =~ /vboxdrv kernel module is not loaded/
- raise Errors::VirtualBoxKernelModuleNotLoaded
- elsif output =~ /Please install/
- # Check for installation incomplete warnings, for example:
- # "WARNING: The character device /dev/vboxdrv does not
- # exist. Please install the virtualbox-ose-dkms package and
- # the appropriate headers, most likely linux-headers-generic."
- raise Errors::VirtualBoxInstallIncomplete
- end
-
- parts = output.split("_")
- return nil if parts.empty?
- parts[0].split("r")[0]
- end
- end
- end
-end
View
474 lib/vagrant/driver/virtualbox_4_0.rb
@@ -1,474 +0,0 @@
-require 'log4r'
-
-require 'vagrant/driver/virtualbox_base'
-
-module Vagrant
- module Driver
- # Driver for VirtualBox 4.0.x
- class VirtualBox_4_0 < VirtualBoxBase
- def initialize(uuid)
- super()
-
- @logger = Log4r::Logger.new("vagrant::driver::virtualbox_4_0")
- @uuid = uuid
- end
-
- def clear_forwarded_ports
- args = []
- read_forwarded_ports(@uuid).each do |nic, name, _, _|
- args.concat(["--natpf#{nic}", "delete", name])
- end
-
- execute("modifyvm", @uuid, *args) if !args.empty?
- end
-
- def clear_shared_folders
- info = execute("showvminfo", @uuid, "--machinereadable", :retryable => true)
- info.split("\n").each do |line|
- if name = line[/^SharedFolderNameMachineMapping\d+="(.+?)"$/, 1]
- execute("sharedfolder", "remove", @uuid, "--name", name)
- end
- end
- end
-
- def create_dhcp_server(network, options)
- execute("dhcpserver", "add", "--ifname", network,
- "--ip", options[:dhcp_ip],
- "--netmask", options[:netmask],
- "--lowerip", options[:dhcp_lower],
- "--upperip", options[:dhcp_upper],
- "--enable")
- end
-
- def create_host_only_network(options)
- # Create the interface
- interface = execute("hostonlyif", "create")
- name = interface[/^Interface '(.+?)' was successfully created$/, 1]
-
- # Configure it
- execute("hostonlyif", "ipconfig", name,
- "--ip", options[:adapter_ip],
- "--netmask", options[:netmask])
-
- # Return the details
- return {
- :name => name,
- :ip => options[:adapter_ip],
- :netmask => options[:netmask],
- :dhcp => nil
- }
- end
-
- def delete
- execute("unregistervm", @uuid, "--delete")
- end
-
- def delete_unused_host_only_networks
- networks = []
- execute("list", "hostonlyifs").split("\n").each do |line|
- if network_name = line[/^Name:\s+(.+?)$/, 1]
- networks << network_name
- end
- end
-
- execute("list", "vms").split("\n").each do |line|
- if vm_name = line[/^".+?"\s+\{(.+?)\}$/, 1]
- info = execute("showvminfo", vm_name, "--machinereadable", :retryable => true)
- info.split("\n").each do |line|
- if network_name = line[/^hostonlyadapter\d+="(.+?)"$/, 1]
- networks.delete(network_name)
- end
- end
- end
- end
-
- networks.each do |name|
- # First try to remove any DHCP servers attached. We use `raw` because
- # it is okay if this fails. It usually means that a DHCP server was
- # never attached.
- raw("dhcpserver", "remove", "--ifname", name)
-
- # Delete the actual host only network interface.
- execute("hostonlyif", "remove", name)
- end
- end
-
- def discard_saved_state
- execute("discardstate", @uuid)
- end
-
- def enable_adapters(adapters)
- args = []
- adapters.each do |adapter|
- args.concat(["--nic#{adapter[:adapter]}", adapter[:type].to_s])
-
- if adapter[:bridge]
- args.concat(["--bridgeadapter#{adapter[:adapter]}",
- adapter[:bridge]])
- end
-
- if adapter[:hostonly]
- args.concat(["--hostonlyadapter#{adapter[:adapter]}",
- adapter[:hostonly]])
- end
-
- if adapter[:mac_address]
- args.concat(["--macaddress#{adapter[:adapter]}",
- adapter[:mac_address]])
- end
-
- if adapter[:nic_type]
- args.concat(["--nictype#{adapter[:adapter]}", adapter[:nic_type].to_s])
- end
- end
-
- execute("modifyvm", @uuid, *args)
- end
-
- def execute_command(command)
- raw(*command)
- end
-
- def export(path)
- # TODO: Progress
- execute("export", @uuid, "--output", path.to_s)
- end
-
- def forward_ports(ports)
- args = []
- ports.each do |options|
- pf_builder = [options[:name],
- options[:protocol] || "tcp",
- "",
- options[:hostport],
- "",
- options[:guestport]]
-
- args.concat(["--natpf#{options[:adapter] || 1}",
- pf_builder.join(",")])
- end
-
- execute("modifyvm", @uuid, *args) if !args.empty?
- end
-
- def halt
- execute("controlvm", @uuid, "poweroff")
- end
-
- def import(ovf)
- output = ""
- total = ""
- last = 0
- execute("import", ovf) do |type, data|
- if type == :stdout
- # Keep track of the stdout so that we can get the VM name
- output << data
- elsif type == :stderr
- # Append the data so we can see the full view
- total << data
-
- # Break up the lines. We can't get the progress until we see an "OK"
- lines = total.split("\n")
- if lines.include?("OK.")
- # The progress of the import will be in the last line. Do a greedy
- # regular expression to find what we're looking for.
- if current = lines.last[/.+(\d{2})%/, 1]
- current = current.to_i
- if current > last
- last = current
- yield current if block_given?
- end
- end
- end
- end
- end
-
- # Find the name of the VM name
- name = output[/Suggested VM name "(.+?)"/, 1]
- if !name
- @logger.error("Couldn't find VM name in the output.")
- return nil
- end
-
- output = execute("list", "vms")
- if existing_vm = output[/^"#{Regexp.escape(name)}" \{(.+?)\}$/, 1]
- return existing_vm
- end
-
- nil
- end
-
- def read_forwarded_ports(uuid=nil, active_only=false)
- uuid ||= @uuid
-
- @logger.debug("read_forward_ports: uuid=#{uuid} active_only=#{active_only}")
-
- results = []
- current_nic = nil
- info = execute("showvminfo", uuid, "--machinereadable", :retryable => true)
- info.split("\n").each do |line|
- # This is how we find the nic that a FP is attached to,
- # since this comes first.
- if nic = line[/^nic(\d+)=".+?"$/, 1]
- current_nic = nic.to_i
- end
-
- # If we care about active VMs only, then we check the state
- # to verify the VM is running.
- if active_only && (state = line[/^VMState="(.+?)"$/, 1] and state != "running")
- return []
- end
-
- # Parse out the forwarded port information
- if matcher = /^Forwarding.+?="(.+?),.+?,.*?,(.+?),.*?,(.+?)"$/.match(line)
- result = [current_nic, matcher[1], matcher[2].to_i, matcher[3].to_i]
- @logger.debug(" - #{result.inspect}")
- results << result
- end
- end
-
- results
- end
-
- def read_bridged_interfaces
- execute("list", "bridgedifs").split("\n\n").collect do |block|
- info = {}
-
- block.split("\n").each do |line|
- if name = line[/^Name:\s+(.+?)$/, 1]
- info[:name] = name
- elsif ip = line[/^IPAddress:\s+(.+?)$/, 1]
- info[:ip] = ip
- elsif netmask = line[/^NetworkMask:\s+(.+?)$/, 1]
- info[:netmask] = netmask
- elsif status = line[/^Status:\s+(.+?)$/, 1]
- info[:status] = status
- end
- end
-
- # Return the info to build up the results
- info
- end
- end
-
- def read_guest_additions_version
- output = execute("guestproperty", "get", @uuid, "/VirtualBox/GuestAdd/Version",
- :retryable => true)
- if value = output[/^Value: (.+?)$/, 1]
- # Split the version by _ since some distro versions modify it
- # to look like this: 4.1.2_ubuntu, and the distro part isn't
- # too important.
- return value.split("_").first
- end
-
- return nil
- end
-
- def read_host_only_interfaces
- dhcp = {}
- execute("list", "dhcpservers", :retryable => true).split("\n\n").each do |block|
- info = {}
-
- block.split("\n").each do |line|
- if network = line[/^NetworkName:\s+HostInterfaceNetworking-(.+?)$/, 1]
- info[:network] = network
- elsif ip = line[/^IP:\s+(.+?)$/, 1]
- info[:ip] = ip
- elsif lower = line[/^lowerIPAddress:\s+(.+?)$/, 1]
- info[:lower] = lower
- elsif upper = line[/^upperIPAddress:\s+(.+?)$/, 1]
- info[:upper] = upper
- end
- end
-
- # Set the DHCP info
- dhcp[info[:network]] = info
- end
-
- execute("list", "hostonlyifs", :retryable => true).split("\n\n").collect do |block|
- info = {}
-
- block.split("\n").each do |line|
- if name = line[/^Name:\s+(.+?)$/, 1]
- info[:name] = name
- elsif ip = line[/^IPAddress:\s+(.+?)$/, 1]
- info[:ip] = ip
- elsif netmask = line[/^NetworkMask:\s+(.+?)$/, 1]
- info[:netmask] = netmask
- elsif status = line[/^Status:\s+(.+?)$/, 1]
- info[:status] = status
- end
- end
-
- # Set the DHCP info if it exists
- info[:dhcp] = dhcp[info[:name]] if dhcp[info[:name]]
-
- info
- end
- end
-
- def read_mac_address
- info = execute("showvminfo", @uuid, "--machinereadable", :retryable => true)
- info.split("\n").each do |line|
- if mac = line[/^macaddress1="(.+?)"$/, 1]
- return mac
- end
- end
-
- nil
- end
-
- def read_mac_addresses
- macs = {}
- info = execute("showvminfo", @uuid, "--machinereadable", :retryable => true)
- info.split("\n").each do |line|
- if matcher = /^macaddress(\d+)="(.+?)"$/.match(line)
- adapter = matcher[1].to_i
- mac = matcher[2].to_s
- macs[adapter] = mac
- end
- end
- macs
- end
-
- def read_machine_folder
- execute("list", "systemproperties", :retryable => true).split("\n").each do |line|
- if folder = line[/^Default machine folder:\s+(.+?)$/i, 1]
- return folder
- end
- end
-
- nil
- end
-
- def read_network_interfaces
- nics = {}
- info = execute("showvminfo", @uuid, "--machinereadable", :retryable => true)
- info.split("\n").each do |line|
- if matcher = /^nic(\d+)="(.+?)"$/.match(line)
- adapter = matcher[1].to_i
- type = matcher[2].to_sym
-
- nics[adapter] ||= {}
- nics[adapter][:type] = type
- elsif matcher = /^hostonlyadapter(\d+)="(.+?)"$/.match(line)
- adapter = matcher[1].to_i
- network = matcher[2].to_s
-
- nics[adapter] ||= {}
- nics[adapter][:hostonly] = network
- elsif matcher = /^bridgeadapter(\d+)="(.+?)"$/.match(line)
- adapter = matcher[1].to_i
- network = matcher[2].to_s
-
- nics[adapter] ||= {}
- nics[adapter][:bridge] = network
- end
- end
-
- nics
- end
-
- def read_state
- output = execute("showvminfo", @uuid, "--machinereadable", :retryable => true)
- if output =~ /^name="<inaccessible>"$/
- return :inaccessible
- elsif state = output[/^VMState="(.+?)"$/, 1]
- return state.to_sym
- end
-
- nil
- end
-
- def read_used_ports
- ports = []
- execute("list", "vms", :retryable => true).split("\n").each do |line|
- if uuid = line[/^".+?" \{(.+?)\}$/, 1]
- # Ignore our own used ports
- next if uuid == @uuid
-
- read_forwarded_ports(uuid, true).each do |_, _, hostport, _|
- ports << hostport
- end
- end
- end
-
- ports
- end
-
- def read_vms
- results = []
- execute("list", "vms", :retryable => true).split("\n").each do |line|
- if vm = line[/^".+?" \{(.+?)\}$/, 1]
- results << vm
- end
- end
-
- results
- end
-
- def set_mac_address(mac)
- execute("modifyvm", @uuid, "--macaddress1", mac)
- end
-
- def set_name(name)
- execute("modifyvm", @uuid, "--name", name)
- end
-
- def share_folders(folders)
- folders.each do |folder|
- args = ["--name",
- folder[:name],
- "--hostpath",
- folder[:hostpath]]
- args << "--transient" if folder.has_key?(:transient) && folder[:transient]
- execute("sharedfolder", "add", @uuid, *args)
- end
- end
-
- def ssh_port(expected_port)
- @logger.debug("Searching for SSH port: #{expected_port.inspect}")
-
- # Look for the forwarded port only by comparing the guest port
- read_forwarded_ports.each do |_, _, hostport, guestport|
- return hostport if guestport == expected_port
- end
-
- nil
- end
-
- def start(mode)
- command = ["startvm", @uuid, "--type", mode.to_s]
- r = raw(*command)
-
- if r.exit_code == 0 || r.stdout =~ /VM ".+?" has been successfully started/
- # Some systems return an exit code 1 for some reason. For that
- # we depend on the output.
- return true
- end
-
- # If we reached this point then it didn't work out.
- raise Errors::VBoxManageError, :command => command.inspect
- end
-
- def suspend
- execute("controlvm", @uuid, "savestate")
- end
-
- def verify!
- # This command sometimes fails if kernel drivers aren't properly loaded
- # so we just run the command and verify that it succeeded.
- execute("list", "hostonlyifs")
- end
-
- def verify_image(path)
- r = raw("import", path.to_s, "--dry-run")
- return r.exit_code == 0
- end
-
- def vm_exists?(uuid)
- raw("showvminfo", uuid).exit_code == 0
- end
- end
- end
-end
View
474 lib/vagrant/driver/virtualbox_4_1.rb
@@ -1,474 +0,0 @@
-require 'log4r'
-
-require 'vagrant/driver/virtualbox_base'
-
-module Vagrant
- module Driver
- # Driver for VirtualBox 4.1.x
- class VirtualBox_4_1 < VirtualBoxBase
- def initialize(uuid)
- super()
-
- @logger = Log4r::Logger.new("vagrant::driver::virtualbox_4_1")
- @uuid = uuid
- end
-
- def clear_forwarded_ports
- args = []
- read_forwarded_ports(@uuid).each do |nic, name, _, _|
- args.concat(["--natpf#{nic}", "delete", name])
- end
-
- execute("modifyvm", @uuid, *args) if !args.empty?
- end
-
- def clear_shared_folders
- info = execute("showvminfo", @uuid, "--machinereadable", :retryable => true)
- info.split("\n").each do |line|
- if folder = line[/^SharedFolderNameMachineMapping\d+="(.+?)"$/, 1]
- execute("sharedfolder", "remove", @uuid, "--name", folder)
- end
- end
- end
-
- def create_dhcp_server(network, options)
- execute("dhcpserver", "add", "--ifname", network,
- "--ip", options[:dhcp_ip],
- "--netmask", options[:netmask],
- "--lowerip", options[:dhcp_lower],
- "--upperip", options[:dhcp_upper],
- "--enable")
- end
-
- def create_host_only_network(options)
- # Create the interface
- interface = execute("hostonlyif", "create")
- name = interface[/^Interface '(.+?)' was successfully created$/, 1]
-
- # Configure it
- execute("hostonlyif", "ipconfig", name,
- "--ip", options[:adapter_ip],
- "--netmask", options[:netmask])
-
- # Return the details
- return {
- :name => name,
- :ip => options[:adapter_ip],
- :netmask => options[:netmask],
- :dhcp => nil
- }
- end
-
- def delete
- execute("unregistervm", @uuid, "--delete")
- end
-
- def delete_unused_host_only_networks
- networks = []
- execute("list", "hostonlyifs").split("\n").each do |line|
- if network = line[/^Name:\s+(.+?)$/, 1]
- networks << network
- end
- end
-
- execute("list", "vms").split("\n").each do |line|
- if vm = line[/^".+?"\s+\{(.+?)\}$/, 1]
- info = execute("showvminfo", vm, "--machinereadable", :retryable => true)
- info.split("\n").each do |line|
- if adapter = line[/^hostonlyadapter\d+="(.+?)"$/, 1]
- networks.delete(adapter)
- end
- end
- end
- end
-
- networks.each do |name|
- # First try to remove any DHCP servers attached. We use `raw` because
- # it is okay if this fails. It usually means that a DHCP server was
- # never attached.
- raw("dhcpserver", "remove", "--ifname", name)
-
- # Delete the actual host only network interface.
- execute("hostonlyif", "remove", name)
- end
- end
-
- def discard_saved_state
- execute("discardstate", @uuid)
- end
-
- def enable_adapters(adapters)
- args = []
- adapters.each do |adapter|
- args.concat(["--nic#{adapter[:adapter]}", adapter[:type].to_s])
-
- if adapter[:bridge]
- args.concat(["--bridgeadapter#{adapter[:adapter]}",
- adapter[:bridge]])
- end
-
- if adapter[:hostonly]
- args.concat(["--hostonlyadapter#{adapter[:adapter]}",
- adapter[:hostonly]])
- end
-
- if adapter[:mac_address]
- args.concat(["--macaddress#{adapter[:adapter]}",
- adapter[:mac_address]])
- end
-
- if adapter[:nic_type]
- args.concat(["--nictype#{adapter[:adapter]}", adapter[:nic_type].to_s])
- end
- end
-
- execute("modifyvm", @uuid, *args)
- end
-
- def execute_command(command)
- raw(*command)
- end
-
- def export(path)
- # TODO: Progress
- execute("export", @uuid, "--output", path.to_s)
- end
-
- def forward_ports(ports)
- args = []
- ports.each do |options|
- pf_builder = [options[:name],
- options[:protocol] || "tcp",
- "",
- options[:hostport],
- "",
- options[:guestport]]
-
- args.concat(["--natpf#{options[:adapter] || 1}",
- pf_builder.join(",")])
- end
-
- execute("modifyvm", @uuid, *args) if !args.empty?
- end
-
- def halt
- execute("controlvm", @uuid, "poweroff")
- end
-
- def import(ovf)
- output = ""
- total = ""
- last = 0
- execute("import", ovf) do |type, data|
- if type == :stdout
- # Keep track of the stdout so that we can get the VM name
- output << data
- elsif type == :stderr
- # Append the data so we can see the full view
- total << data
-
- # Break up the lines. We can't get the progress until we see an "OK"
- lines = total.split("\n")
- if lines.include?("OK.")
- # The progress of the import will be in the last line. Do a greedy
- # regular expression to find what we're looking for.
- if current = lines.last[/.+(\d{2})%/, 1]
- current = current.to_i
- if current > last
- last = current
- yield current if block_given?
- end
- end
- end
- end
- end
-
- # Find the name of the VM name
- name = output[/Suggested VM name "(.+?)"/, 1]
- if !name
- @logger.error("Couldn't find VM name in the output.")
- return nil
- end
-
- output = execute("list", "vms")
- if existing_vm = output[/^"#{Regexp.escape(name)}" \{(.+?)\}$/, 1]
- return existing_vm
- end
-
- nil
- end
-
- def read_forwarded_ports(uuid=nil, active_only=false)
- uuid ||= @uuid
-
- @logger.debug("read_forward_ports: uuid=#{uuid} active_only=#{active_only}")
-
- results = []
- current_nic = nil
- info = execute("showvminfo", uuid, "--machinereadable", :retryable => true)
- info.split("\n").each do |line|
- # This is how we find the nic that a FP is attached to,
- # since this comes first.
- if nic = line[/^nic(\d+)=".+?"$/, 1]
- current_nic = nic.to_i
- end
-
- # If we care about active VMs only, then we check the state
- # to verify the VM is running.
- if active_only && (state = line[/^VMState="(.+?)"$/, 1] and state != "running")
- return []
- end
-
- # Parse out the forwarded port information
- if matcher = /^Forwarding.+?="(.+?),.+?,.*?,(.+?),.*?,(.+?)"$/.match(line)
- result = [current_nic, matcher[1], matcher[2].to_i, matcher[3].to_i]
- @logger.debug(" - #{result.inspect}")
- results << result
- end
- end
-
- results
- end
-
- def read_bridged_interfaces
- execute("list", "bridgedifs").split("\n\n").collect do |block|
- info = {}
-
- block.split("\n").each do |line|
- if name = line[/^Name:\s+(.+?)$/, 1]
- info[:name] = name
- elsif ip = line[/^IPAddress:\s+(.+?)$/, 1]
- info[:ip] = ip
- elsif netmask = line[/^NetworkMask:\s+(.+?)$/, 1]
- info[:netmask] = netmask
- elsif status = line[/^Status:\s+(.+?)$/, 1]
- info[:status] = status
- end
- end
-
- # Return the info to build up the results
- info
- end
- end
-
- def read_guest_additions_version
- output = execute("guestproperty", "get", @uuid, "/VirtualBox/GuestAdd/Version",
- :retryable => true)
- if value = output[/^Value: (.+?)$/, 1]
- # Split the version by _ since some distro versions modify it
- # to look like this: 4.1.2_ubuntu, and the distro part isn't
- # too important.
- return value.split("_").first
- end
-
- return nil
- end
-
- def read_host_only_interfaces
- dhcp = {}
- execute("list", "dhcpservers", :retryable => true).split("\n\n").each do |block|
- info = {}
-
- block.split("\n").each do |line|
- if network = line[/^NetworkName:\s+HostInterfaceNetworking-(.+?)$/, 1]
- info[:network] = network
- elsif ip = line[/^IP:\s+(.+?)$/, 1]
- info[:ip] = ip
- elsif lower = line[/^lowerIPAddress:\s+(.+?)$/, 1]
- info[:lower] = lower
- elsif upper = line[/^upperIPAddress:\s+(.+?)$/, 1]
- info[:upper] = upper
- end
- end
-
- # Set the DHCP info
- dhcp[info[:network]] = info
- end
-
- execute("list", "hostonlyifs", :retryable => true).split("\n\n").collect do |block|
- info = {}
-
- block.split("\n").each do |line|
- if name = line[/^Name:\s+(.+?)$/, 1]
- info[:name] = name
- elsif ip = line[/^IPAddress:\s+(.+?)$/, 1]
- info[:ip] = ip
- elsif netmask = line[/^NetworkMask:\s+(.+?)$/, 1]
- info[:netmask] = netmask
- elsif status = line[/^Status:\s+(.+?)$/, 1]
- info[:status] = status
- end
- end
-
- # Set the DHCP info if it exists
- info[:dhcp] = dhcp[info[:name]] if dhcp[info[:name]]
-
- info
- end
- end
-
- def read_mac_address
- info = execute("showvminfo", @uuid, "--machinereadable", :retryable => true)
- info.split("\n").each do |line|
- if mac = line[/^macaddress1="(.+?)"$/, 1]
- return mac
- end
- end
-
- nil
- end
-
- def read_mac_addresses
- macs = {}
- info = execute("showvminfo", @uuid, "--machinereadable", :retryable => true)
- info.split("\n").each do |line|
- if matcher = /^macaddress(\d+)="(.+?)"$/.match(line)
- adapter = matcher[1].to_i
- mac = matcher[2].to_s
- macs[adapter] = mac
- end
- end
- macs
- end
-
- def read_machine_folder
- execute("list", "systemproperties", :retryable => true).split("\n").each do |line|
- if folder = line[/^Default machine folder:\s+(.+?)$/i, 1]
- return folder
- end
- end
-
- nil
- end
-
- def read_network_interfaces
- nics = {}
- info = execute("showvminfo", @uuid, "--machinereadable", :retryable => true)
- info.split("\n").each do |line|
- if matcher = /^nic(\d+)="(.+?)"$/.match(line)
- adapter = matcher[1].to_i
- type = matcher[2].to_sym
-
- nics[adapter] ||= {}
- nics[adapter][:type] = type
- elsif matcher = /^hostonlyadapter(\d+)="(.+?)"$/.match(line)
- adapter = matcher[1].to_i
- network = matcher[2].to_s
-
- nics[adapter] ||= {}
- nics[adapter][:hostonly] = network
- elsif matcher = /^bridgeadapter(\d+)="(.+?)"$/.match(line)
- adapter = matcher[1].to_i
- network = matcher[2].to_s
-
- nics[adapter] ||= {}
- nics[adapter][:bridge] = network
- end
- end
-
- nics
- end
-
- def read_state
- output = execute("showvminfo", @uuid, "--machinereadable", :retryable => true)
- if output =~ /^name="<inaccessible>"$/
- return :inaccessible
- elsif state = output[/^VMState="(.+?)"$/, 1]
- return state.to_sym
- end
-
- nil
- end
-
- def read_used_ports
- ports = []
- execute("list", "vms", :retryable => true).split("\n").each do |line|
- if uuid = line[/^".+?" \{(.+?)\}$/, 1]
- # Ignore our own used ports
- next if uuid == @uuid
-
- read_forwarded_ports(uuid, true).each do |_, _, hostport, _|
- ports << hostport
- end
- end
- end
-
- ports
- end
-
- def read_vms
- results = []
- execute("list", "vms", :retryable => true).split("\n").each do |line|
- if vm = line[/^".+?" \{(.+?)\}$/, 1]
- results << vm
- end
- end
-
- results
- end
-
- def set_mac_address(mac)
- execute("modifyvm", @uuid, "--macaddress1", mac)
- end
-
- def set_name(name)
- execute("modifyvm", @uuid, "--name", name)
- end
-
- def share_folders(folders)
- folders.each do |folder|
- args = ["--name",
- folder[:name],
- "--hostpath",
- folder[:hostpath]]
- args << "--transient" if folder.has_key?(:transient) && folder[:transient]
- execute("sharedfolder", "add", @uuid, *args)
- end
- end
-
- def ssh_port(expected_port)
- @logger.debug("Searching for SSH port: #{expected_port.inspect}")
-
- # Look for the forwarded port only by comparing the guest port
- read_forwarded_ports.each do |_, _, hostport, guestport|
- return hostport if guestport == expected_port
- end
-
- nil
- end
-
- def start(mode)
- command = ["startvm", @uuid, "--type", mode.to_s]
- r = raw(*command)
-
- if r.exit_code == 0 || r.stdout =~ /VM ".+?" has been successfully started/
- # Some systems return an exit code 1 for some reason. For that
- # we depend on the output.
- return true
- end
-
- # If we reached this point then it didn't work out.
- raise Errors::VBoxManageError, :command => command.inspect
- end
-
- def suspend
- execute("controlvm", @uuid, "savestate")
- end
-
- def verify!
- # This command sometimes fails if kernel drivers aren't properly loaded
- # so we just run the command and verify that it succeeded.
- execute("list", "hostonlyifs")
- end
-
- def verify_image(path)
- r = raw("import", path.to_s, "--dry-run")
- return r.exit_code == 0
- end
-
- def vm_exists?(uuid)
- raw("showvminfo", uuid).exit_code == 0
- end
- end
- end
-end
View
326 lib/vagrant/driver/virtualbox_base.rb
@@ -1,326 +0,0 @@
-require 'log4r'
-
-require 'vagrant/util/busy'
-require 'vagrant/util/platform'
-require 'vagrant/util/retryable'
-require 'vagrant/util/subprocess'
-
-module Vagrant
- module Driver
- # Base class for all VirtualBox drivers.
- #
- # This class provides useful tools for things such as executing
- # VBoxManage and handling SIGINTs and so on.
- class VirtualBoxBase
- # Include this so we can use `Subprocess` more easily.
- include Vagrant::Util
- include Vagrant::Util::Retryable
-
- def initialize
- @logger = Log4r::Logger.new("vagrant::driver::virtualbox_base")
-
- # This flag is used to keep track of interrupted state (SIGINT)
- @interrupted = false
-
- # Set the path to VBoxManage
- @vboxmanage_path = "VBoxManage"
-
- if Util::Platform.windows?
- @logger.debug("Windows. Trying VBOX_INSTALL_PATH for VBoxManage")
-
- # On Windows, we use the VBOX_INSTALL_PATH environmental
- # variable to find VBoxManage.
- if ENV.has_key?("VBOX_INSTALL_PATH")
- # Get the path.
- path = ENV["VBOX_INSTALL_PATH"]
- @logger.debug("VBOX_INSTALL_PATH value: #{path}")
-
- # There can actually be multiple paths in here, so we need to
- # split by the separator ";" and see which is a good one.
- path.split(";").each do |single|
- # Make sure it ends with a \
- single += "\\" if !single.end_with?("\\")
-
- # If the executable exists, then set it as the main path
- # and break out
- vboxmanage = "#{path}VBoxManage.exe"
- if File.file?(vboxmanage)
- @vboxmanage_path = vboxmanage
- break
- end
- end
- end
- end
-
- @logger.info("VBoxManage path: #{@vboxmanage_path}")
- end
-
- # Clears the forwarded ports that have been set on the virtual machine.
- def clear_forwarded_ports
- end
-
- # Clears the shared folders that have been set on the virtual machine.
- def clear_shared_folders
- end
-
- # Creates a DHCP server for a host only network.
- #
- # @param [String] network Name of the host-only network.
- # @param [Hash] options Options for the DHCP server.
- def create_dhcp_server(network, options)
- end
-
- # Creates a host only network with the given options.
- #
- # @param [Hash] options Options to create the host only network.
- # @return [Hash] The details of the host only network, including
- # keys `:name`, `:ip`, and `:netmask`
- def create_host_only_network(options)
- end
-
- # Deletes the virtual machine references by this driver.
- def delete
- end
-
- # Deletes any host only networks that aren't being used for anything.
- def delete_unused_host_only_networks
- end
-
- # Discards any saved state associated with this VM.
- def discard_saved_state
- end
-
- # Enables network adapters on the VM.
- #
- # The format of each adapter specification should be like so: