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,20 @@
|
|
1
|
+
module VagrantPlugins
|
2
|
+
module ProviderVeertu
|
3
|
+
module Action
|
4
|
+
class IsPaused
|
5
|
+
def initialize(app, env)
|
6
|
+
@app = app
|
7
|
+
end
|
8
|
+
|
9
|
+
def call(env)
|
10
|
+
# Set the result to be true if the machine is paused.
|
11
|
+
env[:result] = env[:machine].state.id == :paused
|
12
|
+
|
13
|
+
# Call the next if we have one (but we shouldn't, since this
|
14
|
+
# middleware is built to run with the Call-type middlewares)
|
15
|
+
@app.call(env)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module VagrantPlugins
|
2
|
+
module ProviderVeertu
|
3
|
+
module Action
|
4
|
+
class IsRunning
|
5
|
+
def initialize(app, env)
|
6
|
+
@app = app
|
7
|
+
end
|
8
|
+
|
9
|
+
def call(env)
|
10
|
+
# Set the result to be true if the machine is running.
|
11
|
+
env[:result] = env[:machine].state.id == :running
|
12
|
+
|
13
|
+
# Call the next if we have one (but we shouldn't, since this
|
14
|
+
# middleware is built to run with the Call-type middlewares)
|
15
|
+
@app.call(env)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module VagrantPlugins
|
2
|
+
module ProviderVeertu
|
3
|
+
module Action
|
4
|
+
class IsSaved
|
5
|
+
def initialize(app, env)
|
6
|
+
@app = app
|
7
|
+
end
|
8
|
+
|
9
|
+
def call(env)
|
10
|
+
# Set the result to be true if the machine is saved.
|
11
|
+
env[:result] = env[:machine].state.id == :paused
|
12
|
+
|
13
|
+
# Call the next if we have one (but we shouldn't, since this
|
14
|
+
# middleware is built to run with the Call-type middlewares)
|
15
|
+
@app.call(env)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module VagrantPlugins
|
2
|
+
module ProviderVeertu
|
3
|
+
module Action
|
4
|
+
class MessageAlreadyRunning
|
5
|
+
def initialize(app, env)
|
6
|
+
@app = app
|
7
|
+
end
|
8
|
+
|
9
|
+
def call(env)
|
10
|
+
env[:ui].info I18n.t("vagrant.commands.common.vm_already_running")
|
11
|
+
@app.call(env)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module VagrantPlugins
|
2
|
+
module ProviderVeertu
|
3
|
+
module Action
|
4
|
+
class MessageNotCreated
|
5
|
+
def initialize(app, env)
|
6
|
+
@app = app
|
7
|
+
end
|
8
|
+
|
9
|
+
def call(env)
|
10
|
+
env[:ui].info I18n.t("vagrant.commands.common.vm_not_created")
|
11
|
+
@app.call(env)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module VagrantPlugins
|
2
|
+
module ProviderVeertu
|
3
|
+
module Action
|
4
|
+
class MessageNotRunning
|
5
|
+
def initialize(app, env)
|
6
|
+
@app = app
|
7
|
+
end
|
8
|
+
|
9
|
+
def call(env)
|
10
|
+
env[:ui].info I18n.t("vagrant.commands.common.vm_not_running")
|
11
|
+
@app.call(env)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module VagrantPlugins
|
2
|
+
module ProviderVeertu
|
3
|
+
module Action
|
4
|
+
class MessageWillNotDestroy
|
5
|
+
def initialize(app, env)
|
6
|
+
@app = app
|
7
|
+
end
|
8
|
+
|
9
|
+
def call(env)
|
10
|
+
env[:ui].info I18n.t("vagrant.commands.destroy.will_not_destroy",
|
11
|
+
name: env[:machine].name)
|
12
|
+
@app.call(env)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,556 @@
|
|
1
|
+
require "ipaddr"
|
2
|
+
require "set"
|
3
|
+
|
4
|
+
require "log4r"
|
5
|
+
|
6
|
+
require "vagrant/util/network_ip"
|
7
|
+
require "vagrant/util/scoped_hash_override"
|
8
|
+
|
9
|
+
module VagrantPlugins
|
10
|
+
module ProviderVeertu
|
11
|
+
module Action
|
12
|
+
# This middleware class sets up all networking for the VirtualBox
|
13
|
+
# instance. This includes host only networks, bridged networking,
|
14
|
+
# forwarded ports, etc.
|
15
|
+
#
|
16
|
+
# This handles all the `config.vm.network` configurations.
|
17
|
+
class Network
|
18
|
+
include Vagrant::Util::NetworkIP
|
19
|
+
include Vagrant::Util::ScopedHashOverride
|
20
|
+
|
21
|
+
def initialize(app, env)
|
22
|
+
@logger = Log4r::Logger.new("vagrant::plugins::veertu::network")
|
23
|
+
@app = app
|
24
|
+
end
|
25
|
+
|
26
|
+
def call(env)
|
27
|
+
# TODO: Validate network configuration prior to anything below
|
28
|
+
@env = env
|
29
|
+
|
30
|
+
# Get the list of network adapters from the configuration
|
31
|
+
network_adapters_config = env[:machine].provider_config.network_adapters.dup
|
32
|
+
|
33
|
+
# Assign the adapter slot for each high-level network
|
34
|
+
available_slots = Set.new(1..36)
|
35
|
+
network_adapters_config.each do |slot, _data|
|
36
|
+
available_slots.delete(slot)
|
37
|
+
end
|
38
|
+
|
39
|
+
@logger.debug("Available slots for high-level adapters: #{available_slots.inspect}")
|
40
|
+
@logger.info("Determining network adapters required for high-level configuration...")
|
41
|
+
available_slots = available_slots.to_a.sort
|
42
|
+
env[:machine].config.vm.networks.each do |type, options|
|
43
|
+
# We only handle private and public networks
|
44
|
+
next if type != :private_network && type != :public_network
|
45
|
+
|
46
|
+
options = scoped_hash_override(options, :veertu)
|
47
|
+
|
48
|
+
# Figure out the slot that this adapter will go into
|
49
|
+
slot = options[:adapter]
|
50
|
+
if !slot
|
51
|
+
if available_slots.empty?
|
52
|
+
raise Vagrant::Errors::VirtualBoxNoRoomForHighLevelNetwork
|
53
|
+
end
|
54
|
+
|
55
|
+
slot = available_slots.shift
|
56
|
+
end
|
57
|
+
|
58
|
+
# Internal network is a special type
|
59
|
+
if type == :private_network && options[:intnet]
|
60
|
+
type = :internal_network
|
61
|
+
end
|
62
|
+
|
63
|
+
# Configure it
|
64
|
+
data = nil
|
65
|
+
if type == :private_network
|
66
|
+
# private_network = hostonly
|
67
|
+
data = [:hostonly, options]
|
68
|
+
elsif type == :public_network
|
69
|
+
# public_network = bridged
|
70
|
+
data = [:bridged, options]
|
71
|
+
elsif type == :internal_network
|
72
|
+
data = [:intnet, options]
|
73
|
+
end
|
74
|
+
|
75
|
+
# Store it!
|
76
|
+
@logger.info(" -- Slot #{slot}: #{data[0]}")
|
77
|
+
network_adapters_config[slot] = data
|
78
|
+
end
|
79
|
+
|
80
|
+
@logger.info("Determining adapters and compiling network configuration...")
|
81
|
+
adapters = []
|
82
|
+
networks = []
|
83
|
+
network_adapters_config.each do |slot, data|
|
84
|
+
type = data[0]
|
85
|
+
options = data[1]
|
86
|
+
|
87
|
+
@logger.info("Network slot #{slot}. Type: #{type}.")
|
88
|
+
|
89
|
+
# Get the normalized configuration for this type
|
90
|
+
config = send("#{type}_config", options)
|
91
|
+
config[:adapter] = slot
|
92
|
+
@logger.debug("Normalized configuration: #{config.inspect}")
|
93
|
+
|
94
|
+
# Get the VirtualBox adapter configuration
|
95
|
+
adapter = send("#{type}_adapter", config)
|
96
|
+
adapters << adapter
|
97
|
+
@logger.debug("Adapter configuration: #{adapter.inspect}")
|
98
|
+
|
99
|
+
# Get the network configuration
|
100
|
+
network = send("#{type}_network_config", config)
|
101
|
+
network[:auto_config] = config[:auto_config]
|
102
|
+
networks << network
|
103
|
+
end
|
104
|
+
|
105
|
+
if !adapters.empty?
|
106
|
+
# Enable the adapters
|
107
|
+
@logger.info("Enabling adapters...")
|
108
|
+
env[:ui].output(I18n.t("vagrant.actions.vm.network.preparing"))
|
109
|
+
adapters.each do |adapter|
|
110
|
+
env[:ui].detail(I18n.t(
|
111
|
+
"vagrant.virtualbox.network_adapter",
|
112
|
+
adapter: adapter[:adapter].to_s,
|
113
|
+
type: adapter[:type].to_s,
|
114
|
+
extra: "",
|
115
|
+
))
|
116
|
+
end
|
117
|
+
|
118
|
+
#env[:machine].provider.driver.enable_adapters(adapters)
|
119
|
+
end
|
120
|
+
|
121
|
+
# Continue the middleware chain.
|
122
|
+
@app.call(env)
|
123
|
+
|
124
|
+
# If we have networks to configure, then we configure it now, since
|
125
|
+
# that requires the machine to be up and running.
|
126
|
+
if !adapters.empty? && !networks.empty?
|
127
|
+
assign_interface_numbers(networks, adapters)
|
128
|
+
|
129
|
+
# Only configure the networks the user requested us to configure
|
130
|
+
networks_to_configure = networks.select { |n| n[:auto_config] }
|
131
|
+
if !networks_to_configure.empty?
|
132
|
+
env[:ui].info I18n.t("vagrant.actions.vm.network.configuring")
|
133
|
+
env[:machine].guest.capability(:configure_networks, networks_to_configure)
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
def bridged_config(options)
|
139
|
+
return {
|
140
|
+
auto_config: true,
|
141
|
+
bridge: nil,
|
142
|
+
mac: nil,
|
143
|
+
nic_type: nil,
|
144
|
+
use_dhcp_assigned_default_route: false
|
145
|
+
}.merge(options || {})
|
146
|
+
end
|
147
|
+
|
148
|
+
def bridged_adapter(config)
|
149
|
+
# Find the bridged interfaces that are available
|
150
|
+
bridgedifs = @env[:machine].provider.driver.read_bridged_interfaces
|
151
|
+
bridgedifs.delete_if { |interface| interface[:status] == "Down" || interface[:status] == "Unknown" }
|
152
|
+
|
153
|
+
# The name of the chosen bridge interface will be assigned to this
|
154
|
+
# variable.
|
155
|
+
chosen_bridge = nil
|
156
|
+
|
157
|
+
if config[:bridge]
|
158
|
+
@logger.debug("Bridge was directly specified in config, searching for: #{config[:bridge]}")
|
159
|
+
|
160
|
+
# Search for a matching bridged interface
|
161
|
+
Array(config[:bridge]).each do |bridge|
|
162
|
+
bridge = bridge.downcase if bridge.respond_to?(:downcase)
|
163
|
+
bridgedifs.each do |interface|
|
164
|
+
if bridge === interface[:name].downcase
|
165
|
+
@logger.debug("Specific bridge found as configured in the Vagrantfile. Using it.")
|
166
|
+
chosen_bridge = interface[:name]
|
167
|
+
break
|
168
|
+
end
|
169
|
+
end
|
170
|
+
break if chosen_bridge
|
171
|
+
end
|
172
|
+
|
173
|
+
# If one wasn't found, then we notify the user here.
|
174
|
+
if !chosen_bridge
|
175
|
+
@env[:ui].info I18n.t("vagrant.actions.vm.bridged_networking.specific_not_found",
|
176
|
+
bridge: config[:bridge])
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
# If we still don't have a bridge chosen (this means that one wasn't
|
181
|
+
# specified in the Vagrantfile, or the bridge specified in the Vagrantfile
|
182
|
+
# wasn't found), then we fall back to the normal means of searchign for a
|
183
|
+
# bridged network.
|
184
|
+
if !chosen_bridge
|
185
|
+
if bridgedifs.length == 1
|
186
|
+
# One bridgable interface? Just use it.
|
187
|
+
chosen_bridge = bridgedifs[0][:name]
|
188
|
+
@logger.debug("Only one bridged interface available. Using it by default.")
|
189
|
+
else
|
190
|
+
# More than one bridgable interface requires a user decision, so
|
191
|
+
# show options to choose from.
|
192
|
+
@env[:ui].info I18n.t(
|
193
|
+
"vagrant.actions.vm.bridged_networking.available",
|
194
|
+
prefix: false)
|
195
|
+
bridgedifs.each_index do |index|
|
196
|
+
interface = bridgedifs[index]
|
197
|
+
@env[:ui].info("#{index + 1}) #{interface[:name]}", prefix: false)
|
198
|
+
end
|
199
|
+
@env[:ui].info(I18n.t(
|
200
|
+
"vagrant.actions.vm.bridged_networking.choice_help")+"\n")
|
201
|
+
|
202
|
+
# The range of valid choices
|
203
|
+
valid = Range.new(1, bridgedifs.length)
|
204
|
+
|
205
|
+
# The choice that the user has chosen as the bridging interface
|
206
|
+
choice = nil
|
207
|
+
while !valid.include?(choice)
|
208
|
+
choice = @env[:ui].ask(
|
209
|
+
"Which interface should the network bridge to? ")
|
210
|
+
choice = choice.to_i
|
211
|
+
end
|
212
|
+
|
213
|
+
chosen_bridge = bridgedifs[choice - 1][:name]
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
@logger.info("Bridging adapter #{config[:adapter]} to #{chosen_bridge}")
|
218
|
+
|
219
|
+
# Given the choice we can now define the adapter we're using
|
220
|
+
return {
|
221
|
+
adapter: config[:adapter],
|
222
|
+
type: :bridged,
|
223
|
+
bridge: chosen_bridge,
|
224
|
+
mac_address: config[:mac],
|
225
|
+
nic_type: config[:nic_type]
|
226
|
+
}
|
227
|
+
end
|
228
|
+
|
229
|
+
def bridged_network_config(config)
|
230
|
+
if config[:ip]
|
231
|
+
options = {
|
232
|
+
auto_config: true,
|
233
|
+
mac: nil,
|
234
|
+
netmask: "255.255.255.0",
|
235
|
+
type: :static
|
236
|
+
}.merge(config)
|
237
|
+
options[:type] = options[:type].to_sym
|
238
|
+
return options
|
239
|
+
end
|
240
|
+
|
241
|
+
return {
|
242
|
+
type: :dhcp,
|
243
|
+
use_dhcp_assigned_default_route: config[:use_dhcp_assigned_default_route]
|
244
|
+
}
|
245
|
+
end
|
246
|
+
|
247
|
+
def hostonly_config(options)
|
248
|
+
options = {
|
249
|
+
auto_config: true,
|
250
|
+
mac: nil,
|
251
|
+
nic_type: nil,
|
252
|
+
type: :static,
|
253
|
+
}.merge(options)
|
254
|
+
|
255
|
+
# Make sure the type is a symbol
|
256
|
+
options[:type] = options[:type].to_sym
|
257
|
+
|
258
|
+
# Default IP is in the 20-bit private network block for DHCP based networks
|
259
|
+
options[:ip] = "172.28.128.1" if options[:type] == :dhcp && !options[:ip]
|
260
|
+
|
261
|
+
ip = IPAddr.new(options[:ip])
|
262
|
+
if ip.ipv4?
|
263
|
+
options[:netmask] ||= "255.255.255.0"
|
264
|
+
|
265
|
+
# Calculate our network address for the given IP/netmask
|
266
|
+
netaddr = network_address(options[:ip], options[:netmask])
|
267
|
+
|
268
|
+
# Verify that a host-only network subnet would not collide
|
269
|
+
# with a bridged networking interface.
|
270
|
+
#
|
271
|
+
# If the subnets overlap in any way then the host only network
|
272
|
+
# will not work because the routing tables will force the
|
273
|
+
# traffic onto the real interface rather than the VirtualBox
|
274
|
+
# interface.
|
275
|
+
@env[:machine].provider.driver.read_bridged_interfaces.each do |interface|
|
276
|
+
that_netaddr = network_address(interface[:ip], interface[:netmask])
|
277
|
+
raise Vagrant::Errors::NetworkCollision if \
|
278
|
+
netaddr == that_netaddr && interface[:status] != "Down"
|
279
|
+
end
|
280
|
+
|
281
|
+
# Split the IP address into its components
|
282
|
+
ip_parts = netaddr.split(".").map { |i| i.to_i }
|
283
|
+
|
284
|
+
# Calculate the adapter IP, which we assume is the IP ".1" at
|
285
|
+
# the end usually.
|
286
|
+
adapter_ip = ip_parts.dup
|
287
|
+
adapter_ip[3] += 1
|
288
|
+
options[:adapter_ip] ||= adapter_ip.join(".")
|
289
|
+
elsif ip.ipv6?
|
290
|
+
# Default subnet prefix length
|
291
|
+
options[:netmask] ||= 64
|
292
|
+
|
293
|
+
# Set adapter IP to <prefix>::1
|
294
|
+
options[:adapter_ip] ||= (ip.mask(options[:netmask].to_i) | 1).to_s
|
295
|
+
|
296
|
+
# Append a 6 to the end of the type
|
297
|
+
options[:type] = "#{options[:type]}6".to_sym
|
298
|
+
else
|
299
|
+
raise "BUG: Unknown IP type: #{ip.inspect}"
|
300
|
+
end
|
301
|
+
|
302
|
+
dhcp_options = {}
|
303
|
+
if options[:type] == :dhcp
|
304
|
+
# Calculate the DHCP server IP, which is the network address
|
305
|
+
# with the final octet + 2. So "172.28.0.0" turns into "172.28.0.2"
|
306
|
+
dhcp_ip = ip_parts.dup
|
307
|
+
dhcp_ip[3] += 2
|
308
|
+
dhcp_options[:dhcp_ip] = options[:dhcp_ip] || dhcp_ip.join(".")
|
309
|
+
|
310
|
+
# Calculate the lower and upper bound for the DHCP server
|
311
|
+
dhcp_lower = ip_parts.dup
|
312
|
+
dhcp_lower[3] += 3
|
313
|
+
dhcp_options[:dhcp_lower] = options[:dhcp_lower] || dhcp_lower.join(".")
|
314
|
+
|
315
|
+
dhcp_upper = ip_parts.dup
|
316
|
+
dhcp_upper[3] = 254
|
317
|
+
dhcp_options[:dhcp_upper] = options[:dhcp_upper] || dhcp_upper.join(".")
|
318
|
+
end
|
319
|
+
|
320
|
+
return {
|
321
|
+
adapter_ip: options[:adapter_ip],
|
322
|
+
auto_config: options[:auto_config],
|
323
|
+
ip: options[:ip],
|
324
|
+
mac: options[:mac],
|
325
|
+
name: options[:name],
|
326
|
+
netmask: options[:netmask],
|
327
|
+
nic_type: options[:nic_type],
|
328
|
+
type: options[:type]
|
329
|
+
}.merge(dhcp_options)
|
330
|
+
end
|
331
|
+
|
332
|
+
def hostonly_adapter(config)
|
333
|
+
@logger.info("Searching for matching hostonly network: #{config[:ip]}")
|
334
|
+
interface = hostonly_find_matching_network(config)
|
335
|
+
|
336
|
+
if !interface
|
337
|
+
@logger.info("Network not found. Creating if we can.")
|
338
|
+
|
339
|
+
# It is an error if a specific host only network name was specified
|
340
|
+
# but the network wasn't found.
|
341
|
+
if config[:name]
|
342
|
+
raise Vagrant::Errors::NetworkNotFound, name: config[:name]
|
343
|
+
end
|
344
|
+
|
345
|
+
# Create a new network
|
346
|
+
interface = hostonly_create_network(config)
|
347
|
+
@logger.info("Created network: #{interface[:name]}")
|
348
|
+
end
|
349
|
+
|
350
|
+
if config[:type] == :dhcp
|
351
|
+
create_dhcp_server_if_necessary(interface, config)
|
352
|
+
end
|
353
|
+
|
354
|
+
return {
|
355
|
+
adapter: config[:adapter],
|
356
|
+
hostonly: interface[:name],
|
357
|
+
mac_address: config[:mac],
|
358
|
+
nic_type: config[:nic_type],
|
359
|
+
type: :hostonly
|
360
|
+
}
|
361
|
+
end
|
362
|
+
|
363
|
+
def hostonly_network_config(config)
|
364
|
+
return {
|
365
|
+
type: config[:type],
|
366
|
+
adapter_ip: config[:adapter_ip],
|
367
|
+
ip: config[:ip],
|
368
|
+
netmask: config[:netmask]
|
369
|
+
}
|
370
|
+
end
|
371
|
+
|
372
|
+
def intnet_config(options)
|
373
|
+
return {
|
374
|
+
type: "static",
|
375
|
+
ip: nil,
|
376
|
+
netmask: "255.255.255.0",
|
377
|
+
adapter: nil,
|
378
|
+
mac: nil,
|
379
|
+
intnet: nil,
|
380
|
+
auto_config: true
|
381
|
+
}.merge(options || {})
|
382
|
+
end
|
383
|
+
|
384
|
+
def intnet_adapter(config)
|
385
|
+
intnet_name = config[:intnet]
|
386
|
+
intnet_name = "intnet" if intnet_name == true
|
387
|
+
|
388
|
+
return {
|
389
|
+
adapter: config[:adapter],
|
390
|
+
type: :intnet,
|
391
|
+
mac_address: config[:mac],
|
392
|
+
nic_type: config[:nic_type],
|
393
|
+
intnet: intnet_name,
|
394
|
+
}
|
395
|
+
end
|
396
|
+
|
397
|
+
def intnet_network_config(config)
|
398
|
+
return {
|
399
|
+
type: config[:type],
|
400
|
+
ip: config[:ip],
|
401
|
+
netmask: config[:netmask]
|
402
|
+
}
|
403
|
+
end
|
404
|
+
|
405
|
+
def nat_config(options)
|
406
|
+
return {
|
407
|
+
auto_config: false
|
408
|
+
}
|
409
|
+
end
|
410
|
+
|
411
|
+
def nat_adapter(config)
|
412
|
+
return {
|
413
|
+
adapter: config[:adapter],
|
414
|
+
type: :nat,
|
415
|
+
}
|
416
|
+
end
|
417
|
+
|
418
|
+
def nat_network_config(config)
|
419
|
+
return {}
|
420
|
+
end
|
421
|
+
|
422
|
+
#-----------------------------------------------------------------
|
423
|
+
# Misc. helpers
|
424
|
+
#-----------------------------------------------------------------
|
425
|
+
# Assigns the actual interface number of a network based on the
|
426
|
+
# enabled NICs on the virtual machine.
|
427
|
+
#
|
428
|
+
# This interface number is used by the guest to configure the
|
429
|
+
# NIC on the guest VM.
|
430
|
+
#
|
431
|
+
# The networks are modified in place by adding an ":interface"
|
432
|
+
# field to each.
|
433
|
+
def assign_interface_numbers(networks, adapters)
|
434
|
+
current = 0
|
435
|
+
adapter_to_interface = {}
|
436
|
+
|
437
|
+
# Make a first pass to assign interface numbers by adapter location
|
438
|
+
vm_adapters = @env[:machine].provider.driver.read_network_interfaces
|
439
|
+
vm_adapters.sort.each do |number, adapter|
|
440
|
+
if adapter[:type] != :none
|
441
|
+
# Not used, so assign the interface number and increment
|
442
|
+
adapter_to_interface[number] = current
|
443
|
+
current += 1
|
444
|
+
end
|
445
|
+
end
|
446
|
+
|
447
|
+
# Make a pass through the adapters to assign the :interface
|
448
|
+
# key to each network configuration.
|
449
|
+
adapters.each_index do |i|
|
450
|
+
adapter = adapters[i]
|
451
|
+
network = networks[i]
|
452
|
+
|
453
|
+
# Figure out the interface number by simple lookup
|
454
|
+
network[:interface] = adapter_to_interface[adapter[:adapter]]
|
455
|
+
end
|
456
|
+
end
|
457
|
+
|
458
|
+
#-----------------------------------------------------------------
|
459
|
+
# Hostonly Helper Functions
|
460
|
+
#-----------------------------------------------------------------
|
461
|
+
# This creates a host only network for the given configuration.
|
462
|
+
def hostonly_create_network(config)
|
463
|
+
@env[:machine].provider.driver.create_host_only_network(
|
464
|
+
adapter_ip: config[:adapter_ip],
|
465
|
+
netmask: config[:netmask]
|
466
|
+
)
|
467
|
+
end
|
468
|
+
|
469
|
+
# This finds a matching host only network for the given configuration.
|
470
|
+
def hostonly_find_matching_network(config)
|
471
|
+
this_netaddr = network_address(config[:ip], config[:netmask])
|
472
|
+
|
473
|
+
@env[:machine].provider.driver.read_host_only_interfaces.each do |interface|
|
474
|
+
return interface if config[:name] && config[:name] == interface[:name]
|
475
|
+
|
476
|
+
if interface[:ip] != ""
|
477
|
+
return interface if this_netaddr == \
|
478
|
+
network_address(interface[:ip], interface[:netmask])
|
479
|
+
end
|
480
|
+
|
481
|
+
if interface[:ipv6] != ""
|
482
|
+
return interface if this_netaddr == \
|
483
|
+
network_address(interface[:ipv6], interface[:ipv6_prefix])
|
484
|
+
end
|
485
|
+
end
|
486
|
+
|
487
|
+
nil
|
488
|
+
end
|
489
|
+
|
490
|
+
#-----------------------------------------------------------------
|
491
|
+
# DHCP Server Helper Functions
|
492
|
+
#-----------------------------------------------------------------
|
493
|
+
|
494
|
+
DEFAULT_DHCP_SERVER_FROM_VBOX_INSTALL = {
|
495
|
+
network_name: 'HostInterfaceNetworking-vboxnet0',
|
496
|
+
network: 'vboxnet0',
|
497
|
+
ip: '192.168.56.100',
|
498
|
+
netmask: '255.255.255.0',
|
499
|
+
lower: '192.168.56.101',
|
500
|
+
upper: '192.168.56.254'
|
501
|
+
}.freeze
|
502
|
+
|
503
|
+
#
|
504
|
+
# When a host-only network of type: :dhcp is configured,
|
505
|
+
# this handles the potential creation of a vbox dhcpserver to manage
|
506
|
+
# it.
|
507
|
+
#
|
508
|
+
# @param [Hash<String>] interface hash as returned from read_host_only_interfaces
|
509
|
+
# @param [Hash<String>] config hash as returned from hostonly_config
|
510
|
+
def create_dhcp_server_if_necessary(interface, config)
|
511
|
+
existing_dhcp_server = find_matching_dhcp_server(interface)
|
512
|
+
|
513
|
+
if existing_dhcp_server
|
514
|
+
if dhcp_server_matches_config?(existing_dhcp_server, config)
|
515
|
+
@logger.debug("DHCP server already properly configured")
|
516
|
+
return
|
517
|
+
elsif existing_dhcp_server == DEFAULT_DHCP_SERVER_FROM_VBOX_INSTALL
|
518
|
+
@env[:ui].info I18n.t("vagrant.actions.vm.network.cleanup_vbox_default_dhcp")
|
519
|
+
@env[:machine].provider.driver.remove_dhcp_server(existing_dhcp_server[:network_name])
|
520
|
+
else
|
521
|
+
# We have an invalid DHCP server that we're not able to
|
522
|
+
# automatically clean up, so we need to give up and tell the user
|
523
|
+
# to sort out their own vbox dhcpservers and hostonlyifs
|
524
|
+
raise Vagrant::Errors::NetworkDHCPAlreadyAttached
|
525
|
+
end
|
526
|
+
end
|
527
|
+
|
528
|
+
@logger.debug("Creating a DHCP server...")
|
529
|
+
@env[:machine].provider.driver.create_dhcp_server(interface[:name], config)
|
530
|
+
end
|
531
|
+
|
532
|
+
# Detect when an existing DHCP server matches precisely the
|
533
|
+
# requested config for a hostonly interface.
|
534
|
+
#
|
535
|
+
# @param [Hash<String>] dhcp_server as found by read_dhcp_servers
|
536
|
+
# @param [Hash<String>] config as returned from hostonly_config
|
537
|
+
# @return [Boolean]
|
538
|
+
def dhcp_server_matches_config?(dhcp_server, config)
|
539
|
+
dhcp_server[:ip] == config[:dhcp_ip] &&
|
540
|
+
dhcp_server[:lower] == config[:dhcp_lower] &&
|
541
|
+
dhcp_server[:upper] == config[:dhcp_upper]
|
542
|
+
end
|
543
|
+
|
544
|
+
# Returns the existing dhcp server, if any, that is attached to the
|
545
|
+
# specified interface.
|
546
|
+
#
|
547
|
+
# @return [Hash<String>] dhcp_server or nil if not found
|
548
|
+
def find_matching_dhcp_server(interface)
|
549
|
+
@env[:machine].provider.driver.read_dhcp_servers.detect do |dhcp_server|
|
550
|
+
interface[:name] && interface[:name] == dhcp_server[:network]
|
551
|
+
end
|
552
|
+
end
|
553
|
+
end
|
554
|
+
end
|
555
|
+
end
|
556
|
+
end
|