rvagrant 0.8.7.dev

Sign up to get free protection for your applications and to get access to all the features.
Files changed (251) hide show
  1. data/.gitignore +25 -0
  2. data/.yardopts +1 -0
  3. data/CHANGELOG.md +386 -0
  4. data/Gemfile +21 -0
  5. data/LICENSE +21 -0
  6. data/README.md +61 -0
  7. data/Rakefile +11 -0
  8. data/bin/vagrant +28 -0
  9. data/config/default.rb +38 -0
  10. data/contrib/README.md +12 -0
  11. data/contrib/emacs/vagrant.el +8 -0
  12. data/contrib/vim/vagrantfile.vim +9 -0
  13. data/keys/README.md +17 -0
  14. data/keys/vagrant +27 -0
  15. data/keys/vagrant.ppk +26 -0
  16. data/keys/vagrant.pub +1 -0
  17. data/lib/vagrant.rb +44 -0
  18. data/lib/vagrant/action.rb +138 -0
  19. data/lib/vagrant/action/box.rb +11 -0
  20. data/lib/vagrant/action/box/destroy.rb +21 -0
  21. data/lib/vagrant/action/box/download.rb +72 -0
  22. data/lib/vagrant/action/box/package.rb +19 -0
  23. data/lib/vagrant/action/box/unpackage.rb +55 -0
  24. data/lib/vagrant/action/box/verify.rb +23 -0
  25. data/lib/vagrant/action/builder.rb +124 -0
  26. data/lib/vagrant/action/builtin.rb +108 -0
  27. data/lib/vagrant/action/env.rb +7 -0
  28. data/lib/vagrant/action/env/set.rb +18 -0
  29. data/lib/vagrant/action/environment.rb +50 -0
  30. data/lib/vagrant/action/general.rb +8 -0
  31. data/lib/vagrant/action/general/package.rb +113 -0
  32. data/lib/vagrant/action/general/validate.rb +19 -0
  33. data/lib/vagrant/action/vm.rb +34 -0
  34. data/lib/vagrant/action/vm/boot.rb +48 -0
  35. data/lib/vagrant/action/vm/check_accessible.rb +23 -0
  36. data/lib/vagrant/action/vm/check_box.rb +28 -0
  37. data/lib/vagrant/action/vm/check_guest_additions.rb +35 -0
  38. data/lib/vagrant/action/vm/clean_machine_folder.rb +43 -0
  39. data/lib/vagrant/action/vm/clear_forwarded_ports.rb +26 -0
  40. data/lib/vagrant/action/vm/clear_nfs_exports.rb +20 -0
  41. data/lib/vagrant/action/vm/clear_shared_folders.rb +27 -0
  42. data/lib/vagrant/action/vm/customize.rb +26 -0
  43. data/lib/vagrant/action/vm/destroy.rb +19 -0
  44. data/lib/vagrant/action/vm/destroy_unused_network_interfaces.rb +30 -0
  45. data/lib/vagrant/action/vm/discard_state.rb +22 -0
  46. data/lib/vagrant/action/vm/export.rb +52 -0
  47. data/lib/vagrant/action/vm/forward_ports.rb +133 -0
  48. data/lib/vagrant/action/vm/forward_ports_helpers.rb +28 -0
  49. data/lib/vagrant/action/vm/halt.rb +29 -0
  50. data/lib/vagrant/action/vm/host_name.rb +21 -0
  51. data/lib/vagrant/action/vm/import.rb +40 -0
  52. data/lib/vagrant/action/vm/match_mac_address.rb +26 -0
  53. data/lib/vagrant/action/vm/modify.rb +37 -0
  54. data/lib/vagrant/action/vm/network.rb +146 -0
  55. data/lib/vagrant/action/vm/nfs.rb +160 -0
  56. data/lib/vagrant/action/vm/nfs_helpers.rb +11 -0
  57. data/lib/vagrant/action/vm/package.rb +23 -0
  58. data/lib/vagrant/action/vm/package_vagrantfile.rb +33 -0
  59. data/lib/vagrant/action/vm/provision.rb +34 -0
  60. data/lib/vagrant/action/vm/provisioner_cleanup.rb +26 -0
  61. data/lib/vagrant/action/vm/resume.rb +20 -0
  62. data/lib/vagrant/action/vm/share_folders.rb +78 -0
  63. data/lib/vagrant/action/vm/suspend.rb +20 -0
  64. data/lib/vagrant/action/warden.rb +85 -0
  65. data/lib/vagrant/box.rb +90 -0
  66. data/lib/vagrant/box_collection.rb +53 -0
  67. data/lib/vagrant/cli.rb +55 -0
  68. data/lib/vagrant/command.rb +25 -0
  69. data/lib/vagrant/command/base.rb +106 -0
  70. data/lib/vagrant/command/box.rb +33 -0
  71. data/lib/vagrant/command/destroy.rb +17 -0
  72. data/lib/vagrant/command/group_base.rb +107 -0
  73. data/lib/vagrant/command/halt.rb +18 -0
  74. data/lib/vagrant/command/helpers.rb +33 -0
  75. data/lib/vagrant/command/init.rb +14 -0
  76. data/lib/vagrant/command/named_base.rb +14 -0
  77. data/lib/vagrant/command/package.rb +41 -0
  78. data/lib/vagrant/command/provision.rb +23 -0
  79. data/lib/vagrant/command/reload.rb +17 -0
  80. data/lib/vagrant/command/resume.rb +17 -0
  81. data/lib/vagrant/command/ssh.rb +49 -0
  82. data/lib/vagrant/command/ssh_config.rb +29 -0
  83. data/lib/vagrant/command/status.rb +31 -0
  84. data/lib/vagrant/command/suspend.rb +17 -0
  85. data/lib/vagrant/command/up.rb +19 -0
  86. data/lib/vagrant/command/upgrade_to_060.rb +45 -0
  87. data/lib/vagrant/command/version.rb +13 -0
  88. data/lib/vagrant/config.rb +123 -0
  89. data/lib/vagrant/config/base.rb +85 -0
  90. data/lib/vagrant/config/error_recorder.rb +19 -0
  91. data/lib/vagrant/config/nfs.rb +10 -0
  92. data/lib/vagrant/config/package.rb +9 -0
  93. data/lib/vagrant/config/ssh.rb +38 -0
  94. data/lib/vagrant/config/top.rb +61 -0
  95. data/lib/vagrant/config/vagrant.rb +17 -0
  96. data/lib/vagrant/config/vm.rb +148 -0
  97. data/lib/vagrant/config/vm/provisioner.rb +56 -0
  98. data/lib/vagrant/config/vm/sub_vm.rb +17 -0
  99. data/lib/vagrant/data_store.rb +70 -0
  100. data/lib/vagrant/downloaders.rb +7 -0
  101. data/lib/vagrant/downloaders/base.rb +23 -0
  102. data/lib/vagrant/downloaders/file.rb +22 -0
  103. data/lib/vagrant/downloaders/http.rb +70 -0
  104. data/lib/vagrant/environment.rb +516 -0
  105. data/lib/vagrant/errors.rb +352 -0
  106. data/lib/vagrant/hosts.rb +9 -0
  107. data/lib/vagrant/hosts/arch.rb +27 -0
  108. data/lib/vagrant/hosts/base.rb +76 -0
  109. data/lib/vagrant/hosts/bsd.rb +58 -0
  110. data/lib/vagrant/hosts/fedora.rb +11 -0
  111. data/lib/vagrant/hosts/linux.rb +69 -0
  112. data/lib/vagrant/plugin.rb +79 -0
  113. data/lib/vagrant/provisioners.rb +9 -0
  114. data/lib/vagrant/provisioners/base.rb +67 -0
  115. data/lib/vagrant/provisioners/chef.rb +155 -0
  116. data/lib/vagrant/provisioners/chef_client.rb +120 -0
  117. data/lib/vagrant/provisioners/chef_solo.rb +135 -0
  118. data/lib/vagrant/provisioners/puppet.rb +137 -0
  119. data/lib/vagrant/provisioners/puppet_server.rb +55 -0
  120. data/lib/vagrant/provisioners/shell.rb +96 -0
  121. data/lib/vagrant/ssh.rb +224 -0
  122. data/lib/vagrant/ssh/session.rb +136 -0
  123. data/lib/vagrant/systems.rb +13 -0
  124. data/lib/vagrant/systems/arch.rb +34 -0
  125. data/lib/vagrant/systems/base.rb +87 -0
  126. data/lib/vagrant/systems/debian.rb +36 -0
  127. data/lib/vagrant/systems/freebsd.rb +84 -0
  128. data/lib/vagrant/systems/gentoo.rb +27 -0
  129. data/lib/vagrant/systems/linux.rb +82 -0
  130. data/lib/vagrant/systems/linux/config.rb +21 -0
  131. data/lib/vagrant/systems/linux/error.rb +9 -0
  132. data/lib/vagrant/systems/redhat.rb +48 -0
  133. data/lib/vagrant/systems/solaris.rb +67 -0
  134. data/lib/vagrant/systems/suse.rb +9 -0
  135. data/lib/vagrant/systems/ubuntu.rb +17 -0
  136. data/lib/vagrant/test_helpers.rb +128 -0
  137. data/lib/vagrant/ui.rb +81 -0
  138. data/lib/vagrant/util.rb +13 -0
  139. data/lib/vagrant/util/busy.rb +59 -0
  140. data/lib/vagrant/util/counter.rb +24 -0
  141. data/lib/vagrant/util/hash_with_indifferent_access.rb +63 -0
  142. data/lib/vagrant/util/platform.rb +57 -0
  143. data/lib/vagrant/util/retryable.rb +25 -0
  144. data/lib/vagrant/util/safe_exec.rb +35 -0
  145. data/lib/vagrant/util/stacked_proc_runner.rb +35 -0
  146. data/lib/vagrant/util/template_renderer.rb +83 -0
  147. data/lib/vagrant/version.rb +6 -0
  148. data/lib/vagrant/vm.rb +181 -0
  149. data/templates/chef_server_client.erb +32 -0
  150. data/templates/chef_solo_solo.erb +23 -0
  151. data/templates/commands/init/Vagrantfile.erb +86 -0
  152. data/templates/config/validation_failed.erb +7 -0
  153. data/templates/locales/en.yml +556 -0
  154. data/templates/network_entry_arch.erb +9 -0
  155. data/templates/network_entry_debian.erb +8 -0
  156. data/templates/network_entry_gentoo.erb +5 -0
  157. data/templates/network_entry_redhat.erb +9 -0
  158. data/templates/nfs/exports.erb +5 -0
  159. data/templates/nfs/exports_linux.erb +5 -0
  160. data/templates/package_Vagrantfile.erb +11 -0
  161. data/templates/ssh_config.erb +15 -0
  162. data/test/unit/locales/en.yml +8 -0
  163. data/test/unit/test_helper.rb +28 -0
  164. data/test/unit/vagrant/action/box/destroy_test.rb +18 -0
  165. data/test/unit/vagrant/action/box/download_test.rb +125 -0
  166. data/test/unit/vagrant/action/box/package_test.rb +25 -0
  167. data/test/unit/vagrant/action/box/unpackage_test.rb +84 -0
  168. data/test/unit/vagrant/action/box/verify_test.rb +30 -0
  169. data/test/unit/vagrant/action/builder_test.rb +207 -0
  170. data/test/unit/vagrant/action/env/set_test.rb +24 -0
  171. data/test/unit/vagrant/action/environment_test.rb +27 -0
  172. data/test/unit/vagrant/action/general/package_test.rb +268 -0
  173. data/test/unit/vagrant/action/general/validate_test.rb +31 -0
  174. data/test/unit/vagrant/action/vm/boot_test.rb +66 -0
  175. data/test/unit/vagrant/action/vm/check_accessible_test.rb +61 -0
  176. data/test/unit/vagrant/action/vm/check_box_test.rb +56 -0
  177. data/test/unit/vagrant/action/vm/check_guest_additions_test.rb +9 -0
  178. data/test/unit/vagrant/action/vm/clean_machine_folder_test.rb +84 -0
  179. data/test/unit/vagrant/action/vm/clear_forwarded_ports_test.rb +52 -0
  180. data/test/unit/vagrant/action/vm/clear_nfs_exports_test.rb +22 -0
  181. data/test/unit/vagrant/action/vm/clear_shared_folders_test.rb +40 -0
  182. data/test/unit/vagrant/action/vm/customize_test.rb +37 -0
  183. data/test/unit/vagrant/action/vm/destroy_test.rb +25 -0
  184. data/test/unit/vagrant/action/vm/destroy_unused_network_interfaces_test.rb +49 -0
  185. data/test/unit/vagrant/action/vm/discard_state_test.rb +45 -0
  186. data/test/unit/vagrant/action/vm/export_test.rb +107 -0
  187. data/test/unit/vagrant/action/vm/forward_ports_helpers_test.rb +77 -0
  188. data/test/unit/vagrant/action/vm/forward_ports_test.rb +213 -0
  189. data/test/unit/vagrant/action/vm/halt_test.rb +79 -0
  190. data/test/unit/vagrant/action/vm/host_name_test.rb +36 -0
  191. data/test/unit/vagrant/action/vm/import_test.rb +66 -0
  192. data/test/unit/vagrant/action/vm/match_mac_address_test.rb +40 -0
  193. data/test/unit/vagrant/action/vm/modify_test.rb +38 -0
  194. data/test/unit/vagrant/action/vm/network_test.rb +286 -0
  195. data/test/unit/vagrant/action/vm/nfs_helpers_test.rb +26 -0
  196. data/test/unit/vagrant/action/vm/nfs_test.rb +260 -0
  197. data/test/unit/vagrant/action/vm/package_test.rb +25 -0
  198. data/test/unit/vagrant/action/vm/package_vagrantfile_test.rb +46 -0
  199. data/test/unit/vagrant/action/vm/provision_test.rb +65 -0
  200. data/test/unit/vagrant/action/vm/provisioner_cleanup_test.rb +56 -0
  201. data/test/unit/vagrant/action/vm/resume_test.rb +35 -0
  202. data/test/unit/vagrant/action/vm/share_folders_test.rb +144 -0
  203. data/test/unit/vagrant/action/vm/suspend_test.rb +35 -0
  204. data/test/unit/vagrant/action/warden_test.rb +125 -0
  205. data/test/unit/vagrant/action_test.rb +89 -0
  206. data/test/unit/vagrant/box_collection_test.rb +45 -0
  207. data/test/unit/vagrant/box_test.rb +74 -0
  208. data/test/unit/vagrant/cli_test.rb +35 -0
  209. data/test/unit/vagrant/command/base_test.rb +23 -0
  210. data/test/unit/vagrant/command/group_base_test.rb +15 -0
  211. data/test/unit/vagrant/command/helpers_test.rb +88 -0
  212. data/test/unit/vagrant/command/package_test.rb +27 -0
  213. data/test/unit/vagrant/config/base_test.rb +52 -0
  214. data/test/unit/vagrant/config/error_recorder_test.rb +18 -0
  215. data/test/unit/vagrant/config/ssh_test.rb +12 -0
  216. data/test/unit/vagrant/config/vagrant_test.rb +35 -0
  217. data/test/unit/vagrant/config/vm/provisioner_test.rb +92 -0
  218. data/test/unit/vagrant/config/vm_test.rb +56 -0
  219. data/test/unit/vagrant/config_test.rb +162 -0
  220. data/test/unit/vagrant/data_store_test.rb +77 -0
  221. data/test/unit/vagrant/downloaders/base_test.rb +28 -0
  222. data/test/unit/vagrant/downloaders/file_test.rb +48 -0
  223. data/test/unit/vagrant/downloaders/http_test.rb +82 -0
  224. data/test/unit/vagrant/environment_test.rb +598 -0
  225. data/test/unit/vagrant/errors_test.rb +42 -0
  226. data/test/unit/vagrant/hosts/base_test.rb +46 -0
  227. data/test/unit/vagrant/hosts/bsd_test.rb +53 -0
  228. data/test/unit/vagrant/hosts/linux_test.rb +54 -0
  229. data/test/unit/vagrant/plugin_test.rb +9 -0
  230. data/test/unit/vagrant/provisioners/base_test.rb +63 -0
  231. data/test/unit/vagrant/provisioners/chef_client_test.rb +190 -0
  232. data/test/unit/vagrant/provisioners/chef_solo_test.rb +114 -0
  233. data/test/unit/vagrant/provisioners/chef_test.rb +202 -0
  234. data/test/unit/vagrant/provisioners/puppet_server_test.rb +68 -0
  235. data/test/unit/vagrant/provisioners/puppet_test.rb +182 -0
  236. data/test/unit/vagrant/provisioners/shell_test.rb +79 -0
  237. data/test/unit/vagrant/ssh/session_test.rb +40 -0
  238. data/test/unit/vagrant/ssh_test.rb +307 -0
  239. data/test/unit/vagrant/systems/base_test.rb +18 -0
  240. data/test/unit/vagrant/systems/linux_test.rb +104 -0
  241. data/test/unit/vagrant/ui_test.rb +29 -0
  242. data/test/unit/vagrant/util/busy_test.rb +106 -0
  243. data/test/unit/vagrant/util/counter_test.rb +29 -0
  244. data/test/unit/vagrant/util/hash_with_indifferent_access_test.rb +39 -0
  245. data/test/unit/vagrant/util/platform_test.rb +18 -0
  246. data/test/unit/vagrant/util/retryable_test.rb +50 -0
  247. data/test/unit/vagrant/util/stacked_proc_runner_test.rb +43 -0
  248. data/test/unit/vagrant/util/template_renderer_test.rb +145 -0
  249. data/test/unit/vagrant/vm_test.rb +300 -0
  250. data/vagrant.gemspec +35 -0
  251. metadata +431 -0
@@ -0,0 +1,22 @@
1
+ require 'fileutils'
2
+
3
+ module Vagrant
4
+ module Downloaders
5
+ # "Downloads" a file to a temporary file. Basically, this downloader
6
+ # simply does a file copy.
7
+ class File < Base
8
+ def self.match?(uri)
9
+ ::File.exists?(uri)
10
+ end
11
+
12
+ def prepare(source_url)
13
+ raise Errors::DownloaderFileDoesntExist if !::File.file?(source_url)
14
+ end
15
+
16
+ def download!(source_url, destination_file)
17
+ env.ui.info I18n.t("vagrant.downloaders.file.download")
18
+ FileUtils.cp(source_url, destination_file.path)
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,70 @@
1
+ require 'net/http'
2
+ require 'net/https'
3
+ require 'open-uri'
4
+ require 'uri'
5
+
6
+ module Vagrant
7
+ module Downloaders
8
+ # Downloads a file from an HTTP URL to a temporary file. This
9
+ # downloader reports its progress to stdout while downloading.
10
+ class HTTP < Base
11
+ def self.match?(uri)
12
+ # URI.parse barfs on '<drive letter>:\\files \on\ windows'
13
+ extracted = URI.extract(uri).first
14
+ extracted && extracted.include?(uri)
15
+ end
16
+
17
+ def download!(source_url, destination_file)
18
+ proxy_uri = URI.parse(ENV["http_proxy"] || "")
19
+ uri = URI.parse(source_url)
20
+ http = Net::HTTP.new(uri.host, uri.port, proxy_uri.host, proxy_uri.port, proxy_uri.user, proxy_uri.password)
21
+
22
+ if uri.scheme == "https"
23
+ http.use_ssl = true
24
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
25
+ end
26
+
27
+ http.start do |h|
28
+ env.ui.info I18n.t("vagrant.downloaders.http.download", :url => source_url)
29
+
30
+ h.request_get(uri.request_uri) do |response|
31
+ if response.is_a?(Net::HTTPRedirection)
32
+ # Follow the HTTP redirect.
33
+ # TODO: Error on some redirect limit
34
+ download!(response["Location"], destination_file)
35
+ return
36
+ elsif !response.is_a?(Net::HTTPOK)
37
+ raise Errors::DownloaderHTTPStatusError, :status => response.code
38
+ end
39
+
40
+ total = response.content_length
41
+ progress = 0
42
+ segment_count = 0
43
+
44
+ response.read_body do |segment|
45
+ # Report the progress out
46
+ progress += segment.length
47
+ segment_count += 1
48
+
49
+ # Progress reporting is limited to every 25 segments just so
50
+ # we're not constantly updating
51
+ if segment_count % 25 == 0
52
+ env.ui.clear_line
53
+ env.ui.report_progress(progress, total)
54
+ segment_count = 0
55
+ end
56
+
57
+ # Store the segment
58
+ destination_file.write(segment)
59
+ end
60
+
61
+ # Clear the line one last time so that the progress meter disappears
62
+ env.ui.clear_line
63
+ end
64
+ end
65
+ rescue SocketError
66
+ raise Errors::DownloaderHTTPSocketError
67
+ end
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,516 @@
1
+ require 'pathname'
2
+ require 'fileutils'
3
+ require 'logger'
4
+
5
+ module Vagrant
6
+ # Represents a single Vagrant environment. A "Vagrant environment" is
7
+ # defined as basically a folder with a "Vagrantfile." This class allows
8
+ # access to the VMs, CLI, etc. all in the scope of this environment.
9
+ class Environment
10
+ HOME_SUBDIRS = ["tmp", "boxes", "logs"]
11
+ DEFAULT_VM = :default
12
+ DEFAULT_HOME = "~/.vagrant.d"
13
+
14
+ # Parent environment (in the case of multi-VMs)
15
+ attr_reader :parent
16
+
17
+ # The `cwd` that this environment represents
18
+ attr_reader :cwd
19
+
20
+ # The valid name for a Vagrantfile for this environment.
21
+ attr_reader :vagrantfile_name
22
+
23
+ # The single VM that this environment represents, in the case of
24
+ # multi-VM.
25
+ attr_accessor :vm
26
+
27
+ # The {UI} object to communicate with the outside world.
28
+ attr_writer :ui
29
+
30
+ # The {Config} object representing the Vagrantfile loader
31
+ attr_reader :config_loader
32
+
33
+ #---------------------------------------------------------------
34
+ # Class Methods
35
+ #---------------------------------------------------------------
36
+ class << self
37
+ # Verifies that VirtualBox is installed and that the version of
38
+ # VirtualBox installed is high enough.
39
+ def check_virtualbox!
40
+ version = VirtualBox.version
41
+ raise Errors::VirtualBoxNotDetected if version.nil?
42
+ raise Errors::VirtualBoxInvalidVersion, :version => version.to_s if version.to_f < 4.1 || version.to_f >= 4.2
43
+ rescue Errors::VirtualBoxNotDetected
44
+ # On 64-bit Windows, show a special error. This error is a subclass
45
+ # of VirtualBoxNotDetected, so libraries which use Vagrant can just
46
+ # rescue VirtualBoxNotDetected.
47
+ raise Errors::VirtualBoxNotDetected_Win64 if Util::Platform.windows? && Util::Platform.bit64?
48
+
49
+ # Otherwise, reraise the old error
50
+ raise
51
+ end
52
+ end
53
+
54
+ # Initializes a new environment with the given options. The options
55
+ # is a hash where the main available key is `cwd`, which defines where
56
+ # the environment represents. There are other options available but
57
+ # they shouldn't be used in general. If `cwd` is nil, then it defaults
58
+ # to the `Dir.pwd` (which is the cwd of the executing process).
59
+ def initialize(opts=nil)
60
+ opts = {
61
+ :parent => nil,
62
+ :vm => nil,
63
+ :cwd => nil,
64
+ :vagrantfile_name => nil,
65
+ :lock_path => nil
66
+ }.merge(opts || {})
67
+
68
+ # Set the default working directory to look for the vagrantfile
69
+ opts[:cwd] ||= Dir.pwd
70
+ opts[:cwd] = Pathname.new(opts[:cwd])
71
+
72
+ # Set the default vagrantfile name, which can be either Vagrantfile
73
+ # or vagrantfile (capital for backwards compatibility)
74
+ opts[:vagrantfile_name] ||= ["Vagrantfile", "vagrantfile"]
75
+ opts[:vagrantfile_name] = [opts[:vagrantfile_name]] if !opts[:vagrantfile_name].is_a?(Array)
76
+
77
+ opts.each do |key, value|
78
+ instance_variable_set("@#{key}".to_sym, opts[key])
79
+ end
80
+
81
+ @loaded = false
82
+ @lock_acquired = false
83
+
84
+ logger.info("environment") { "Environment initialized (#{self})" }
85
+ logger.info("environment") { " - cwd: #{cwd}" }
86
+ logger.info("environment") { " - parent: #{parent}" }
87
+ logger.info("environment") { " - vm: #{vm}" }
88
+ end
89
+
90
+ #---------------------------------------------------------------
91
+ # Helpers
92
+ #---------------------------------------------------------------
93
+
94
+ # The path to the `dotfile`, which contains the persisted UUID of
95
+ # the VM if it exists.
96
+ #
97
+ # @return [Pathname]
98
+ def dotfile_path
99
+ root_path.join(config.vagrant.dotfile_name) rescue nil
100
+ end
101
+
102
+ # The path to the home directory and converted into a Pathname object.
103
+ #
104
+ # @return [Pathname]
105
+ def home_path
106
+ return parent.home_path if parent
107
+ return @_home_path if defined?(@_home_path)
108
+
109
+ @_home_path ||= Pathname.new(File.expand_path(ENV["VAGRANT_HOME"] || DEFAULT_HOME))
110
+ logger.info("environment") { "Home path: #{@_home_path}" }
111
+
112
+ # This is the old default that Vagrant used to be put things into
113
+ # up until Vagrant 0.8.0. We keep around an automatic migration
114
+ # script here in case any old users upgrade.
115
+ old_home = File.expand_path("~/.vagrant")
116
+ if File.exists?(old_home) && File.directory?(old_home)
117
+ logger.info("environment") { "Found both an old and new Vagrantfile. Migration initiated." }
118
+
119
+ # We can't migrate if the home directory already exists
120
+ if File.exists?(@_home_path)
121
+ ui.warn I18n.t("vagrant.general.home_dir_migration_failed",
122
+ :old => old_home,
123
+ :new => @_home_path.to_s)
124
+ else
125
+ # If the new home path doesn't exist, simply transition to it
126
+ ui.info I18n.t("vagrant.general.moving_home_dir", :directory => @_home_path)
127
+ FileUtils.mv(old_home, @_home_path)
128
+ end
129
+ end
130
+
131
+ # Return the home path
132
+ @_home_path
133
+ end
134
+
135
+ # The path to the Vagrant tmp directory
136
+ #
137
+ # @return [Pathname]
138
+ def tmp_path
139
+ home_path.join("tmp")
140
+ end
141
+
142
+ # The path to the Vagrant boxes directory
143
+ #
144
+ # @return [Pathname]
145
+ def boxes_path
146
+ home_path.join("boxes")
147
+ end
148
+
149
+ # Path to the Vagrant logs directory
150
+ #
151
+ # @return [Pathname]
152
+ def log_path
153
+ home_path.join("logs")
154
+ end
155
+
156
+ # Returns the name of the resource which this environment represents.
157
+ # The resource is the VM name if there is a VM it represents, otherwise
158
+ # it defaults to "vagrant"
159
+ #
160
+ # @return [String]
161
+ def resource
162
+ result = vm.name rescue nil
163
+ result || "vagrant"
164
+ end
165
+
166
+ # Returns the collection of boxes for the environment.
167
+ #
168
+ # @return [BoxCollection]
169
+ def boxes
170
+ return parent.boxes if parent
171
+ @_boxes ||= BoxCollection.new(self)
172
+ end
173
+
174
+ # Returns the box that this environment represents.
175
+ #
176
+ # @return [Box]
177
+ def box
178
+ boxes.find(config.vm.box)
179
+ end
180
+
181
+ # Returns the VMs associated with this environment.
182
+ #
183
+ # @return [Hash<Symbol,VM>]
184
+ def vms
185
+ return parent.vms if parent
186
+ load! if !loaded?
187
+ @vms ||= load_vms!
188
+ end
189
+
190
+ # Returns the VMs associated with this environment, in the order
191
+ # that they were defined.
192
+ #
193
+ # @return [Array<VM>]
194
+ def vms_ordered
195
+ @vms_enum ||= config.vm.defined_vm_keys.map { |name| @vms[name] }
196
+ end
197
+
198
+ # Returns the primary VM associated with this environment. This
199
+ # method is only applicable for multi-VM environments. This can
200
+ # potentially be nil if no primary VM is specified.
201
+ #
202
+ # @return [VM]
203
+ def primary_vm
204
+ return vms.values.first if !multivm?
205
+ return parent.primary_vm if parent
206
+
207
+ config.vm.defined_vms.each do |name, subvm|
208
+ return vms[name] if subvm.options[:primary]
209
+ end
210
+
211
+ nil
212
+ end
213
+
214
+ # Returns a boolean whether this environment represents a multi-VM
215
+ # environment or not. This will work even when called on child
216
+ # environments.
217
+ #
218
+ # @return [Bool]
219
+ def multivm?
220
+ if parent
221
+ parent.multivm?
222
+ else
223
+ vms.length > 1 || vms.keys.first != DEFAULT_VM
224
+ end
225
+ end
226
+
227
+ # Makes a call to the CLI with the given arguments as if they
228
+ # came from the real command line (sometimes they do!). An example:
229
+ #
230
+ # env.cli("package", "--vagrantfile", "Vagrantfile")
231
+ #
232
+ def cli(*args)
233
+ CLI.start(args.flatten, :env => self)
234
+ end
235
+
236
+ # Returns the {UI} for the environment, which is responsible
237
+ # for talking with the outside world.
238
+ #
239
+ # @return [UI]
240
+ def ui
241
+ @ui ||= if parent
242
+ result = parent.ui.clone
243
+ result.env = self
244
+ result
245
+ else
246
+ UI.new(self)
247
+ end
248
+ end
249
+
250
+ # Returns the host object associated with this environment.
251
+ #
252
+ # @return [Hosts::Base]
253
+ def host
254
+ @host ||= Hosts::Base.load(self, config.vagrant.host)
255
+ end
256
+
257
+ # Returns the {Action} class for this environment which allows actions
258
+ # to be executed (middleware chains) in the context of this environment.
259
+ #
260
+ # @return [Action]
261
+ def actions
262
+ @actions ||= Action.new(self)
263
+ end
264
+
265
+ # Loads on initial access and reads data from the global data store.
266
+ # The global data store is global to Vagrant everywhere (in every environment),
267
+ # so it can be used to store system-wide information. Note that "system-wide"
268
+ # typically means "for this user" since the location of the global data
269
+ # store is in the home directory.
270
+ #
271
+ # @return [DataStore]
272
+ def global_data
273
+ return parent.global_data if parent
274
+ @global_data ||= DataStore.new(File.expand_path("global_data.json", home_path))
275
+ end
276
+
277
+ # Loads (on initial access) and reads data from the local data
278
+ # store. This file is always at the root path as the file "~/.vagrant"
279
+ # and contains a JSON dump of a hash. See {DataStore} for more
280
+ # information.
281
+ #
282
+ # @return [DataStore]
283
+ def local_data
284
+ return parent.local_data if parent
285
+ @local_data ||= DataStore.new(dotfile_path)
286
+ end
287
+
288
+ # Accesses the logger for Vagrant. This logger is a _detailed_
289
+ # logger which should be used to log internals only. For outward
290
+ # facing information, use {#ui}.
291
+ #
292
+ # @return [Logger]
293
+ def logger
294
+ return parent.logger if parent
295
+ return @logger if @logger
296
+
297
+ # Figure out where the output should go to.
298
+ output = nil
299
+ if ENV["VAGRANT_LOG"] == "STDOUT"
300
+ output = STDOUT
301
+ elsif ENV["VAGRANT_LOG"] == "NULL"
302
+ output = nil
303
+ elsif ENV["VAGRANT_LOG"]
304
+ output = ENV["VAGRANT_LOG"]
305
+ else
306
+ output = nil #log_path.join("#{Time.now.to_i}.log")
307
+ end
308
+
309
+ # Create the logger and custom formatter
310
+ @logger = Logger.new(output)
311
+ @logger.formatter = Proc.new do |severity, datetime, progname, msg|
312
+ "#{datetime} - #{progname} - [#{resource}] #{msg}\n"
313
+ end
314
+
315
+ @logger
316
+ end
317
+
318
+ # The root path is the path where the top-most (loaded last)
319
+ # Vagrantfile resides. It can be considered the project root for
320
+ # this environment.
321
+ #
322
+ # @return [String]
323
+ def root_path
324
+ return @root_path if defined?(@root_path)
325
+
326
+ root_finder = lambda do |path|
327
+ # Note: To remain compatible with Ruby 1.8, we have to use
328
+ # a `find` here instead of an `each`.
329
+ found = vagrantfile_name.find do |rootfile|
330
+ File.exist?(File.join(path.to_s, rootfile))
331
+ end
332
+
333
+ return path if found
334
+ return nil if path.root? || !File.exist?(path)
335
+ root_finder.call(path.parent)
336
+ end
337
+
338
+ @root_path = root_finder.call(cwd)
339
+ end
340
+
341
+ # This returns the path which Vagrant uses to determine the location
342
+ # of the file lock. This is specific to each operating system.
343
+ def lock_path
344
+ @lock_path || tmp_path.join("vagrant.lock")
345
+ end
346
+
347
+ # This locks Vagrant for the duration of the block passed to this
348
+ # method. During this time, any other environment which attempts
349
+ # to lock which points to the same lock file will fail.
350
+ def lock
351
+ # This allows multiple locks in the same process to be nested
352
+ return yield if @lock_acquired
353
+
354
+ File.open(lock_path, "w+") do |f|
355
+ # The file locking fails only if it returns "false." If it
356
+ # succeeds it returns a 0, so we must explicitly check for
357
+ # the proper error case.
358
+ raise Errors::EnvironmentLockedError if f.flock(File::LOCK_EX | File::LOCK_NB) === false
359
+
360
+ begin
361
+ # Mark that we have a lock
362
+ @lock_acquired = true
363
+
364
+ yield
365
+ ensure
366
+ # We need to make sure that no matter what this is always
367
+ # reset to false so we don't think we have a lock when we
368
+ # actually don't.
369
+ @lock_acquired = false
370
+ end
371
+ end
372
+ end
373
+
374
+ #---------------------------------------------------------------
375
+ # Config Methods
376
+ #---------------------------------------------------------------
377
+
378
+ # The configuration object represented by this environment. This
379
+ # will trigger the environment to load if it hasn't loaded yet (see
380
+ # {#load!}).
381
+ #
382
+ # @return [Config::Top]
383
+ def config
384
+ load! if !loaded?
385
+ @config
386
+ end
387
+
388
+ #---------------------------------------------------------------
389
+ # Load Methods
390
+ #---------------------------------------------------------------
391
+
392
+ # Returns a boolean representing if the environment has been
393
+ # loaded or not.
394
+ #
395
+ # @return [Bool]
396
+ def loaded?
397
+ !!@loaded
398
+ end
399
+
400
+ # Loads this entire environment, setting up the instance variables
401
+ # such as `vm`, `config`, etc. on this environment. The order this
402
+ # method calls its other methods is very particular.
403
+ def load!
404
+ if !loaded?
405
+ @loaded = true
406
+
407
+ if !parent
408
+ # We only need to check the virtualbox version once, so do it on
409
+ # the parent most environment and then forget about it
410
+ logger.info("environment") { "Environment not loaded. Checking virtual box version..." }
411
+ self.class.check_virtualbox!
412
+ end
413
+
414
+ logger.info("environment") { "Loading configuration..." }
415
+ load_config!
416
+ end
417
+
418
+ self
419
+ end
420
+
421
+ # Reloads the configuration of this environment.
422
+ def reload_config!
423
+ @config = nil
424
+ @config_loader = nil
425
+ load_config!
426
+ self
427
+ end
428
+
429
+ # Loads this environment's configuration and stores it in the {#config}
430
+ # variable. The configuration loaded by this method is specified to
431
+ # this environment, meaning that it will use the given root directory
432
+ # to load the Vagrantfile into that context.
433
+ def load_config!
434
+ first_run = @config.nil?
435
+
436
+ # First load the initial, non config-dependent Vagrantfiles
437
+ @config_loader ||= Config.new(parent ? parent.config_loader : nil)
438
+ @config_loader.load_order = [:default, :box, :home, :root, :sub_vm]
439
+ @config_loader.set(:default, File.expand_path("config/default.rb", Vagrant.source_root))
440
+
441
+ vagrantfile_name.each do |rootfile|
442
+ if !first_run && vm && box
443
+ # We load the box Vagrantfile
444
+ box_vagrantfile = box.directory.join(rootfile)
445
+ @config_loader.set(:box, box_vagrantfile) if box_vagrantfile.exist?
446
+ end
447
+
448
+ if !first_run && home_path
449
+ # Load the home Vagrantfile
450
+ home_vagrantfile = home_path.join(rootfile)
451
+ @config_loader.set(:home, home_vagrantfile) if home_vagrantfile.exist?
452
+ end
453
+
454
+ if root_path
455
+ # Load the Vagrantfile in this directory
456
+ root_vagrantfile = root_path.join(rootfile)
457
+ @config_loader.set(:root, root_vagrantfile) if root_vagrantfile.exist?
458
+ end
459
+ end
460
+
461
+ # If this environment is representing a sub-VM, then we push that
462
+ # proc on as the last configuration.
463
+ if vm
464
+ subvm = parent.config.vm.defined_vms[vm.name]
465
+ @config_loader.set(:sub_vm, subvm.proc_stack) if subvm
466
+ end
467
+
468
+ # Execute the configuration stack and store the result as the final
469
+ # value in the config ivar.
470
+ @config = @config_loader.load(self)
471
+
472
+ if first_run
473
+ # After the first run we want to load the configuration again since
474
+ # it can change due to box Vagrantfiles and home directory Vagrantfiles
475
+ load_home_directory!
476
+ load_config!
477
+ end
478
+ end
479
+
480
+ # Loads the home directory path and creates the necessary subdirectories
481
+ # within the home directory if they're not already created.
482
+ def load_home_directory!
483
+ # Setup the array of necessary home directories
484
+ dirs = [home_path]
485
+ dirs += HOME_SUBDIRS.collect { |subdir| home_path.join(subdir) }
486
+
487
+ # Go through each required directory, creating it if it doesn't exist
488
+ dirs.each do |dir|
489
+ next if File.directory?(dir)
490
+
491
+ ui.info I18n.t("vagrant.general.creating_home_dir", :directory => dir)
492
+ FileUtils.mkdir_p(dir)
493
+ end
494
+ end
495
+
496
+ # Loads the persisted VM (if it exists) for this environment.
497
+ def load_vms!
498
+ result = {}
499
+
500
+ # Load the VM UUIDs from the local data store
501
+ (local_data[:active] || {}).each do |name, uuid|
502
+ result[name.to_sym] = Vagrant::VM.find(uuid, self, name.to_sym)
503
+ end
504
+
505
+ # For any VMs which aren't created, create a blank VM instance for
506
+ # them
507
+ all_keys = config.vm.defined_vm_keys
508
+ all_keys = [DEFAULT_VM] if all_keys.empty?
509
+ all_keys.each do |name|
510
+ result[name] = Vagrant::VM.new(:name => name, :env => self) if !result.has_key?(name)
511
+ end
512
+
513
+ result
514
+ end
515
+ end
516
+ end