vagrant-parallels 1.0.5 → 1.0.6.rc1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/vagrant-parallels/action.rb +0 -2
- data/lib/vagrant-parallels/driver/pd_9.rb +3 -401
- data/lib/vagrant-parallels/guest_cap/linux/mount_parallels_shared_folder.rb +20 -59
- data/lib/vagrant-parallels/version.rb +1 -1
- metadata +2 -3
- data/lib/vagrant-parallels/action/force_prl_fs_mount.rb +0 -55
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c81c8a8004ab4f04103fe026fe8336bceb20087d
|
4
|
+
data.tar.gz: 7c35af159575f21dc35bea6d6b975ebb7e3449c8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 761ef849dd461d789b1826e347c4e42278123995083a5bea95b88f05cf7a11ec1c62b5ee3cce359ee193769bbed5cf4f01e86bd7448d43dfc9a117425d0c7eac
|
7
|
+
data.tar.gz: 658d8e9a2b6eebff58b9b343ebfedf33df44bbf6644ace802068c89668122826077e691b5bf6df811be0aabed5dc9fdbb294bdf37086972d5e5b1f6af9f170cf
|
@@ -168,7 +168,6 @@ module VagrantPlugins
|
|
168
168
|
b2.use EnvSet, :port_collision_repair => false
|
169
169
|
b2.use Resume
|
170
170
|
b2.use WaitForCommunicator, [:resuming, :running]
|
171
|
-
b2.use ForcePrlFsMount
|
172
171
|
else
|
173
172
|
b2.use MessageNotCreated
|
174
173
|
end
|
@@ -284,7 +283,6 @@ module VagrantPlugins
|
|
284
283
|
autoload :DestroyUnusedNetworkInterfaces, File.expand_path("../action/destroy_unused_network_interfaces", __FILE__)
|
285
284
|
autoload :Export, File.expand_path("../action/export", __FILE__)
|
286
285
|
autoload :ForcedHalt, File.expand_path("../action/forced_halt", __FILE__)
|
287
|
-
autoload :ForcePrlFsMount, File.expand_path("../action/force_prl_fs_mount", __FILE__)
|
288
286
|
autoload :Import, File.expand_path("../action/import", __FILE__)
|
289
287
|
autoload :IsSuspended, File.expand_path("../action/is_suspended", __FILE__)
|
290
288
|
autoload :IsRunning, File.expand_path("../action/is_running", __FILE__)
|
@@ -2,307 +2,17 @@ require 'log4r'
|
|
2
2
|
|
3
3
|
require 'vagrant/util/platform'
|
4
4
|
|
5
|
-
require File.expand_path("../
|
5
|
+
require File.expand_path("../pd_8", __FILE__)
|
6
6
|
|
7
7
|
module VagrantPlugins
|
8
8
|
module Parallels
|
9
9
|
module Driver
|
10
10
|
# Driver for Parallels Desktop 9.
|
11
|
-
class PD_9 <
|
11
|
+
class PD_9 < PD_8
|
12
12
|
def initialize(uuid)
|
13
|
-
super()
|
13
|
+
super(uuid)
|
14
14
|
|
15
15
|
@logger = Log4r::Logger.new("vagrant::provider::parallels::pd_9")
|
16
|
-
@uuid = uuid
|
17
|
-
end
|
18
|
-
|
19
|
-
|
20
|
-
def compact(uuid)
|
21
|
-
used_drives = read_settings.fetch('Hardware', {}).select { |name, _| name.start_with? 'hdd' }
|
22
|
-
used_drives.each_value do |drive_params|
|
23
|
-
execute(:prl_disk_tool, 'compact', '--hdd', drive_params["image"]) do |type, data|
|
24
|
-
lines = data.split("\r")
|
25
|
-
# The progress of the compact will be in the last line. Do a greedy
|
26
|
-
# regular expression to find what we're looking for.
|
27
|
-
if lines.last =~ /.+?(\d{,3}) ?%/
|
28
|
-
yield $1.to_i if block_given?
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
def clear_shared_folders
|
35
|
-
share_ids = read_shared_folders.keys
|
36
|
-
share_ids.each do |id|
|
37
|
-
execute("set", @uuid, "--shf-host-del", id)
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
def create_host_only_network(options)
|
42
|
-
# Create the interface
|
43
|
-
execute(:prlsrvctl, "net", "add", options[:network_id], "--type", "host-only")
|
44
|
-
|
45
|
-
# Configure it
|
46
|
-
args = ["--ip", "#{options[:adapter_ip]}/#{options[:netmask]}"]
|
47
|
-
if options[:dhcp]
|
48
|
-
args.concat(["--dhcp-ip", options[:dhcp][:ip],
|
49
|
-
"--ip-scope-start", options[:dhcp][:lower],
|
50
|
-
"--ip-scope-end", options[:dhcp][:upper]])
|
51
|
-
end
|
52
|
-
|
53
|
-
execute(:prlsrvctl, "net", "set", options[:network_id], *args)
|
54
|
-
|
55
|
-
# Determine interface to which it has been bound
|
56
|
-
net_info = json { execute(:prlsrvctl, 'net', 'info', options[:network_id], '--json', retryable: true) }
|
57
|
-
iface_name = net_info['Bound To']
|
58
|
-
|
59
|
-
# Return the details
|
60
|
-
return {
|
61
|
-
:name => iface_name,
|
62
|
-
:ip => options[:adapter_ip],
|
63
|
-
:netmask => options[:netmask],
|
64
|
-
:dhcp => options[:dhcp]
|
65
|
-
}
|
66
|
-
end
|
67
|
-
|
68
|
-
def delete
|
69
|
-
execute('delete', @uuid)
|
70
|
-
end
|
71
|
-
|
72
|
-
def delete_disabled_adapters
|
73
|
-
read_settings.fetch('Hardware', {}).each do |adapter, params|
|
74
|
-
if adapter.start_with?('net') and !params.fetch("enabled", true)
|
75
|
-
execute('set', @uuid, '--device-del', adapter)
|
76
|
-
end
|
77
|
-
end
|
78
|
-
end
|
79
|
-
|
80
|
-
def delete_unused_host_only_networks
|
81
|
-
networks = read_virtual_networks
|
82
|
-
|
83
|
-
# 'Shared'(vnic0) and 'Host-Only'(vnic1) are default in Parallels Desktop
|
84
|
-
# They should not be deleted anyway.
|
85
|
-
networks.keep_if do |net|
|
86
|
-
net['Type'] == "host-only" &&
|
87
|
-
net['Bound To'].match(/^(?>vnic|Parallels Host-Only #)(\d+)$/)[1].to_i >= 2
|
88
|
-
end
|
89
|
-
|
90
|
-
read_vms_info.each do |vm|
|
91
|
-
used_nets = vm.fetch('Hardware', {}).select { |name, _| name.start_with? 'net' }
|
92
|
-
used_nets.each_value do |net_params|
|
93
|
-
networks.delete_if { |net| net['Bound To'] == net_params.fetch('iface', nil) }
|
94
|
-
end
|
95
|
-
|
96
|
-
end
|
97
|
-
|
98
|
-
networks.each do |net|
|
99
|
-
# Delete the actual host only network interface.
|
100
|
-
execute(:prlsrvctl, "net", "del", net["Network ID"])
|
101
|
-
end
|
102
|
-
end
|
103
|
-
|
104
|
-
def enable_adapters(adapters)
|
105
|
-
# Get adapters which have already configured for this VM
|
106
|
-
# Such adapters will be just overridden
|
107
|
-
existing_adapters = read_settings.fetch('Hardware', {}).keys.select { |name| name.start_with? 'net' }
|
108
|
-
|
109
|
-
# Disable all previously existing adapters (except shared 'vnet0')
|
110
|
-
existing_adapters.each do |adapter|
|
111
|
-
if adapter != 'vnet0'
|
112
|
-
execute('set', @uuid, '--device-set', adapter, '--disable')
|
113
|
-
end
|
114
|
-
end
|
115
|
-
|
116
|
-
adapters.each do |adapter|
|
117
|
-
args = []
|
118
|
-
if existing_adapters.include? "net#{adapter[:adapter]}"
|
119
|
-
args.concat(["--device-set","net#{adapter[:adapter]}", "--enable"])
|
120
|
-
else
|
121
|
-
args.concat(["--device-add", "net"])
|
122
|
-
end
|
123
|
-
|
124
|
-
if adapter[:type] == :hostonly
|
125
|
-
# Oddly enough, but there is a 'bridge' anyway.
|
126
|
-
# The only difference is the destination interface:
|
127
|
-
# - in host-only (private) network it will be bridged to the 'vnicX' device
|
128
|
-
# - in real bridge (public) network it will be bridged to the assigned device
|
129
|
-
args.concat(["--type", "bridged", "--iface", adapter[:hostonly]])
|
130
|
-
elsif adapter[:type] == :bridge
|
131
|
-
args.concat(["--type", "bridged", "--iface", adapter[:bridge]])
|
132
|
-
elsif adapter[:type] == :shared
|
133
|
-
args.concat(["--type", "shared"])
|
134
|
-
end
|
135
|
-
|
136
|
-
if adapter[:mac_address]
|
137
|
-
args.concat(["--mac", adapter[:mac_address]])
|
138
|
-
end
|
139
|
-
|
140
|
-
if adapter[:nic_type]
|
141
|
-
args.concat(["--adapter-type", adapter[:nic_type].to_s])
|
142
|
-
end
|
143
|
-
|
144
|
-
execute("set", @uuid, *args)
|
145
|
-
end
|
146
|
-
end
|
147
|
-
|
148
|
-
def execute_command(command)
|
149
|
-
execute(*command)
|
150
|
-
end
|
151
|
-
|
152
|
-
def export(path, tpl_name)
|
153
|
-
execute("clone", @uuid, "--name", tpl_name, "--template", "--dst", path.to_s) do |type, data|
|
154
|
-
lines = data.split("\r")
|
155
|
-
# The progress of the export will be in the last line. Do a greedy
|
156
|
-
# regular expression to find what we're looking for.
|
157
|
-
if lines.last =~ /.+?(\d{,3}) ?%/
|
158
|
-
yield $1.to_i if block_given?
|
159
|
-
end
|
160
|
-
end
|
161
|
-
read_vms[tpl_name]
|
162
|
-
end
|
163
|
-
|
164
|
-
def halt(force=false)
|
165
|
-
args = ['stop', @uuid]
|
166
|
-
args << '--kill' if force
|
167
|
-
execute(*args)
|
168
|
-
end
|
169
|
-
|
170
|
-
def import(template_uuid)
|
171
|
-
template_name = read_vms.key(template_uuid)
|
172
|
-
vm_name = "#{template_name}_#{(Time.now.to_f * 1000.0).to_i}_#{rand(100000)}"
|
173
|
-
|
174
|
-
execute("clone", template_uuid, '--name', vm_name) do |type, data|
|
175
|
-
lines = data.split("\r")
|
176
|
-
# The progress of the import will be in the last line. Do a greedy
|
177
|
-
# regular expression to find what we're looking for.
|
178
|
-
if lines.last =~ /.+?(\d{,3}) ?%/
|
179
|
-
yield $1.to_i if block_given?
|
180
|
-
end
|
181
|
-
end
|
182
|
-
read_vms[vm_name]
|
183
|
-
end
|
184
|
-
|
185
|
-
def read_bridged_interfaces
|
186
|
-
host_hw_info = read_host_info.fetch("Hardware info")
|
187
|
-
net_list = host_hw_info.select do |name, attrs|
|
188
|
-
# Get all network interfaces except 'vnicXXX'
|
189
|
-
attrs.fetch("type") == "net" and name !~ /^(vnic(.+?))$/
|
190
|
-
end
|
191
|
-
|
192
|
-
bridged_ifaces = []
|
193
|
-
net_list.keys.each do |iface|
|
194
|
-
info = {}
|
195
|
-
ifconfig = execute(:ifconfig, iface)
|
196
|
-
# Assign default values
|
197
|
-
info[:name] = iface
|
198
|
-
info[:ip] = "0.0.0.0"
|
199
|
-
info[:netmask] = "0.0.0.0"
|
200
|
-
info[:status] = "Down"
|
201
|
-
|
202
|
-
if ifconfig =~ /(?<=inet\s)(\S*)/
|
203
|
-
info[:ip] = $1.to_s
|
204
|
-
end
|
205
|
-
if ifconfig =~ /(?<=netmask\s)(\S*)/
|
206
|
-
# Netmask will be converted from hex to dec:
|
207
|
-
# '0xffffff00' -> '255.255.255.0'
|
208
|
-
info[:netmask] = $1.hex.to_s(16).scan(/../).each.map{|octet| octet.hex}.join(".")
|
209
|
-
end
|
210
|
-
if ifconfig =~ /\W(UP)\W/ and ifconfig !~ /(?<=status:\s)inactive$/
|
211
|
-
info[:status] = "Up"
|
212
|
-
end
|
213
|
-
|
214
|
-
bridged_ifaces << info
|
215
|
-
end
|
216
|
-
bridged_ifaces
|
217
|
-
end
|
218
|
-
|
219
|
-
def read_guest_ip
|
220
|
-
mac_addr = read_mac_address.downcase
|
221
|
-
leases_file = "/Library/Preferences/Parallels/parallels_dhcp_leases"
|
222
|
-
begin
|
223
|
-
File.open(leases_file).grep(/#{mac_addr}/) do |line|
|
224
|
-
return line[/^(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})/]
|
225
|
-
end
|
226
|
-
rescue Errno::EACCES
|
227
|
-
raise Errors::DhcpLeasesNotAccessible, :leases_file => leases_file.to_s
|
228
|
-
rescue Errno::ENOENT
|
229
|
-
# File does not exist
|
230
|
-
# Perhaps, it is the fist start of Parallels Desktop
|
231
|
-
return nil
|
232
|
-
end
|
233
|
-
|
234
|
-
nil
|
235
|
-
end
|
236
|
-
|
237
|
-
def read_guest_tools_version
|
238
|
-
read_settings.fetch('GuestTools', {}).fetch('version', nil)
|
239
|
-
end
|
240
|
-
|
241
|
-
def read_host_info
|
242
|
-
json { execute('server', 'info', '--json', retryable: true) }
|
243
|
-
end
|
244
|
-
|
245
|
-
def read_host_only_interfaces
|
246
|
-
net_list = read_virtual_networks
|
247
|
-
net_list.keep_if { |net| net['Type'] == "host-only" }
|
248
|
-
|
249
|
-
hostonly_ifaces = []
|
250
|
-
net_list.each do |iface|
|
251
|
-
info = {}
|
252
|
-
net_info = json { execute(:prlsrvctl, 'net', 'info', iface['Network ID'], '--json') }
|
253
|
-
# Really we need to work with bounded virtual interface
|
254
|
-
info[:name] = net_info['Bound To']
|
255
|
-
info[:ip] = net_info['Parallels adapter']['IP address']
|
256
|
-
info[:netmask] = net_info['Parallels adapter']['Subnet mask']
|
257
|
-
# Such interfaces are always in 'Up'
|
258
|
-
info[:status] = "Up"
|
259
|
-
|
260
|
-
# There may be a fake DHCPv4 parameters
|
261
|
-
# We can trust them only if adapter IP and DHCP IP are in the same subnet
|
262
|
-
dhcp_ip = net_info['DHCPv4 server']['Server address']
|
263
|
-
if network_address(info[:ip], info[:netmask]) == network_address(dhcp_ip, info[:netmask])
|
264
|
-
info[:dhcp] = {
|
265
|
-
:ip => dhcp_ip,
|
266
|
-
:lower => net_info['DHCPv4 server']['IP scope start address'],
|
267
|
-
:upper => net_info['DHCPv4 server']['IP scope end address']
|
268
|
-
}
|
269
|
-
end
|
270
|
-
hostonly_ifaces << info
|
271
|
-
end
|
272
|
-
hostonly_ifaces
|
273
|
-
end
|
274
|
-
|
275
|
-
def read_mac_address
|
276
|
-
read_settings.fetch('Hardware', {}).fetch('net0', {}).fetch('mac', nil)
|
277
|
-
end
|
278
|
-
|
279
|
-
def read_network_interfaces
|
280
|
-
nics = {}
|
281
|
-
|
282
|
-
# Get enabled VM's network interfaces
|
283
|
-
ifaces = read_settings.fetch('Hardware', {}).keep_if do |dev, params|
|
284
|
-
dev.start_with?('net') and params.fetch("enabled", true)
|
285
|
-
end
|
286
|
-
ifaces.each do |name, params|
|
287
|
-
adapter = name.match(/^net(\d+)$/)[1].to_i
|
288
|
-
nics[adapter] ||= {}
|
289
|
-
|
290
|
-
if params['type'] == "shared"
|
291
|
-
nics[adapter][:type] = :shared
|
292
|
-
elsif params['type'] == "host"
|
293
|
-
# It is PD internal host-only network and it is bounded to 'vnic1'
|
294
|
-
nics[adapter][:type] = :hostonly
|
295
|
-
nics[adapter][:hostonly] = "vnic1"
|
296
|
-
elsif params['type'] == "bridged" and params.fetch('iface','').start_with?('vnic')
|
297
|
-
# Bridged to the 'vnicXX'? Then it is a host-only, actually.
|
298
|
-
nics[adapter][:type] = :hostonly
|
299
|
-
nics[adapter][:hostonly] = params.fetch('iface','')
|
300
|
-
elsif params['type'] == "bridged"
|
301
|
-
nics[adapter][:type] = :bridged
|
302
|
-
nics[adapter][:bridge] = params.fetch('iface','')
|
303
|
-
end
|
304
|
-
end
|
305
|
-
nics
|
306
16
|
end
|
307
17
|
|
308
18
|
def read_settings
|
@@ -310,50 +20,12 @@ module VagrantPlugins
|
|
310
20
|
vm.last
|
311
21
|
end
|
312
22
|
|
313
|
-
def read_shared_interface
|
314
|
-
# There should be only one Shared interface
|
315
|
-
shared_net = read_virtual_networks.detect { |net| net['Type'] == 'shared' }
|
316
|
-
return nil if !shared_net
|
317
|
-
|
318
|
-
net_info = json { execute(:prlsrvctl, 'net', 'info', shared_net['Network ID'], '--json') }
|
319
|
-
info = {
|
320
|
-
name: net_info['Bound To'],
|
321
|
-
ip: net_info['Parallels adapter']['IP address'],
|
322
|
-
netmask: net_info['Parallels adapter']['Subnet mask'],
|
323
|
-
status: "Up"
|
324
|
-
}
|
325
|
-
|
326
|
-
if net_info.key?('DHCPv4 server')
|
327
|
-
info[:dhcp] = {
|
328
|
-
ip: net_info['DHCPv4 server']['Server address'],
|
329
|
-
lower: net_info['DHCPv4 server']['IP scope start address'],
|
330
|
-
upper: net_info['DHCPv4 server']['IP scope end address']
|
331
|
-
}
|
332
|
-
end
|
333
|
-
|
334
|
-
info
|
335
|
-
end
|
336
|
-
|
337
|
-
def read_shared_folders
|
338
|
-
shf_info = read_settings.fetch("Host Shared Folders", {})
|
339
|
-
list = {}
|
340
|
-
shf_info.delete_if {|k,v| k == "enabled"}.each do |id, data|
|
341
|
-
list[id] = data.fetch("path")
|
342
|
-
end
|
343
|
-
|
344
|
-
list
|
345
|
-
end
|
346
|
-
|
347
23
|
def read_state
|
348
24
|
vm = json { execute('list', @uuid, '--json', retryable: true) }
|
349
25
|
return nil if !vm.last
|
350
26
|
vm.last.fetch('status').to_sym
|
351
27
|
end
|
352
28
|
|
353
|
-
def read_virtual_networks
|
354
|
-
json { execute(:prlsrvctl, 'net', 'list', '--json', retryable: true) }
|
355
|
-
end
|
356
|
-
|
357
29
|
def read_vms
|
358
30
|
results = {}
|
359
31
|
vms_arr = json([]) do
|
@@ -380,76 +52,6 @@ module VagrantPlugins
|
|
380
52
|
end
|
381
53
|
vms_arr | templates_arr
|
382
54
|
end
|
383
|
-
|
384
|
-
def read_vms_paths
|
385
|
-
list = {}
|
386
|
-
read_vms_info.each do |item|
|
387
|
-
if Dir.exists? item.fetch('Home')
|
388
|
-
list[File.realpath item.fetch('Home')] = item.fetch('ID')
|
389
|
-
end
|
390
|
-
end
|
391
|
-
|
392
|
-
list
|
393
|
-
end
|
394
|
-
|
395
|
-
def register(pvm_file)
|
396
|
-
execute("register", pvm_file)
|
397
|
-
end
|
398
|
-
|
399
|
-
def registered?(uuid)
|
400
|
-
read_vms.has_value?(uuid)
|
401
|
-
end
|
402
|
-
|
403
|
-
def resume
|
404
|
-
execute('resume', @uuid)
|
405
|
-
end
|
406
|
-
|
407
|
-
def set_mac_address(mac)
|
408
|
-
execute('set', @uuid, '--device-set', 'net0', '--type', 'shared', '--mac', mac)
|
409
|
-
end
|
410
|
-
|
411
|
-
def set_name(name)
|
412
|
-
execute('set', @uuid, '--name', name, :retryable => true)
|
413
|
-
end
|
414
|
-
|
415
|
-
def share_folders(folders)
|
416
|
-
folders.each do |folder|
|
417
|
-
# Add the shared folder
|
418
|
-
execute('set', @uuid, '--shf-host-add', folder[:name], '--path', folder[:hostpath])
|
419
|
-
end
|
420
|
-
end
|
421
|
-
|
422
|
-
def ssh_port(expected_port)
|
423
|
-
expected_port
|
424
|
-
end
|
425
|
-
|
426
|
-
def start
|
427
|
-
execute('start', @uuid)
|
428
|
-
end
|
429
|
-
|
430
|
-
def suspend
|
431
|
-
execute('suspend', @uuid)
|
432
|
-
end
|
433
|
-
|
434
|
-
def unregister(uuid)
|
435
|
-
execute("unregister", uuid)
|
436
|
-
end
|
437
|
-
|
438
|
-
def verify!
|
439
|
-
version
|
440
|
-
end
|
441
|
-
|
442
|
-
def version
|
443
|
-
if execute('--version', retryable: true) =~ /prlctl version ([\d\.]+)/
|
444
|
-
$1.downcase
|
445
|
-
else
|
446
|
-
raise VagrantPlugins::Parallels::Errors::ParallelsInstallIncomplete
|
447
|
-
end
|
448
|
-
end
|
449
|
-
|
450
|
-
def vm_exists?(uuid)
|
451
|
-
raw("list", uuid).exit_code == 0
|
452
|
-
end
|
453
55
|
end
|
454
56
|
end
|
455
57
|
end
|
@@ -4,74 +4,35 @@ module VagrantPlugins
|
|
4
4
|
class MountParallelsSharedFolder
|
5
5
|
|
6
6
|
def self.mount_parallels_shared_folder(machine, name, guestpath, options)
|
7
|
+
# Expand the guest path so we can handle things like "~/vagrant"
|
7
8
|
expanded_guest_path = machine.guest.capability(
|
8
9
|
:shell_expand_guest_path, guestpath)
|
9
10
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
else
|
15
|
-
mount_uid = "`id -u #{options[:owner]}`"
|
16
|
-
end
|
17
|
-
|
18
|
-
if options[:group].is_a? Integer
|
19
|
-
mount_gid = options[:group]
|
20
|
-
mount_gid_old = options[:group]
|
21
|
-
else
|
22
|
-
mount_gid = "`getent group #{options[:group]} | cut -d: -f3`"
|
23
|
-
mount_gid_old = "`id -g #{options[:group]}`"
|
24
|
-
end
|
25
|
-
|
26
|
-
# First mount command uses getent to get the group
|
27
|
-
mount_options = "-o uid=#{mount_uid},gid=#{mount_gid}"
|
28
|
-
mount_options += ",#{options[:mount_options].join(",")}" if options[:mount_options]
|
29
|
-
mount_commands << "mount -t prl_fs #{mount_options} #{name} #{expanded_guest_path}"
|
30
|
-
|
31
|
-
# Second mount command uses the old style `id -g`
|
32
|
-
mount_options = "-o uid=#{mount_uid},gid=#{mount_gid_old}"
|
33
|
-
mount_options += ",#{options[:mount_options].join(",")}" if options[:mount_options]
|
34
|
-
mount_commands << "mount -t prl_fs #{mount_options} #{name} #{expanded_guest_path}"
|
35
|
-
|
36
|
-
# Clear prior symlink if exists
|
37
|
-
if machine.communicate.test("test -L #{expanded_guest_path}")
|
38
|
-
machine.communicate.sudo("rm #{expanded_guest_path}")
|
39
|
-
end
|
40
|
-
|
41
|
-
# Create the guest path if it doesn't exist
|
42
|
-
machine.communicate.sudo("mkdir -p #{expanded_guest_path}")
|
43
|
-
|
44
|
-
# Attempt to mount the folder. We retry here a few times because
|
45
|
-
# it can fail early on.
|
46
|
-
attempts = 0
|
47
|
-
while true
|
48
|
-
success = true
|
49
|
-
|
50
|
-
mount_commands.each do |command|
|
51
|
-
no_such_device = false
|
52
|
-
status = machine.communicate.sudo(command, error_check: false) do |type, data|
|
53
|
-
no_such_device = true if type == :stderr && data =~ /No such device/i
|
54
|
-
end
|
55
|
-
|
56
|
-
success = status == 0 && !no_such_device
|
57
|
-
break if success
|
11
|
+
machine.communicate.tap do |comm|
|
12
|
+
# clear prior symlink
|
13
|
+
if comm.test("test -L \"#{expanded_guest_path}\"", :sudo => true)
|
14
|
+
comm.sudo("rm \"#{expanded_guest_path}\"")
|
58
15
|
end
|
59
16
|
|
60
|
-
|
17
|
+
# clear prior directory if exists
|
18
|
+
if comm.test("test -d \"#{expanded_guest_path}\"", :sudo => true)
|
19
|
+
comm.sudo("rm -Rf \"#{expanded_guest_path}\"")
|
20
|
+
end
|
61
21
|
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
22
|
+
# create intermediate directories if needed
|
23
|
+
intermediate_dir = File.dirname(expanded_guest_path)
|
24
|
+
if !comm.test("test -d \"#{intermediate_dir}\"", :sudo => true)
|
25
|
+
comm.sudo("mkdir -p \"#{intermediate_dir}\"")
|
66
26
|
end
|
67
27
|
|
68
|
-
|
69
|
-
|
28
|
+
# finally make the symlink
|
29
|
+
comm.sudo("ln -s \"/media/psf/#{name}\" \"#{expanded_guest_path}\"")
|
70
30
|
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
31
|
+
# Emit an upstart event if we can
|
32
|
+
if comm.test("test -x /sbin/initctl")
|
33
|
+
comm.sudo(
|
34
|
+
"/sbin/initctl emit --no-wait vagrant-mounted MOUNTPOINT=#{expanded_guest_path}")
|
35
|
+
end
|
75
36
|
end
|
76
37
|
end
|
77
38
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: vagrant-parallels
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.6.rc1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mikhail Zholobov
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2014-03-
|
12
|
+
date: 2014-03-24 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: bundler
|
@@ -90,7 +90,6 @@ files:
|
|
90
90
|
- lib/vagrant-parallels/action/destroy.rb
|
91
91
|
- lib/vagrant-parallels/action/destroy_unused_network_interfaces.rb
|
92
92
|
- lib/vagrant-parallels/action/export.rb
|
93
|
-
- lib/vagrant-parallels/action/force_prl_fs_mount.rb
|
94
93
|
- lib/vagrant-parallels/action/forced_halt.rb
|
95
94
|
- lib/vagrant-parallels/action/import.rb
|
96
95
|
- lib/vagrant-parallels/action/is_running.rb
|
@@ -1,55 +0,0 @@
|
|
1
|
-
require "log4r"
|
2
|
-
require 'vagrant/util/platform'
|
3
|
-
|
4
|
-
module VagrantPlugins
|
5
|
-
module Parallels
|
6
|
-
module Action
|
7
|
-
class ForcePrlFsMount
|
8
|
-
# This middleware forces the prl_fs mount after the Resume, because
|
9
|
-
# there is bug in Linux guests - custom shared folders are missed after
|
10
|
-
# the resume [GH-102]
|
11
|
-
include Vagrant::Action::Builtin::MixinSyncedFolders
|
12
|
-
|
13
|
-
def initialize(app, env)
|
14
|
-
@app = app
|
15
|
-
@logger = Log4r::Logger.new("vagrant::plugins::parallels::force_prl_fs_mount")
|
16
|
-
end
|
17
|
-
|
18
|
-
def call(env)
|
19
|
-
# Only for Linux guests!
|
20
|
-
if env[:machine].communicate.test("uname -s | grep 'Linux'")
|
21
|
-
folders = synced_folders(env[:machine])[:parallels]
|
22
|
-
|
23
|
-
# Go through each folder and make sure to create it if
|
24
|
-
# it does not exist on host
|
25
|
-
folders.each do |id, data|
|
26
|
-
data[:hostpath] = File.expand_path(data[:hostpath], env[:root_path])
|
27
|
-
|
28
|
-
# Create the hostpath if it doesn't exist and we've been told to
|
29
|
-
if !File.directory?(data[:hostpath]) && data[:create]
|
30
|
-
@logger.info("Creating shared folder host directory: #{data[:hostpath]}")
|
31
|
-
begin
|
32
|
-
Pathname.new(data[:hostpath]).mkpath
|
33
|
-
rescue Errno::EACCES
|
34
|
-
raise Vagrant::Errors::SharedFolderCreateFailed,
|
35
|
-
path: data[:hostpath]
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
if File.directory?(data[:hostpath])
|
40
|
-
data[:hostpath] = File.realpath(data[:hostpath])
|
41
|
-
data[:hostpath] = Vagrant::Util::Platform.fs_real_path(data[:hostpath]).to_s
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
opts = nil
|
46
|
-
instance = VagrantPlugins::Parallels::SyncedFolder.new
|
47
|
-
instance.enable(env[:machine], folders, opts)
|
48
|
-
end
|
49
|
-
|
50
|
-
@app.call(env)
|
51
|
-
end
|
52
|
-
end
|
53
|
-
end
|
54
|
-
end
|
55
|
-
end
|