vagrant-share 0.0.1 → 2.0.0

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.
@@ -0,0 +1,153 @@
1
+ require "log4r"
2
+
3
+ require "vagrant/util/subprocess"
4
+
5
+ module VagrantPlugins
6
+ module Share
7
+ module Command
8
+ class Share < Vagrant.plugin("2", "command")
9
+
10
+ include Ngrok::Share
11
+
12
+ def self.synopsis
13
+ "share your Vagrant environment with anyone in the world"
14
+ end
15
+
16
+ attr_reader :options
17
+
18
+ def execute
19
+ @logger = Log4r::Logger.new("vagrant::share::command::share")
20
+ @options = {}
21
+
22
+ options[:use_key_once] = false
23
+ options[:disable_http] = false
24
+
25
+ opts = OptionParser.new do |o|
26
+ o.banner = "Usage: vagrant share"
27
+ o.separator ""
28
+ o.separator "Allows anyone in the world with an internet connection to access"
29
+ o.separator "your Vagrant environment by giving you a globally accessible"
30
+ o.separator "URL. "
31
+ o.separator ""
32
+ o.separator "If the person wanting to connect to your environment also has"
33
+ o.separator "Vagrant installed, they can use `vagrant connect` to connect to"
34
+ o.separator "open any TCP stream to your Vagrant machine."
35
+ o.separator ""
36
+ o.separator "Vagrant will attempt to auto-discover your HTTP port and enable"
37
+ o.separator "that. If you want to disable HTTP, specify the --disable-http flag"
38
+ o.separator "directly. If you want HTTPS, specify the --https flag directly."
39
+ o.separator ""
40
+ o.separator "If the --ssh flag is specified, others can easily SSH into your"
41
+ o.separator "Vagrant environment by using `vagrant connect --ssh`. We generate"
42
+ o.separator "a new SSH key for this that you can encrypt with a password."
43
+ o.separator "When --ssh is specified, all other SSH flags are optional."
44
+ o.separator ""
45
+
46
+ o.on("--disable-http", "Disable publicly visible HTTP(S) endpoint") do |d|
47
+ options[:disable_http] = d
48
+ end
49
+
50
+ o.on("--disable-https", "Disable publicly visible HTTPS endpoint only") do |d|
51
+ options[:disable_https] = d
52
+ end
53
+
54
+ o.on("--domain VALUE", String, "Domain the share name will be a subdomain of") do |n|
55
+ options[:domain] = n
56
+ end
57
+
58
+ o.on("--http VALUE", String, "Local HTTP port to forward to") do |p|
59
+ options[:http_port] = p
60
+ end
61
+
62
+ o.on("--https VALUE", String, "Local HTTPS port to forward to") do |p|
63
+ options[:https_port] = p
64
+ end
65
+
66
+ o.on("--name VALUE", String, "Specific name for the share") do |n|
67
+ options[:name] = n
68
+ end
69
+
70
+ o.on("--ssh", "Allow 'vagrant connect --ssh' access") do |ssh|
71
+ options[:ssh] = ssh
72
+ end
73
+
74
+ o.on("--ssh-no-password", "Key won't be encrypted with --ssh") do |p|
75
+ options[:ssh_no_password] = p
76
+ options[:ssh_flag] = true
77
+ end
78
+
79
+ o.on("--ssh-port PORT", Integer, "Specific port for SSH when using --ssh") do |p|
80
+ options[:ssh_port] = p
81
+ options[:ssh_flag] = true
82
+ end
83
+
84
+ o.on("--ssh-once", "Allow 'vagrant connect --ssh' only one time") do |r|
85
+ options[:use_key_once] = true
86
+ options[:ssh_flag] = true
87
+ end
88
+
89
+ o.on("--driver DRIVER", "Deprecated option for compatibility") do |d|
90
+ options[:driver] = d
91
+ end
92
+
93
+ o.on("--full", "Share entire machine") do |full|
94
+ options[:full_share] = true
95
+ end
96
+
97
+ o.on("--share-password", "Custom share password") do |p|
98
+ options[:share_password] = p
99
+ end
100
+ end
101
+
102
+ # Parse the options
103
+ argv = parse_options(opts)
104
+ return if !argv
105
+ if argv.length > 1
106
+ raise Vagrant::Errors::CLIInvalidUsage, help: opts.help.chomp
107
+ end
108
+
109
+ # If an SSH option was specified without the --ssh flag, let
110
+ # the user know.
111
+ if !options[:ssh] && options[:ssh_flag]
112
+ @env.ui.error(I18n.t("vagrant_share.ssh_flag_missing") + "\n ")
113
+ raise Vagrant::Errors::CLIInvalidUsage, help: opts.help.chomp
114
+ end
115
+
116
+ # If we're not using HTTP, get rid of the ports
117
+ if options[:disable_http]
118
+ options[:http_port] = nil
119
+ options[:https_port] = nil
120
+ end
121
+
122
+ start_share(argv, options)
123
+ end
124
+
125
+ protected
126
+
127
+ def detect_ports!(options, target, machine)
128
+ detected = nil
129
+ if target == "127.0.0.1"
130
+ # Use forwarded ports to detect because we're NATting
131
+ detected = Helper.detect_forwarded_ports(machine) || []
132
+ if !detected[0]
133
+ raise Errors::DetectHTTPForwardedPortFailed
134
+ end
135
+ else
136
+ # Try forwarded ports first because its not such a
137
+ # shot in the dark.
138
+ detected = Helper.detect_hybrid(machine, target)
139
+ if !detected[0]
140
+ raise Errors::DetectHTTPCommonPortFailed,
141
+ target: target
142
+ end
143
+ end
144
+
145
+ options[:http_port] = detected[0]
146
+ if !options[:https_port] && detected[1]
147
+ options[:https_port] = detected[1]
148
+ end
149
+ end
150
+ end
151
+ end
152
+ end
153
+ end
@@ -0,0 +1,96 @@
1
+ require "vagrant"
2
+
3
+ module VagrantPlugins
4
+ module Share
5
+ module Errors
6
+ # A convenient superclass for all our errors.
7
+ class ShareError < Vagrant::Errors::VagrantError
8
+ error_namespace("vagrant_share.errors")
9
+ end
10
+
11
+ class APIError < ShareError
12
+ error_key(:api_error)
13
+ end
14
+
15
+ class AuthExpired < ShareError
16
+ error_key(:auth_expired)
17
+ end
18
+
19
+ class AuthRequired < ShareError
20
+ error_key(:auth_required)
21
+ end
22
+
23
+ class ConnectNameIsURL < ShareError
24
+ error_key(:connect_name_is_url)
25
+ end
26
+
27
+ class DetectHTTPCommonPortFailed < ShareError
28
+ error_key(:detect_http_common_port_failed)
29
+ end
30
+
31
+ class DetectHTTPForwardedPortFailed < ShareError
32
+ error_key(:detect_http_forwarded_port_failed)
33
+ end
34
+
35
+ class IPCouldNotAutoAcquire < ShareError
36
+ error_key(:ip_could_not_auto_acquire)
37
+ end
38
+
39
+ class IPInUse < ShareError
40
+ error_key(:ip_in_use)
41
+ end
42
+
43
+ class IPInvalid < ShareError
44
+ error_key(:ip_invalid)
45
+ end
46
+
47
+ class PortCouldNotAcquire < ShareError
48
+ error_key(:port_could_not_acquire)
49
+ end
50
+
51
+ class MachineNotReady < ShareError
52
+ error_key(:machine_not_ready)
53
+ end
54
+
55
+ class NgrokUnavailable < ShareError
56
+ error_key(:ngrok_unavailable)
57
+ end
58
+
59
+ class ProxyExit < ShareError
60
+ error_key(:proxy_exit)
61
+ end
62
+
63
+ class ProxyMachineBadProvider < ShareError
64
+ error_key(:proxy_machine_bad_provider)
65
+ end
66
+
67
+ class ServerNotSet < ShareError
68
+ error_key(:server_not_set)
69
+ end
70
+
71
+ class ShareNotFound < ShareError
72
+ error_key(:share_not_found)
73
+ end
74
+
75
+ class SSHCantInsertKey < ShareError
76
+ error_key(:ssh_cant_insert_key)
77
+ end
78
+
79
+ class SSHNotReady < ShareError
80
+ error_key(:ssh_not_ready)
81
+ end
82
+
83
+ class SSHNotShared < ShareError
84
+ error_key(:ssh_not_shared)
85
+ end
86
+
87
+ class SSHPortNotDetected < ShareError
88
+ error_key(:ssh_port_not_detected)
89
+ end
90
+
91
+ class SSHHostPortNotDetected < ShareError
92
+ error_key(:ssh_host_port_not_detected)
93
+ end
94
+ end
95
+ end
96
+ end
@@ -0,0 +1,488 @@
1
+ require "base64"
2
+ require "ipaddr"
3
+ require "openssl"
4
+ require "pathname"
5
+ require "timeout"
6
+ require "thread"
7
+ require "tmpdir"
8
+ require "securerandom"
9
+ require "log4r"
10
+ require "rest_client"
11
+
12
+ require "vagrant/util/retryable"
13
+ require "vagrant/util/subprocess"
14
+ require "vagrant/vagrantfile"
15
+
16
+ module VagrantPlugins
17
+ module Share
18
+ # Contains helper methods that the command uses.
19
+ class Helper
20
+ autoload :Api, "vagrant-share/helper/api"
21
+ autoload :WordList, "vagrant-share/helper/word_list"
22
+
23
+ extend Vagrant::Util::Retryable
24
+
25
+ # List of ephemeral ports
26
+ SHARE_PORT_RANGE = (49152..65535).freeze
27
+
28
+ # Acquires the given IP for the static IP for the machine. This
29
+ # also cleverly uses file locks to try to make sure that IPs
30
+ # aren't reused if multiple `connect` calls are called.
31
+ #
32
+ # @param [Vagrant::Environment] env
33
+ # @param [String] requested A specific requested IP, or nil if
34
+ # it doesn't matter.
35
+ # @return [Array<String, File>] The first element is the IP, and
36
+ # the second is a File that holds the file lock. Make sure to
37
+ # close this when you're done. Nil is returned if the requested
38
+ # IP can't be acquired.
39
+ def self.acquire_ip(env, requested)
40
+ if requested
41
+ path = env.tmp_path.join("vagrant_connect_#{requested}")
42
+ f = path.open("w+")
43
+ if f.flock(File::LOCK_EX | File::LOCK_NB) === false
44
+ # Someone already has this IP.
45
+ f.close
46
+ return nil
47
+ end
48
+
49
+ return requested.to_s, f
50
+ end
51
+
52
+ # We just skip ".1" and ".2" because they cause problems often.
53
+ range = IPAddr.new("172.16.0.0/12").succ.succ
54
+ while true
55
+ results = acquire_ip(env, range.to_s)
56
+ return results if results
57
+ range = range.succ
58
+ end
59
+ end
60
+
61
+ # Acquires the given port if free.
62
+ #
63
+ # @param [Vagrant::Environment] env
64
+ # @param [Integer] requested
65
+ # @return [Array<Integer, File>]
66
+ def self.acquire_port(env, requested=nil)
67
+ if requested
68
+ path = env.tmp_path.join("vagrant_share_#{requested}")
69
+ handle = path.open("w+")
70
+ if !handle.flock(File::LOCK_EX | File::LOCK_NB)
71
+ handle.close
72
+ nil
73
+ else
74
+ begin
75
+ Socket.tcp('127.0.0.1', requested, connect_timeout: 1)
76
+ nil
77
+ rescue Errno::ECONNREFUSED
78
+ [requested, handle]
79
+ end
80
+ end
81
+ else
82
+ port_list = SHARE_PORT_RANGE.to_a
83
+ port = acquire_port(env, port_list.pop) until port || port_list.empty?
84
+ if port.nil?
85
+ raise Errors::PortCouldNotAcquire.new
86
+ else
87
+ port
88
+ end
89
+ end
90
+ end
91
+
92
+ # Detects the HTTP/HTTPs ports of the machine automatically by
93
+ # trying a bunch of commonly used ports.
94
+ #
95
+ # @param [String] target IP or FQDN
96
+ # @return [Array] Same as {#detect_forwarded_ports}
97
+ def self.detect_ports(target)
98
+ common = [80, 3000, 4567, 8000, 8080]
99
+
100
+ logger = Log4r::Logger.new("vagrant::share::helper")
101
+ queue = Queue.new
102
+ workers = []
103
+ common.each do |port|
104
+ workers << Thread.new(port) do |p|
105
+ Thread.current.abort_on_exception = true
106
+
107
+ url = "http://#{target}:#{p}/"
108
+ logger.debug("Trying: #{url}")
109
+ queue << p if http_url?(url)
110
+ end
111
+ end
112
+
113
+ # Make a thread that puts a tombstone if all the workers are dead
114
+ workers << Thread.new(workers.dup) do |waiters|
115
+ Thread.current.abort_on_exception = true
116
+
117
+ begin
118
+ waiters.map(&:join)
119
+ ensure
120
+ queue << nil
121
+ end
122
+ end
123
+
124
+ [queue.pop, nil]
125
+ ensure
126
+ workers.map(&:kill)
127
+ end
128
+
129
+ # Detects the HTTP/HTTPs ports of the machine automatically using
130
+ # forwarded ports.
131
+ #
132
+ # @param [Vagrant::Machine]
133
+ # @return [Array] Results where first element is HTTP and second
134
+ # is HTTPs port. Nil elements if not detected.
135
+ def self.detect_forwarded_ports(machine, **opts)
136
+ logger = Log4r::Logger.new("vagrant::share::helper")
137
+ queue = Queue.new
138
+ https_queue = Queue.new
139
+ found_https = false
140
+ workers = []
141
+
142
+ machine.config.vm.networks.each do |type, netopts|
143
+ next if type != :forwarded_port
144
+ next if !netopts[:host]
145
+
146
+ target = opts[:target] || "127.0.0.1"
147
+ port = opts[:guest_port] ? netopts[:guest] : netopts[:host]
148
+
149
+ # Try the forwarded port
150
+ workers << Thread.new(target, port) do |t, p|
151
+ Thread.current.abort_on_exception = true
152
+
153
+ url = "http://#{t}:#{p}/"
154
+ logger.debug("Trying: #{url}")
155
+ if http_url?(url)
156
+ logger.info("HTTP url found: #{url}")
157
+ queue << port
158
+ else
159
+ logger.debug("Not an HTTP URL: #{url}")
160
+ end
161
+ end
162
+
163
+ # If it is an SSL port, attempt an SSL connection...
164
+ if netopts[:guest].to_i == 443 && !found_https
165
+ found_https = true
166
+
167
+ workers << Thread.new(target, port) do |t, p|
168
+ Thread.current.abort_on_exception = true
169
+
170
+ url = "https://#{t}:#{p}/"
171
+ logger.debug("Trying HTTPS: #{url}")
172
+ if http_url?(url, secure: true)
173
+ https_queue << port
174
+ else
175
+ https_queue << nil
176
+ end
177
+ end
178
+ end
179
+ end
180
+
181
+ # Make a thread that puts a tombstone if all the workers are dead
182
+ workers << Thread.new(workers.dup) do |waiters|
183
+ Thread.current.abort_on_exception = true
184
+
185
+ begin
186
+ waiters.map(&:join)
187
+ ensure
188
+ queue << nil
189
+ end
190
+ end
191
+
192
+ if !found_https
193
+ Thread.new do
194
+ # We never had an https candidate, so just put a nil on it
195
+ https_queue << nil
196
+ end
197
+ end
198
+
199
+ [queue.pop, https_queue.pop]
200
+ ensure
201
+ workers.map(&:kill)
202
+ end
203
+
204
+ # Get information from vagrant internal share API
205
+ #
206
+ # @param [String] path
207
+ # @param [String] ip
208
+ # @param [Integer] port
209
+ # @return [Hash]
210
+ def self.share_info(path, ip, port)
211
+ uri = URI.parse("https://#{ip}:#{port}/#{path}")
212
+ conn = Net::HTTP.new(uri.host, uri.port)
213
+ conn.use_ssl = true
214
+ conn.verify_mode = OpenSSL::SSL::VERIFY_NONE
215
+ response = conn.get(uri.path)
216
+ JSON.parse(response.body.to_s)
217
+ end
218
+
219
+ # Ping share to validate connection
220
+ #
221
+ # @param [String] ip
222
+ # @param [Integer] port
223
+ # @return [TrueClass, FalseClass] connection is valid
224
+ def self.ping_share(ip, port, **opts)
225
+ uri = URI.parse("https://#{ip}:#{port}/#{opts.fetch(:path, "ping")}")
226
+ begin
227
+ conn = Net::HTTP.new(uri.host, uri.port)
228
+ conn.use_ssl = true
229
+ conn.verify_mode = OpenSSL::SSL::VERIFY_NONE
230
+ response = conn.get(uri.path)
231
+ response.code.to_s == "200"
232
+ rescue
233
+ false
234
+ end
235
+ end
236
+
237
+ # Convert number into words
238
+ #
239
+ # @param [Integer] int
240
+ # @return [Array<String>]
241
+ def self.wordify(int)
242
+ WordList.encode(int)
243
+ end
244
+
245
+ # Convert words into number
246
+ #
247
+ # @param [Array<String>] words
248
+ # @return [Integer]
249
+ def self.dewordify(words)
250
+ WordList.decode(words)
251
+ end
252
+
253
+ # Trap given signal and execute given block. Reapply replaced
254
+ # signal trap block when complete.
255
+ #
256
+ # @param [String] type
257
+ # @return [Proc]
258
+ def self.signal_retrap(type)
259
+ initial_trap = Signal.trap(type) do
260
+ yield
261
+ Signal.trap(type, initial_trap)
262
+ end
263
+ end
264
+
265
+ # Detects the HTTP/HTTPS ports using a hybrid approach by
266
+ # trying both the forwarded port and common port methods.
267
+ #
268
+ # @return [Array]
269
+ def self.detect_hybrid(machine, target)
270
+ http_queue = Queue.new
271
+ https_queue = Queue.new
272
+
273
+ workers = []
274
+ workers << Thread.new do
275
+ Thread.current.abort_on_exception = true
276
+
277
+ results = detect_forwarded_ports(
278
+ machine, target: target, guest_port: true)
279
+ http_queue << results[0] if results && results[0]
280
+ https_queue << results[1] if results && results[1]
281
+ end
282
+
283
+ workers << Thread.new do
284
+ Thread.current.abort_on_exception = true
285
+
286
+ results = detect_ports(target)
287
+ http_queue << results[0] if results && results[0]
288
+ https_queue << results[1] if results && results[1]
289
+ end
290
+
291
+ workers << Thread.new(workers.dup) do |waiters|
292
+ Thread.current.abort_on_exception = true
293
+
294
+ begin
295
+ waiters.map(&:join)
296
+ ensure
297
+ http_queue << nil
298
+ https_queue << nil
299
+ end
300
+ end
301
+
302
+ [http_queue.pop, https_queue.pop]
303
+ ensure
304
+ workers.map(&:kill)
305
+ end
306
+
307
+ # Returns the forwarded ports (on the host) for the machine.
308
+ #
309
+ # @return [Hash<Integer, Integer>] Mapping of forwarded ports. The
310
+ # key is the host port and the value is the guest port.
311
+ def self.forwarded_ports(machine)
312
+ if machine.provider.capability?(:forwarded_ports)
313
+ # This is a much more correct way, if it is available
314
+ return machine.provider.capability(:forwarded_ports)
315
+ end
316
+
317
+ # This is so we can implement it for other providers while still
318
+ # allowing them to implement it eventually. For example, we can
319
+ # support people running older VMware plugins.
320
+ if machine.provider.capability?(:vagrant_share__forwarded_ports)
321
+ return machine.provider.capability(:vagrant_share__forwarded_ports)
322
+ end
323
+
324
+ {}.tap do |result|
325
+ machine.config.vm.networks.each do |type, netopts|
326
+ next if type != :forwarded_port
327
+ next if !netopts[:host]
328
+ result[netopts[:host]] = netopts[:guest]
329
+ end
330
+ end
331
+ end
332
+
333
+ # Looks up the guest port of a forwarded port.
334
+ #
335
+ # @param [Integer] port Port on the host.
336
+ # @return [Integer]
337
+ def self.guest_forwarded_port(machine, port)
338
+ forwarded_ports(machine)[port]
339
+ end
340
+
341
+ # Looks up the host port of a forwarded port.
342
+ #
343
+ # @param [Integer] port Port on the guest.
344
+ # @return [Integer]
345
+ def self.host_forwarded_port(machine, port)
346
+ forwarded_ports(machine).invert[port]
347
+ end
348
+
349
+ # Creates an SSH keypair and returns it.
350
+ #
351
+ # @param [String] password Password for the key, or nil for no password.
352
+ # @return [Array<String, String, String>] PEM-encoded public and private key,
353
+ # respectively. The final element is the OpenSSH encoded public
354
+ # key.
355
+ def self.generate_keypair(password)
356
+ rsa_key = OpenSSL::PKey::RSA.new(2048)
357
+ public_key = rsa_key.public_key
358
+ private_key = rsa_key.to_pem
359
+
360
+ if password
361
+ cipher = OpenSSL::Cipher.new('des3')
362
+ private_key = rsa_key.to_pem(cipher, password)
363
+ end
364
+
365
+ # Generate the binary necessary for the OpenSSH public key.
366
+ binary = [7].pack("N")
367
+ binary += "ssh-rsa"
368
+ ["e", "n"].each do |m|
369
+ val = public_key.send(m)
370
+ data = val.to_s(2)
371
+
372
+ first_byte = data[0,1].unpack("c").first
373
+ if val < 0
374
+ data[0] = [0x80 & first_byte].pack("c")
375
+ elsif first_byte < 0
376
+ data = 0.chr + data
377
+ end
378
+
379
+ binary += [data.length].pack("N") + data
380
+ end
381
+
382
+ openssh_key = "ssh-rsa #{Base64.encode64(binary).gsub("\n", "")} vagrant-share"
383
+ public_key = public_key.to_pem
384
+ return [public_key, private_key, openssh_key]
385
+ end
386
+
387
+ # Tests if the URL given is a valid URL for HTTP access.
388
+ #
389
+ # @return [Boolean]
390
+ def self.http_url?(url, **opts)
391
+ exceptions = [
392
+ Errno::EACCES,
393
+ Errno::ECONNREFUSED,
394
+ Net::HTTPBadResponse,
395
+ ]
396
+
397
+ begin
398
+ args = {
399
+ method: :get,
400
+ url: url,
401
+ }
402
+
403
+ if opts[:secure]
404
+ args[:verify_ssl] = OpenSSL::SSL::VERIFY_NONE
405
+ end
406
+
407
+ retryable(on: exceptions, tries: 2) do
408
+ Timeout.timeout(2) do
409
+ RestClient::Request.execute(args)
410
+ end
411
+ end
412
+ return true
413
+ rescue Errno::EACCES
414
+ rescue Errno::ECONNREFUSED
415
+ rescue Errno::ECONNRESET
416
+ rescue Net::HTTPBadResponse
417
+ rescue RestClient::RequestTimeout
418
+ rescue RestClient::ServerBrokeConnection
419
+ rescue Timeout::Error
420
+ # All the above are bad and should return false.
421
+ # Below this are good exceptions.
422
+ rescue RestClient::ExceptionWithResponse
423
+ # This will catch any HTTP status code errors, which means
424
+ # there is an HTTP sever on the other end, so we should accept that.
425
+ return true
426
+ end
427
+
428
+ false
429
+ end
430
+
431
+ # Returns a {Vagrant::Machine} that is properly configured
432
+ # and can be started/stopped for connections.
433
+ #
434
+ # @return [Vagrant::Machine]
435
+ # @note This is used for Ngrok implementation
436
+ def self.share_machine(env, **opts)
437
+ provider = env.default_provider.to_sym
438
+ if ![:dummy, :virtualbox, :vmware_fusion, :vmware_workstation, :vmware_desktop].include?(provider)
439
+ raise Errors::ProxyMachineBadProvider, provider: provider.to_s
440
+ end
441
+
442
+ machine_name = opts.fetch(:name, "connect").to_sym
443
+
444
+ # Our "Vagrantfile" for the proxy machine
445
+ config = lambda do |c|
446
+ c.vm.box = "hashicorp/vagrant-share"
447
+ c.vm.box_version = ">= #{VERSION.segments[0,1].join(".")}, < #{VERSION.bump.version}"
448
+ c.vm.box_check_update = false
449
+
450
+ # Configure a DHCP network so that we can get an IP
451
+ if opts[:ip]
452
+ c.vm.network "private_network", ip: opts[:ip]
453
+ end
454
+
455
+ if opts[:port]
456
+ c.vm.network "forwarded_port", guest: opts[:port][:guest], host: opts[:port][:host]
457
+ end
458
+
459
+ c.vm.provider "virtualbox" do |v|
460
+ v.memory = opts[:memory] || 128
461
+ v.auto_nat_dns_proxy = false
462
+ v.check_guest_additions = false
463
+ v.name = "#{machine_name}-#{SecureRandom.uuid}"
464
+ end
465
+
466
+ # NOTE: Default the vmware instances to 256MB for memory. We
467
+ # can get away with much less on virtualbox but will get panics
468
+ # when using less on vmware
469
+ ["vmware_fusion", "vmware_workstation", "vmware_desktop"].each do |vmware|
470
+ c.vm.provider vmware do |v|
471
+ v.vmx["memsize"] = opts[:memory] || 256
472
+ v.whitelist_verified = true
473
+ end
474
+ end
475
+
476
+ # Make our only VM the connect-proxy
477
+ c.vm.define machine_name.to_s
478
+ end
479
+ env.config_loader.set(machine_name, [["2", config]])
480
+
481
+ data_path = Pathname.new(Dir.mktmpdir)
482
+ vagrantfile = Vagrant::Vagrantfile.new(env.config_loader, [machine_name])
483
+ vagrantfile.machine(
484
+ machine_name, provider, env.boxes, data_path, env)
485
+ end
486
+ end
487
+ end
488
+ end