vagrant-vmware-free 0.0.1

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 (66) hide show
  1. data/.gitignore +5 -0
  2. data/.ruby-version +1 -0
  3. data/Gemfile +7 -0
  4. data/Gemfile.lock +57 -0
  5. data/LICENSE +21 -0
  6. data/README.md +10 -0
  7. data/Rakefile +3 -0
  8. data/lib/vagrant_vmware_free.rb +5 -0
  9. data/lib/vagrant_vmware_free/action.rb +214 -0
  10. data/lib/vagrant_vmware_free/action/boot.rb +23 -0
  11. data/lib/vagrant_vmware_free/action/check_accessible.rb +23 -0
  12. data/lib/vagrant_vmware_free/action/check_created.rb +21 -0
  13. data/lib/vagrant_vmware_free/action/check_guest_additions.rb +45 -0
  14. data/lib/vagrant_vmware_free/action/check_running.rb +21 -0
  15. data/lib/vagrant_vmware_free/action/check_virtualbox.rb +22 -0
  16. data/lib/vagrant_vmware_free/action/clean_machine_folder.rb +43 -0
  17. data/lib/vagrant_vmware_free/action/clear_forwarded_ports.rb +18 -0
  18. data/lib/vagrant_vmware_free/action/clear_network_interfaces.rb +31 -0
  19. data/lib/vagrant_vmware_free/action/clear_shared_folders.rb +17 -0
  20. data/lib/vagrant_vmware_free/action/created.rb +20 -0
  21. data/lib/vagrant_vmware_free/action/customize.rb +43 -0
  22. data/lib/vagrant_vmware_free/action/destroy.rb +19 -0
  23. data/lib/vagrant_vmware_free/action/destroy_unused_network_interfaces.rb +23 -0
  24. data/lib/vagrant_vmware_free/action/discard_state.rb +20 -0
  25. data/lib/vagrant_vmware_free/action/export.rb +57 -0
  26. data/lib/vagrant_vmware_free/action/forced_halt.rb +25 -0
  27. data/lib/vagrant_vmware_free/action/forward_ports.rb +89 -0
  28. data/lib/vagrant_vmware_free/action/get_network_address.rb +27 -0
  29. data/lib/vagrant_vmware_free/action/import.rb +56 -0
  30. data/lib/vagrant_vmware_free/action/is_paused.rb +20 -0
  31. data/lib/vagrant_vmware_free/action/is_running.rb +20 -0
  32. data/lib/vagrant_vmware_free/action/is_saved.rb +20 -0
  33. data/lib/vagrant_vmware_free/action/match_mac_address.rb +21 -0
  34. data/lib/vagrant_vmware_free/action/message_already_running.rb +16 -0
  35. data/lib/vagrant_vmware_free/action/message_not_created.rb +16 -0
  36. data/lib/vagrant_vmware_free/action/message_not_running.rb +16 -0
  37. data/lib/vagrant_vmware_free/action/message_will_not_destroy.rb +17 -0
  38. data/lib/vagrant_vmware_free/action/network.rb +424 -0
  39. data/lib/vagrant_vmware_free/action/package.rb +20 -0
  40. data/lib/vagrant_vmware_free/action/package_vagrantfile.rb +33 -0
  41. data/lib/vagrant_vmware_free/action/prepare_forwarded_port_collision_params.rb +35 -0
  42. data/lib/vagrant_vmware_free/action/prepare_nfs_settings.rb +69 -0
  43. data/lib/vagrant_vmware_free/action/prune_nfs_exports.rb +20 -0
  44. data/lib/vagrant_vmware_free/action/resume.rb +26 -0
  45. data/lib/vagrant_vmware_free/action/sane_defaults.rb +91 -0
  46. data/lib/vagrant_vmware_free/action/set_name.rb +52 -0
  47. data/lib/vagrant_vmware_free/action/set_network.rb +17 -0
  48. data/lib/vagrant_vmware_free/action/setup_package_files.rb +51 -0
  49. data/lib/vagrant_vmware_free/action/share_folders.rb +128 -0
  50. data/lib/vagrant_vmware_free/action/suspend.rb +20 -0
  51. data/lib/vagrant_vmware_free/action/wait_for_vm_tools.rb +19 -0
  52. data/lib/vagrant_vmware_free/config.rb +38 -0
  53. data/lib/vagrant_vmware_free/driver/base.rb +14 -0
  54. data/lib/vagrant_vmware_free/driver/fusion.rb +17 -0
  55. data/lib/vagrant_vmware_free/driver/fusion_6.rb +188 -0
  56. data/lib/vagrant_vmware_free/driver/meta.rb +122 -0
  57. data/lib/vagrant_vmware_free/driver/vix.rb +19 -0
  58. data/lib/vagrant_vmware_free/driver/vix/functions.rb +38 -0
  59. data/lib/vagrant_vmware_free/driver/vix/helpers.rb +63 -0
  60. data/lib/vagrant_vmware_free/driver/vix/types.rb +143 -0
  61. data/lib/vagrant_vmware_free/errors.rb +9 -0
  62. data/lib/vagrant_vmware_free/plugin.rb +43 -0
  63. data/lib/vagrant_vmware_free/provider.rb +62 -0
  64. data/lib/vagrant_vmware_free/util/vmx.rb +48 -0
  65. data/vagrant-vmware-free.gemspec +21 -0
  66. metadata +190 -0
@@ -0,0 +1,20 @@
1
+ require 'vagrant/action/general/package'
2
+
3
+ module VagrantPlugins
4
+ module ProviderVMwareFree
5
+ module Action
6
+ class Package < Vagrant::Action::General::Package
7
+ # Doing this so that we can test that the parent is properly
8
+ # called in the unit tests.
9
+ alias_method :general_call, :call
10
+ def call(env)
11
+ # Just match up a couple environmental variables so that
12
+ # the superclass will do the right thing. Then, call the
13
+ # superclass
14
+ env["package.directory"] = env["export.temp_dir"]
15
+ general_call(env)
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,33 @@
1
+ require 'vagrant/util/template_renderer'
2
+
3
+ module VagrantPlugins
4
+ module ProviderVMwareFree
5
+ module Action
6
+ class PackageVagrantfile
7
+ # For TemplateRenderer
8
+ include Vagrant::Util
9
+
10
+ def initialize(app, env)
11
+ @app = app
12
+ end
13
+
14
+ def call(env)
15
+ @env = env
16
+ create_vagrantfile
17
+ @app.call(env)
18
+ end
19
+
20
+ # This method creates the auto-generated Vagrantfile at the root of the
21
+ # box. This Vagrantfile contains the MAC address so that the user doesn't
22
+ # have to worry about it.
23
+ def create_vagrantfile
24
+ File.open(File.join(@env["export.temp_dir"], "Vagrantfile"), "w") do |f|
25
+ f.write(TemplateRenderer.render("package_Vagrantfile", {
26
+ :base_mac => @env[:machine].provider.driver.read_mac_address
27
+ }))
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,35 @@
1
+ module VagrantPlugins
2
+ module ProviderVMwareFree
3
+ module Action
4
+ class PrepareForwardedPortCollisionParams
5
+ def initialize(app, env)
6
+ @app = app
7
+ end
8
+
9
+ def call(env)
10
+ # Get the forwarded ports used by other virtual machines and
11
+ # consider those in use as well.
12
+ env[:port_collision_extra_in_use] = env[:machine].provider.driver.read_used_ports
13
+
14
+ # Build the remap for any existing collision detections
15
+ remap = {}
16
+ env[:port_collision_remap] = remap
17
+ env[:machine].provider.driver.read_forwarded_ports.each do |_nic, name, hostport, _guestport|
18
+ env[:machine].config.vm.networks.each do |type, options|
19
+ next if type != :forwarded_port
20
+
21
+ # If the ID matches the name of the forwarded port, then
22
+ # remap.
23
+ if options[:id] == name
24
+ remap[options[:host]] = hostport
25
+ break
26
+ end
27
+ end
28
+ end
29
+
30
+ @app.call(env)
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,69 @@
1
+ module VagrantPlugins
2
+ module ProviderVMwareFree
3
+ module Action
4
+ class PrepareNFSSettings
5
+ def initialize(app,env)
6
+ @app = app
7
+ @logger = Log4r::Logger.new("vagrant::action::vm::nfs")
8
+ end
9
+
10
+ def call(env)
11
+ @app.call(env)
12
+
13
+ using_nfs = false
14
+ env[:machine].config.vm.synced_folders.each do |id, opts|
15
+ if opts[:nfs]
16
+ using_nfs = true
17
+ break
18
+ end
19
+ end
20
+
21
+ if using_nfs
22
+ @logger.info("Using NFS, preparing NFS settings by reading host IP and machine IP")
23
+ env[:nfs_host_ip] = read_host_ip(env[:machine])
24
+ env[:nfs_machine_ip] = read_machine_ip(env[:machine])
25
+
26
+ raise Vagrant::Errors::NFSNoHostonlyNetwork if !env[:nfs_machine_ip]
27
+ end
28
+ end
29
+
30
+ # Returns the IP address of the first host only network adapter
31
+ #
32
+ # @param [Machine] machine
33
+ # @return [String]
34
+ def read_host_ip(machine)
35
+ machine.provider.driver.read_network_interfaces.each do |adapter, opts|
36
+ if opts[:type] == :hostonly
37
+ machine.provider.driver.read_host_only_interfaces.each do |interface|
38
+ if interface[:name] == opts[:hostonly]
39
+ return interface[:ip]
40
+ end
41
+ end
42
+ end
43
+ end
44
+
45
+ nil
46
+ end
47
+
48
+ # Returns the IP address of the guest by looking at the first
49
+ # enabled host only network.
50
+ #
51
+ # @return [String]
52
+ def read_machine_ip(machine)
53
+ ips = []
54
+ machine.config.vm.networks.each do |type, options|
55
+ if type == :private_network && options[:ip].is_a?(String)
56
+ ips << options[:ip]
57
+ end
58
+ end
59
+
60
+ if ips.empty?
61
+ return nil
62
+ end
63
+
64
+ ips
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,20 @@
1
+ module VagrantPlugins
2
+ module ProviderVMwareFree
3
+ module Action
4
+ class PruneNFSExports
5
+ def initialize(app, env)
6
+ @app = app
7
+ end
8
+
9
+ def call(env)
10
+ if env[:host]
11
+ vms = env[:machine].provider.driver.read_vms
12
+ env[:host].nfs_prune(vms.values)
13
+ end
14
+
15
+ @app.call(env)
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,26 @@
1
+ module VagrantPlugins
2
+ module ProviderVMwareFree
3
+ module Action
4
+ class Resume
5
+ def initialize(app, env)
6
+ @app = app
7
+ end
8
+
9
+ def call(env)
10
+ current_state = env[:machine].provider.state.id
11
+ boot_mode = @env[:machine].provider_config.gui ? "gui" : "headless"
12
+
13
+ if current_state == :paused
14
+ env[:ui].info I18n.t("vagrant.actions.vm.resume.unpausing")
15
+ env[:machine].provider.driver.resume(boot_mode)
16
+ elsif current_state == :saved
17
+ env[:ui].info I18n.t("vagrant.actions.vm.resume.resuming")
18
+ env[:action_runner].run(Boot, env)
19
+ end
20
+
21
+ @app.call(env)
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,91 @@
1
+ require "log4r"
2
+
3
+ module VagrantPlugins
4
+ module ProviderVMwareFree
5
+ module Action
6
+ class SaneDefaults
7
+ def initialize(app, env)
8
+ @logger = Log4r::Logger.new("vagrant::action::vm::sanedefaults")
9
+ @app = app
10
+ end
11
+
12
+ def call(env)
13
+ # Set the env on an instance variable so we can access it in
14
+ # helpers.
15
+ @env = env
16
+
17
+ # Enable the host IO cache on the sata controller. Note that
18
+ # if this fails then its not a big deal, so we don't raise any
19
+ # errors. The Host IO cache vastly improves disk IO performance
20
+ # for VMs.
21
+ command = [
22
+ "storagectl", env[:machine].id,
23
+ "--name", "SATA Controller",
24
+ "--hostiocache", "on"
25
+ ]
26
+ attempt_and_log(command, "Enabling the Host I/O cache on the SATA controller...")
27
+
28
+ # Use rtcuseutc so that the VM sees UTC time.
29
+ command = ["modifyvm", env[:machine].id, "--rtcuseutc", "on"]
30
+ attempt_and_log(command, "Enabling rtcuseutc...")
31
+
32
+ if env[:machine].provider_config.auto_nat_dns_proxy
33
+ @logger.info("Automatically figuring out whether to enable/disable NAT DNS proxy...")
34
+
35
+ # Enable/disable the NAT DNS proxy as necessary
36
+ if enable_dns_proxy?
37
+ command = ["modifyvm", env[:machine].id, "--natdnsproxy1", "on"]
38
+ attempt_and_log(command, "Enable the NAT DNS proxy on adapter 1...")
39
+ else
40
+ command = [ "modifyvm", env[:machine].id, "--natdnsproxy1", "off" ]
41
+ attempt_and_log(command, "Disable the NAT DNS proxy on adapter 1...")
42
+ command = [ "modifyvm", env[:machine].id, "--natdnshostresolver1", "off" ]
43
+ attempt_and_log(command, "Disable the NAT DNS resolver on adapter 1...")
44
+ end
45
+ else
46
+ @logger.info("NOT trying to automatically manage NAT DNS proxy.")
47
+ end
48
+
49
+ @app.call(env)
50
+ end
51
+
52
+ protected
53
+
54
+ # This is just a helper method that executes a single command, logs
55
+ # the given string to the log, and also includes the exit status in
56
+ # the log message.
57
+ #
58
+ # @param [Array] command Command to run
59
+ # @param [String] log Log message to write.
60
+ def attempt_and_log(command, log)
61
+ result = @env[:machine].provider.driver.execute_command(command)
62
+ @logger.info("#{log} (exit status = #{result.exit_code})")
63
+ end
64
+
65
+ # This uses some heuristics to determine if the NAT DNS proxy should
66
+ # be enabled or disabled. See the comments within the function body
67
+ # itself to see the checks it does.
68
+ #
69
+ # @return [Boolean]
70
+ def enable_dns_proxy?
71
+ begin
72
+ contents = File.read("/etc/resolv.conf")
73
+
74
+ if contents =~ /^nameserver 127\.0\.(0|1)\.1$/
75
+ # The use of both natdnsproxy and natdnshostresolver break on
76
+ # Ubuntu 12.04 and 12.10 that uses resolvconf with localhost. When used
77
+ # VirtualBox will give the client dns server 10.0.2.3, while
78
+ # not binding to that address itself. Therefore disable this
79
+ # feature if host uses the resolvconf server 127.0.0.1 or
80
+ # 127.0.1.1
81
+ @logger.info("Disabling DNS proxy since resolv.conf contains 127.0.0.1 or 127.0.1.1")
82
+ return false
83
+ end
84
+ rescue Errno::ENOENT; end
85
+
86
+ return true
87
+ end
88
+ end
89
+ end
90
+ end
91
+ end
@@ -0,0 +1,52 @@
1
+ require "log4r"
2
+
3
+ module VagrantPlugins
4
+ module ProviderVMwareFree
5
+ module Action
6
+ class SetName
7
+ def initialize(app, env)
8
+ @logger = Log4r::Logger.new("vagrant::action::vm::setname")
9
+ @app = app
10
+ end
11
+
12
+ def call(env)
13
+ name = env[:machine].provider_config.name
14
+
15
+ # If we already set the name before, then don't do anything
16
+ sentinel = env[:machine].data_dir.join("action_set_name")
17
+ if !name && sentinel.file?
18
+ @logger.info("Default name was already set before, not doing it again.")
19
+ return @app.call(env)
20
+ end
21
+
22
+ # If no name was manually set, then use a default
23
+ if !name
24
+ prefix = "#{env[:root_path].basename.to_s}_#{env[:machine].name}"
25
+ prefix.gsub!(/[^-a-z0-9_]/i, "")
26
+ name = prefix + "_#{Time.now.to_i}"
27
+ end
28
+
29
+ # Verify the name is not taken
30
+ vms = env[:machine].provider.driver.read_vms
31
+ raise Vagrant::Errors::VMNameExists, :name => name if \
32
+ vms.any? { |uuid, data| data[:name] == name && data[:name] != env[:machine].id }
33
+
34
+ if vms.any? { |uuid, data| data[:name] == name }
35
+ @logger.info("Not setting the name because our name is already set.")
36
+ else
37
+ @logger.info("Setting the name of the VM: #{name}")
38
+ env[:ui].info(I18n.t("vagrant.actions.vm.set_name.setting_name"))
39
+ env[:machine].provider.driver.set_name(name)
40
+ end
41
+
42
+ # Create the sentinel
43
+ sentinel.open("w") do |f|
44
+ f.write(Time.now.to_i.to_s)
45
+ end
46
+
47
+ @app.call(env)
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,17 @@
1
+ module VagrantPlugins
2
+ module ProviderVMwareFree
3
+ module Action
4
+ class SetNetwork
5
+ def initialize(app, env)
6
+ @app = app
7
+ end
8
+
9
+ def call(env)
10
+ env[:machine].provider.driver.set_value('ethernet0.connectionType', 'hostonly')
11
+
12
+ @app.call(env)
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,51 @@
1
+ module VagrantPlugins
2
+ module ProviderVMwareFree
3
+ module Action
4
+ class SetupPackageFiles
5
+ def initialize(app, env)
6
+ @app = app
7
+
8
+ env["package.include"] ||= []
9
+ env["package.vagrantfile"] ||= nil
10
+ end
11
+
12
+ def call(env)
13
+ files = {}
14
+ env["package.include"].each do |file|
15
+ source = Pathname.new(file)
16
+ dest = nil
17
+
18
+ # If the source is relative then we add the file as-is to the include
19
+ # directory. Otherwise, we copy only the file into the root of the
20
+ # include directory. Kind of strange, but seems to match what people
21
+ # expect based on history.
22
+ if source.relative?
23
+ dest = source
24
+ else
25
+ dest = source.basename
26
+ end
27
+
28
+ # Assign the mapping
29
+ files[file] = dest
30
+ end
31
+
32
+ if env["package.vagrantfile"]
33
+ # Vagrantfiles are treated special and mapped to a specific file
34
+ files[env["package.vagrantfile"]] = "_Vagrantfile"
35
+ end
36
+
37
+ # Verify the mapping
38
+ files.each do |from, _|
39
+ raise Vagrant::Errors::PackageIncludeMissing,
40
+ :file => from if !File.exist?(from)
41
+ end
42
+
43
+ # Save the mapping
44
+ env["package.files"] = files
45
+
46
+ @app.call(env)
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,128 @@
1
+ require "pathname"
2
+
3
+ require "log4r"
4
+
5
+ require "vagrant/util/platform"
6
+ require "vagrant/util/scoped_hash_override"
7
+
8
+ module VagrantPlugins
9
+ module ProviderVMwareFree
10
+ module Action
11
+ class ShareFolders
12
+ include Vagrant::Util::ScopedHashOverride
13
+
14
+ def initialize(app, env)
15
+ @logger = Log4r::Logger.new("vagrant::action::vm::share_folders")
16
+ @app = app
17
+ end
18
+
19
+ def call(env)
20
+ @env = env
21
+
22
+ prepare_folders
23
+ create_metadata
24
+
25
+ @app.call(env)
26
+
27
+ mount_shared_folders
28
+ end
29
+
30
+ # This method returns an actual list of VirtualBox shared
31
+ # folders to create and their proper path.
32
+ def shared_folders
33
+ {}.tap do |result|
34
+ @env[:machine].config.vm.synced_folders.each do |id, data|
35
+ data = scoped_hash_override(data, :virtualbox)
36
+
37
+ # Ignore NFS shared folders
38
+ next if data[:nfs]
39
+
40
+ # Ignore disabled shared folders
41
+ next if data[:disabled]
42
+
43
+ # This to prevent overwriting the actual shared folders data
44
+ result[id] = data.dup
45
+ end
46
+ end
47
+ end
48
+
49
+ # Prepares the shared folders by verifying they exist and creating them
50
+ # if they don't.
51
+ def prepare_folders
52
+ shared_folders.each do |id, options|
53
+ hostpath = Pathname.new(options[:hostpath]).expand_path(@env[:root_path])
54
+
55
+ if !hostpath.directory? && options[:create]
56
+ # Host path doesn't exist, so let's create it.
57
+ @logger.debug("Host path doesn't exist, creating: #{hostpath}")
58
+
59
+ begin
60
+ hostpath.mkpath
61
+ rescue Errno::EACCES
62
+ raise Vagrant::Errors::SharedFolderCreateFailed,
63
+ :path => hostpath.to_s
64
+ end
65
+ end
66
+ end
67
+ end
68
+
69
+ def create_metadata
70
+ @env[:ui].info I18n.t("vagrant.actions.vm.share_folders.creating")
71
+
72
+ folders = []
73
+ shared_folders.each do |id, data|
74
+ hostpath = File.expand_path(data[:hostpath], @env[:root_path])
75
+ hostpath = Vagrant::Util::Platform.cygwin_windows_path(hostpath)
76
+
77
+ folders << {
78
+ :name => id,
79
+ :hostpath => hostpath,
80
+ :transient => data[:transient]
81
+ }
82
+ end
83
+
84
+ @env[:machine].provider.driver.share_folders(folders)
85
+ end
86
+
87
+ def mount_shared_folders
88
+ @env[:ui].info I18n.t("vagrant.actions.vm.share_folders.mounting")
89
+
90
+ # short guestpaths first, so we don't step on ourselves
91
+ folders = shared_folders.sort_by do |id, data|
92
+ if data[:guestpath]
93
+ data[:guestpath].length
94
+ else
95
+ # A long enough path to just do this at the end.
96
+ 10000
97
+ end
98
+ end
99
+
100
+ # Go through each folder and mount
101
+ folders.each do |id, data|
102
+ if data[:guestpath]
103
+ # Guest path specified, so mount the folder to specified point
104
+ @env[:ui].info(I18n.t("vagrant.actions.vm.share_folders.mounting_entry",
105
+ :guest_path => data[:guestpath]))
106
+
107
+ # Dup the data so we can pass it to the guest API
108
+ data = data.dup
109
+
110
+ # Calculate the owner and group
111
+ ssh_info = @env[:machine].ssh_info
112
+ data[:owner] ||= ssh_info[:username]
113
+ data[:group] ||= ssh_info[:username]
114
+
115
+ # Mount the actual folder
116
+ @env[:machine].guest.capability(
117
+ :mount_virtualbox_shared_folder, id, data[:guestpath], data)
118
+ else
119
+ # If no guest path is specified, then automounting is disabled
120
+ @env[:ui].info(I18n.t("vagrant.actions.vm.share_folders.nomount_entry",
121
+ :host_path => data[:hostpath]))
122
+ end
123
+ end
124
+ end
125
+ end
126
+ end
127
+ end
128
+ end