vagrant-share 0.0.1 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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