rvagrant 0.8.7.dev

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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