vagrant-veertu 0.0.12
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.
- checksums.yaml +7 -0
- data/Gemfile +11 -0
- data/LICENSE.txt +22 -0
- data/README.md +31 -0
- data/Rakefile +5 -0
- data/lib/vagrant-veertu.rb +18 -0
- data/lib/vagrant-veertu/action.rb +330 -0
- data/lib/vagrant-veertu/action/boot.rb +21 -0
- data/lib/vagrant-veertu/action/check_accessible.rb +22 -0
- data/lib/vagrant-veertu/action/check_created.rb +21 -0
- data/lib/vagrant-veertu/action/check_running.rb +21 -0
- data/lib/vagrant-veertu/action/check_veertu.rb +22 -0
- data/lib/vagrant-veertu/action/clear_forwarded_ports.rb +20 -0
- data/lib/vagrant-veertu/action/clear_network_interfaces.rb +31 -0
- data/lib/vagrant-veertu/action/created.rb +20 -0
- data/lib/vagrant-veertu/action/customize.rb +44 -0
- data/lib/vagrant-veertu/action/destroy.rb +19 -0
- data/lib/vagrant-veertu/action/discard_state.rb +20 -0
- data/lib/vagrant-veertu/action/export.rb +41 -0
- data/lib/vagrant-veertu/action/forced_halt.rb +25 -0
- data/lib/vagrant-veertu/action/forward_ports.rb +91 -0
- data/lib/vagrant-veertu/action/import.rb +96 -0
- data/lib/vagrant-veertu/action/is_paused.rb +20 -0
- data/lib/vagrant-veertu/action/is_running.rb +20 -0
- data/lib/vagrant-veertu/action/is_saved.rb +20 -0
- data/lib/vagrant-veertu/action/message_already_running.rb +16 -0
- data/lib/vagrant-veertu/action/message_not_created.rb +16 -0
- data/lib/vagrant-veertu/action/message_not_running.rb +16 -0
- data/lib/vagrant-veertu/action/message_will_not_destroy.rb +17 -0
- data/lib/vagrant-veertu/action/network.rb +556 -0
- data/lib/vagrant-veertu/action/network_fix_ipv6.rb +81 -0
- data/lib/vagrant-veertu/action/package.rb +44 -0
- data/lib/vagrant-veertu/action/package_vagrantfile.rb +33 -0
- data/lib/vagrant-veertu/action/prepare_forwarded_port_collision_params.rb +35 -0
- data/lib/vagrant-veertu/action/prepare_nfs_settings.rb +119 -0
- data/lib/vagrant-veertu/action/prepare_nfs_valid_ids.rb +17 -0
- data/lib/vagrant-veertu/action/resume.rb +21 -0
- data/lib/vagrant-veertu/action/sane_defaults.rb +89 -0
- data/lib/vagrant-veertu/action/set_name.rb +55 -0
- data/lib/vagrant-veertu/action/setup_package_files.rb +51 -0
- data/lib/vagrant-veertu/action/snapshot_delete.rb +32 -0
- data/lib/vagrant-veertu/action/snapshot_restore.rb +28 -0
- data/lib/vagrant-veertu/action/snapshot_save.rb +25 -0
- data/lib/vagrant-veertu/action/suspend.rb +20 -0
- data/lib/vagrant-veertu/cap.rb +23 -0
- data/lib/vagrant-veertu/cap/public_address.rb +15 -0
- data/lib/vagrant-veertu/config.rb +199 -0
- data/lib/vagrant-veertu/driver/base.rb +240 -0
- data/lib/vagrant-veertu/driver/meta.rb +143 -0
- data/lib/vagrant-veertu/driver/version_5_0.rb +284 -0
- data/lib/vagrant-veertu/errors.rb +18 -0
- data/lib/vagrant-veertu/model/forwarded_port.rb +70 -0
- data/lib/vagrant-veertu/plugin.rb +76 -0
- data/lib/vagrant-veertu/provider.rb +121 -0
- data/lib/vagrant-veertu/synced_folder.rb +120 -0
- data/lib/vagrant-veertu/util/compile_forwarded_ports.rb +35 -0
- data/lib/vagrant-veertu/version.rb +5 -0
- data/locales/en.yml +19 -0
- data/vagrant-veertu.gemspec +22 -0
- metadata +130 -0
@@ -0,0 +1,81 @@
|
|
1
|
+
require "ipaddr"
|
2
|
+
require "socket"
|
3
|
+
|
4
|
+
require "log4r"
|
5
|
+
|
6
|
+
require "vagrant/util/presence"
|
7
|
+
require "vagrant/util/scoped_hash_override"
|
8
|
+
|
9
|
+
module VagrantPlugins
|
10
|
+
module ProviderVeertu
|
11
|
+
module Action
|
12
|
+
# This middleware works around a bug in VirtualBox where booting
|
13
|
+
# a VM with an IPv6 host-only network will someties lose the
|
14
|
+
# route to that machine.
|
15
|
+
class NetworkFixIPv6
|
16
|
+
include Vagrant::Util::Presence
|
17
|
+
include Vagrant::Util::ScopedHashOverride
|
18
|
+
|
19
|
+
def initialize(app, env)
|
20
|
+
@logger = Log4r::Logger.new("vagrant::plugins::veertu::network")
|
21
|
+
@app = app
|
22
|
+
end
|
23
|
+
|
24
|
+
def call(env)
|
25
|
+
@env = env
|
26
|
+
|
27
|
+
# Determine if we have an IPv6 network
|
28
|
+
has_v6 = false
|
29
|
+
env[:machine].config.vm.networks.each do |type, options|
|
30
|
+
next if type != :private_network
|
31
|
+
options = scoped_hash_override(options, :veertu)
|
32
|
+
next if options[:ip].to_s.strip == ""
|
33
|
+
|
34
|
+
if IPAddr.new(options[:ip]).ipv6?
|
35
|
+
has_v6 = true
|
36
|
+
break
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
# Call up
|
41
|
+
@app.call(env)
|
42
|
+
|
43
|
+
# If we have no IPv6, forget it
|
44
|
+
return if !has_v6
|
45
|
+
|
46
|
+
host_only_interfaces(env).each do |interface|
|
47
|
+
next if !present?(interface[:ipv6])
|
48
|
+
next if interface[:status] != "Up"
|
49
|
+
|
50
|
+
ip = IPAddr.new(interface[:ipv6])
|
51
|
+
ip |= ("1" * (128 - interface[:ipv6_prefix].to_i)).to_i(2)
|
52
|
+
|
53
|
+
@logger.info("testing IPv6: #{ip}")
|
54
|
+
|
55
|
+
begin
|
56
|
+
UDPSocket.new(Socket::AF_INET6).connect(ip.to_s, 80)
|
57
|
+
rescue Errno::EHOSTUNREACH
|
58
|
+
@logger.info("IPv6 host unreachable. Fixing: #{ip}")
|
59
|
+
env[:machine].provider.driver.reconfig_host_only(interface)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
# The list of interface names for host-only adapters.
|
65
|
+
# @return [Array<String>]
|
66
|
+
def host_only_interface_names(env)
|
67
|
+
env[:machine].provider.driver.read_network_interfaces
|
68
|
+
.map { |_, i| i[:hostonly] if i[:type] == :hostonly }.compact
|
69
|
+
end
|
70
|
+
|
71
|
+
# The list of host_only_interfaces that are tied to a host-only adapter.
|
72
|
+
# @return [Array]
|
73
|
+
def host_only_interfaces(env)
|
74
|
+
iface_names = self.host_only_interface_names(env)
|
75
|
+
env[:machine].provider.driver.read_host_only_interfaces
|
76
|
+
.select { |interface| iface_names.include?(interface[:name]) }
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
|
3
|
+
require 'vagrant/action/general/package'
|
4
|
+
|
5
|
+
module VagrantPlugins
|
6
|
+
module ProviderVeertu
|
7
|
+
module Action
|
8
|
+
class Package < Vagrant::Action::General::Package
|
9
|
+
# Doing this so that we can test that the parent is properly
|
10
|
+
# called in the unit tests.
|
11
|
+
alias_method :general_call, :call
|
12
|
+
def call(env)
|
13
|
+
# Setup the temporary directory
|
14
|
+
@temp_dir = env[:tmp_path].join(Time.now.to_i.to_s)
|
15
|
+
env["export.temp_dir"] = @temp_dir
|
16
|
+
FileUtils.mkpath(env["export.temp_dir"])
|
17
|
+
|
18
|
+
# Just match up a couple environmental variables so that
|
19
|
+
# the superclass will do the right thing. Then, call the
|
20
|
+
# superclass
|
21
|
+
env["package.directory"] = env["export.temp_dir"]
|
22
|
+
|
23
|
+
general_call(env)
|
24
|
+
|
25
|
+
# Always call recover to clean up the temp dir
|
26
|
+
clean_temp_dir
|
27
|
+
end
|
28
|
+
|
29
|
+
def recover(env)
|
30
|
+
clean_temp_dir
|
31
|
+
super
|
32
|
+
end
|
33
|
+
|
34
|
+
protected
|
35
|
+
|
36
|
+
def clean_temp_dir
|
37
|
+
if @temp_dir && File.exist?(@temp_dir)
|
38
|
+
FileUtils.rm_rf(@temp_dir)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'vagrant/util/template_renderer'
|
2
|
+
|
3
|
+
module VagrantPlugins
|
4
|
+
module ProviderVeertu
|
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 ProviderVeertu
|
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,119 @@
|
|
1
|
+
require "vagrant/action/builtin/mixin_synced_folders"
|
2
|
+
|
3
|
+
module VagrantPlugins
|
4
|
+
module ProviderVeertu
|
5
|
+
module Action
|
6
|
+
class PrepareNFSSettings
|
7
|
+
include Vagrant::Action::Builtin::MixinSyncedFolders
|
8
|
+
include Vagrant::Util::Retryable
|
9
|
+
|
10
|
+
def initialize(app, env)
|
11
|
+
@app = app
|
12
|
+
@logger = Log4r::Logger.new("vagrant::action::vm::nfs")
|
13
|
+
end
|
14
|
+
|
15
|
+
def call(env)
|
16
|
+
@machine = env[:machine]
|
17
|
+
|
18
|
+
@app.call(env)
|
19
|
+
|
20
|
+
opts = {
|
21
|
+
cached: !!env[:synced_folders_cached],
|
22
|
+
config: env[:synced_folders_config],
|
23
|
+
disable_usable_check: !!env[:test],
|
24
|
+
}
|
25
|
+
folders = synced_folders(env[:machine], **opts)
|
26
|
+
|
27
|
+
if folders.key?(:nfs)
|
28
|
+
@logger.info("Using NFS, preparing NFS settings by reading host IP and machine IP")
|
29
|
+
add_ips_to_env!(env)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
# Extracts the proper host and guest IPs for NFS mounts and stores them
|
34
|
+
# in the environment for the SyncedFolder action to use them in
|
35
|
+
# mounting.
|
36
|
+
#
|
37
|
+
# The ! indicates that this method modifies its argument.
|
38
|
+
def add_ips_to_env!(env)
|
39
|
+
adapter, host_ip = find_host_only_adapter
|
40
|
+
machine_ip = read_static_machine_ips || read_dynamic_machine_ip(adapter)
|
41
|
+
|
42
|
+
raise Vagrant::Errors::NFSNoHostonlyNetwork if !host_ip || !machine_ip
|
43
|
+
|
44
|
+
env[:nfs_host_ip] = host_ip
|
45
|
+
env[:nfs_machine_ip] = machine_ip
|
46
|
+
end
|
47
|
+
|
48
|
+
# Finds first host only network adapter and returns its adapter number
|
49
|
+
# and IP address
|
50
|
+
#
|
51
|
+
# @return [Integer, String] adapter number, ip address of found host-only adapter
|
52
|
+
def find_host_only_adapter
|
53
|
+
@machine.provider.driver.read_network_interfaces.each do |adapter, opts|
|
54
|
+
if opts[:type] == :hostonly
|
55
|
+
@machine.provider.driver.read_host_only_interfaces.each do |interface|
|
56
|
+
if interface[:name] == opts[:hostonly]
|
57
|
+
return adapter, interface[:ip]
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
nil
|
64
|
+
end
|
65
|
+
|
66
|
+
# Returns the IP address(es) of the guest by looking for static IPs
|
67
|
+
# given to host only adapters in the Vagrantfile
|
68
|
+
#
|
69
|
+
# @return [Array]<String> Configured static IPs
|
70
|
+
def read_static_machine_ips
|
71
|
+
ips = []
|
72
|
+
@machine.config.vm.networks.each do |type, options|
|
73
|
+
if type == :private_network && options[:type] != :dhcp && options[:ip].is_a?(String)
|
74
|
+
ips << options[:ip]
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
if ips.empty?
|
79
|
+
return nil
|
80
|
+
end
|
81
|
+
|
82
|
+
ips
|
83
|
+
end
|
84
|
+
|
85
|
+
# Returns the IP address of the guest by looking at vbox guest property
|
86
|
+
# for the appropriate guest adapter.
|
87
|
+
#
|
88
|
+
# For DHCP interfaces, the guest property will not be present until the
|
89
|
+
# guest completes
|
90
|
+
#
|
91
|
+
# @param [Integer] adapter number to read IP for
|
92
|
+
# @return [String] ip address of adapter
|
93
|
+
def read_dynamic_machine_ip(adapter)
|
94
|
+
return nil unless adapter
|
95
|
+
|
96
|
+
# vbox guest properties are 0-indexed, while showvminfo network
|
97
|
+
# interfaces are 1-indexed. go figure.
|
98
|
+
guestproperty_adapter = adapter - 1
|
99
|
+
|
100
|
+
# we need to wait for the guest's IP to show up as a guest property.
|
101
|
+
# retry thresholds are relatively high since we might need to wait
|
102
|
+
# for DHCP, but even static IPs can take a second or two to appear.
|
103
|
+
retryable(retry_options.merge(on: Vagrant::Errors::VirtualBoxGuestPropertyNotFound)) do
|
104
|
+
@machine.provider.driver.read_guest_ip(guestproperty_adapter)
|
105
|
+
end
|
106
|
+
rescue Vagrant::Errors::VirtualBoxGuestPropertyNotFound
|
107
|
+
# this error is more specific with a better error message directing
|
108
|
+
# the user towards the fact that it's probably a reportable bug
|
109
|
+
raise Vagrant::Errors::NFSNoGuestIP
|
110
|
+
end
|
111
|
+
|
112
|
+
# Separating these out so we can stub out the sleep in tests
|
113
|
+
def retry_options
|
114
|
+
{tries: 15, sleep: 1}
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module VagrantPlugins
|
2
|
+
module ProviderVeertu
|
3
|
+
module Action
|
4
|
+
class PrepareNFSValidIds
|
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
|
+
env[:nfs_valid_ids] = env[:machine].provider.driver.read_vms.values
|
12
|
+
@app.call(env)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module VagrantPlugins
|
2
|
+
module ProviderVeertu
|
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].state.id
|
11
|
+
|
12
|
+
if current_state == :paused or current_state == :stopped
|
13
|
+
env[:ui].info I18n.t("vagrant.actions.vm.resume.resuming")
|
14
|
+
env[:machine].provider.driver.resume
|
15
|
+
end
|
16
|
+
@app.call(env)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
require "log4r"
|
2
|
+
|
3
|
+
module VagrantPlugins
|
4
|
+
module ProviderVeertu
|
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
|
+
# Use rtcuseutc so that the VM sees UTC time.
|
18
|
+
#command = ["modifyvm", env[:machine].id, "--rtcuseutc", "on"]
|
19
|
+
#attempt_and_log(command, "Enabling rtcuseutc...")
|
20
|
+
|
21
|
+
if env[:machine].provider_config.auto_nat_dns_proxy
|
22
|
+
@logger.info("Automatically figuring out whether to enable/disable NAT DNS proxy...")
|
23
|
+
|
24
|
+
# Enable/disable the NAT DNS proxy as necessary
|
25
|
+
#if enable_dns_proxy?
|
26
|
+
# #command = ["modifyvm", env[:machine].id, "--natdnsproxy1", "on"]
|
27
|
+
# #attempt_and_log(command, "Enable the NAT DNS proxy on adapter 1...")
|
28
|
+
#else
|
29
|
+
# command = ["modifyvm", env[:machine].id, "--natdnsproxy1", "off" ]
|
30
|
+
# attempt_and_log(command, "Disable the NAT DNS proxy on adapter 1...")
|
31
|
+
# command = ["modifyvm", env[:machine].id, "--natdnshostresolver1", "off" ]
|
32
|
+
# attempt_and_log(command, "Disable the NAT DNS resolver on adapter 1...")
|
33
|
+
#end
|
34
|
+
else
|
35
|
+
@logger.info("NOT trying to automatically manage NAT DNS proxy.")
|
36
|
+
end
|
37
|
+
|
38
|
+
@app.call(env)
|
39
|
+
end
|
40
|
+
|
41
|
+
protected
|
42
|
+
|
43
|
+
# This is just a helper method that executes a single command, logs
|
44
|
+
# the given string to the log, and also includes the exit status in
|
45
|
+
# the log message.
|
46
|
+
#
|
47
|
+
# We assume every command is idempotent and pass along the `retryable`
|
48
|
+
# flag. This is because VeertuManage is janky about running simultaneously
|
49
|
+
# on the same box, and if we up multiple boxes at the same time, a bunch
|
50
|
+
# of modifyvm commands get fired
|
51
|
+
#
|
52
|
+
# @param [Array] command Command to run
|
53
|
+
# @param [String] log Log message to write.
|
54
|
+
def attempt_and_log(command, log)
|
55
|
+
begin
|
56
|
+
@env[:machine].provider.driver.execute_command(
|
57
|
+
command + [retryable: true])
|
58
|
+
rescue Vagrant::Errors::VBoxManageError => e
|
59
|
+
@logger.info("#{log} (error = #{e.inspect})")
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
# This uses some heuristics to determine if the NAT DNS proxy should
|
64
|
+
# be enabled or disabled. See the comments within the function body
|
65
|
+
# itself to see the checks it does.
|
66
|
+
#
|
67
|
+
# @return [Boolean]
|
68
|
+
def enable_dns_proxy?
|
69
|
+
begin
|
70
|
+
contents = File.read("/etc/resolv.conf")
|
71
|
+
|
72
|
+
if contents =~ /^nameserver 127\.0\.(0|1)\.1$/
|
73
|
+
# The use of both natdnsproxy and natdnshostresolver break on
|
74
|
+
# Ubuntu 12.04 and 12.10 that uses resolvconf with localhost. When used
|
75
|
+
# VirtualBox will give the client dns server 10.0.2.3, while
|
76
|
+
# not binding to that address itself. Therefore disable this
|
77
|
+
# feature if host uses the resolvconf server 127.0.0.1 or
|
78
|
+
# 127.0.1.1
|
79
|
+
@logger.info("Disabling DNS proxy since resolv.conf contains 127.0.0.1 or 127.0.1.1")
|
80
|
+
return false
|
81
|
+
end
|
82
|
+
rescue Errno::ENOENT; end
|
83
|
+
|
84
|
+
return true
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|