vagrant-parallels 1.5.1 → 1.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +7 -4
- data/CHANGELOG.md +33 -0
- data/Gemfile +2 -2
- data/README.md +1 -1
- data/debug.log +1237 -1
- data/lib/vagrant-parallels/action.rb +8 -0
- data/lib/vagrant-parallels/action/box_register.rb +113 -0
- data/lib/vagrant-parallels/action/box_unregister.rb +43 -0
- data/lib/vagrant-parallels/action/export.rb +36 -35
- data/lib/vagrant-parallels/action/forward_ports.rb +32 -18
- data/lib/vagrant-parallels/action/import.rb +59 -106
- data/lib/vagrant-parallels/action/network.rb +17 -13
- data/lib/vagrant-parallels/action/prepare_clone_snapshot.rb +67 -0
- data/lib/vagrant-parallels/action/set_name.rb +1 -1
- data/lib/vagrant-parallels/action/snapshot_delete.rb +25 -0
- data/lib/vagrant-parallels/action/snapshot_restore.rb +23 -0
- data/lib/vagrant-parallels/action/snapshot_save.rb +23 -0
- data/lib/vagrant-parallels/cap.rb +63 -0
- data/lib/vagrant-parallels/config.rb +7 -3
- data/lib/vagrant-parallels/driver/base.rb +61 -28
- data/lib/vagrant-parallels/driver/meta.rb +20 -10
- data/lib/vagrant-parallels/driver/pd_11.rb +0 -21
- data/lib/vagrant-parallels/errors.rb +14 -6
- data/lib/vagrant-parallels/guest_cap/darwin/install_parallels_tools.rb +34 -0
- data/lib/vagrant-parallels/plugin.rb +23 -8
- data/lib/vagrant-parallels/version.rb +1 -1
- data/locales/en.yml +31 -17
- data/test/acceptance/provider/linked_clone_spec.rb +6 -2
- data/test/acceptance/skeletons/linked_clone/Vagrantfile +1 -1
- data/test/unit/base.rb +1 -0
- data/test/unit/cap_test.rb +96 -0
- data/test/unit/support/shared/pd_driver_examples.rb +7 -10
- metadata +12 -6
- data/lib/vagrant-parallels/cap/forwarded_ports.rb +0 -22
- data/lib/vagrant-parallels/cap/host_address.rb +0 -15
- data/lib/vagrant-parallels/cap/nic_mac_addresses.rb +0 -17
- data/lib/vagrant-parallels/cap/public_address.rb +0 -15
@@ -167,6 +167,7 @@ module VagrantPlugins
|
|
167
167
|
b1.use HandleForwardedPortCollisions
|
168
168
|
b1.use ForwardPorts
|
169
169
|
b1.use Resume
|
170
|
+
b1.use Provision
|
170
171
|
b1.use WaitForCommunicator, [:resuming, :running]
|
171
172
|
end
|
172
173
|
end
|
@@ -276,7 +277,11 @@ module VagrantPlugins
|
|
276
277
|
# If the VM is NOT created yet, then do the setup steps
|
277
278
|
if env1[:result]
|
278
279
|
b1.use Customize, 'pre-import'
|
280
|
+
b1.use BoxRegister
|
281
|
+
b1.use PrepareClone
|
282
|
+
b1.use PrepareCloneSnapshot
|
279
283
|
b1.use Import
|
284
|
+
b1.use BoxUnregister
|
280
285
|
b1.use SaneDefaults
|
281
286
|
b1.use Customize, 'post-import'
|
282
287
|
end
|
@@ -330,6 +335,8 @@ module VagrantPlugins
|
|
330
335
|
|
331
336
|
|
332
337
|
autoload :Boot, File.expand_path('../action/boot', __FILE__)
|
338
|
+
autoload :BoxRegister, File.expand_path('../action/box_register', __FILE__)
|
339
|
+
autoload :BoxUnregister, File.expand_path('../action/box_unregister', __FILE__)
|
333
340
|
autoload :HandleGuestTools, File.expand_path('../action/handle_guest_tools', __FILE__)
|
334
341
|
autoload :HandleForwardedPortCollisions, File.expand_path('../action/handle_forwarded_port_collisions.rb', __FILE__)
|
335
342
|
autoload :ClearNetworkInterfaces, File.expand_path('../action/clear_network_interfaces', __FILE__)
|
@@ -344,6 +351,7 @@ module VagrantPlugins
|
|
344
351
|
autoload :Network, File.expand_path('../action/network', __FILE__)
|
345
352
|
autoload :Package, File.expand_path('../action/package', __FILE__)
|
346
353
|
autoload :PackageConfigFiles, File.expand_path('../action/package_config_files', __FILE__)
|
354
|
+
autoload :PrepareCloneSnapshot, File.expand_path('../action/prepare_clone_snapshot', __FILE__)
|
347
355
|
autoload :PrepareForwardedPortCollisionParams, File.expand_path('../action/prepare_forwarded_port_collision_params', __FILE__)
|
348
356
|
autoload :PrepareNFSSettings, File.expand_path('../action/prepare_nfs_settings', __FILE__)
|
349
357
|
autoload :PrepareNFSValidIds, File.expand_path('../action/prepare_nfs_valid_ids', __FILE__)
|
@@ -0,0 +1,113 @@
|
|
1
|
+
require 'log4r'
|
2
|
+
|
3
|
+
module VagrantPlugins
|
4
|
+
module Parallels
|
5
|
+
module Action
|
6
|
+
class BoxRegister
|
7
|
+
@@lock = Mutex.new
|
8
|
+
|
9
|
+
def initialize(app, env)
|
10
|
+
@app = app
|
11
|
+
@logger = Log4r::Logger.new('vagrant_parallels::action::box_register')
|
12
|
+
end
|
13
|
+
|
14
|
+
def call(env)
|
15
|
+
# If we don't have a box, nothing to do
|
16
|
+
if !env[:machine].box
|
17
|
+
return @app.call(env)
|
18
|
+
end
|
19
|
+
|
20
|
+
# Do the register while locked so that nobody else register
|
21
|
+
# a box at the same time.
|
22
|
+
@@lock.synchronize do
|
23
|
+
lock_key = Digest::MD5.hexdigest(env[:machine].box.name)
|
24
|
+
env[:machine].env.lock(lock_key, retry: true) do
|
25
|
+
register_box(env)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
# If we got interrupted, then the import could have been
|
30
|
+
# interrupted and its not a big deal. Just return out.
|
31
|
+
return if env[:interrupted]
|
32
|
+
|
33
|
+
# Register completed successfully. Continue the chain
|
34
|
+
@app.call(env)
|
35
|
+
end
|
36
|
+
|
37
|
+
protected
|
38
|
+
|
39
|
+
def box_path(env)
|
40
|
+
pvm = Dir.glob(env[:machine].box.directory.join('*.pvm')).first
|
41
|
+
|
42
|
+
if !pvm
|
43
|
+
raise Errors::BoxImageNotFound, name: env[:machine].box.name
|
44
|
+
end
|
45
|
+
|
46
|
+
pvm
|
47
|
+
end
|
48
|
+
|
49
|
+
def box_id(env, box_path)
|
50
|
+
# Get the box image UUID from XML-based configuration file
|
51
|
+
tpl_config = File.join(box_path, 'config.pvs')
|
52
|
+
xml = Nokogiri::XML(File.open(tpl_config))
|
53
|
+
id = xml.xpath('//ParallelsVirtualMachine/Identification/VmUuid').text
|
54
|
+
|
55
|
+
if !id
|
56
|
+
raise Errors::BoxIDNotFound,
|
57
|
+
name: env[:machine].box.name,
|
58
|
+
config: tpl_config
|
59
|
+
end
|
60
|
+
|
61
|
+
id
|
62
|
+
end
|
63
|
+
|
64
|
+
def register_box(env)
|
65
|
+
box_id_file = env[:machine].box.directory.join('box_id')
|
66
|
+
|
67
|
+
# Read the master ID if we have it in the file.
|
68
|
+
env[:clone_id] = box_id_file.read.chomp if box_id_file.file?
|
69
|
+
|
70
|
+
# If we have the ID and the VM exists already, then we
|
71
|
+
# have nothing to do. Success!
|
72
|
+
if env[:clone_id] && env[:machine].provider.driver.vm_exists?(env[:clone_id])
|
73
|
+
@logger.info(
|
74
|
+
"Box image '#{env[:machine].box.name}' is already registered " +
|
75
|
+
"(id=#{env[:clone_id]}) - skipping register step.")
|
76
|
+
return
|
77
|
+
end
|
78
|
+
|
79
|
+
env[:ui].info I18n.t('vagrant_parallels.actions.vm.box.register',
|
80
|
+
name: env[:machine].box.name)
|
81
|
+
|
82
|
+
pvm = box_path(env)
|
83
|
+
|
84
|
+
# We need the box ID to be the same for all parallel runs
|
85
|
+
options = ['--preserve-uuid']
|
86
|
+
|
87
|
+
if env[:machine].provider_config.regen_src_uuid \
|
88
|
+
&& env[:machine].provider.pd_version_satisfies?('>= 10.1.2')
|
89
|
+
options << '--regenerate-src-uuid'
|
90
|
+
end
|
91
|
+
|
92
|
+
# Register the box VM image
|
93
|
+
env[:machine].provider.driver.register(pvm, options)
|
94
|
+
env[:clone_id] = box_id(env, pvm)
|
95
|
+
|
96
|
+
@logger.info(
|
97
|
+
"Registered box #{env[:machine].box.name} with id #{env[:clone_id]}")
|
98
|
+
|
99
|
+
@logger.debug("Writing box id '#{env[:clone_id]}' to #{box_id_file}")
|
100
|
+
box_id_file.open('w+') do |f|
|
101
|
+
f.write(env[:clone_id])
|
102
|
+
end
|
103
|
+
|
104
|
+
if env[:machine].provider.pd_version_satisfies?('>= 10')
|
105
|
+
# Convert template to VM (compatibility with old-styled boxes)
|
106
|
+
env[:machine].provider.driver.execute_prlctl(
|
107
|
+
'set', env[:clone_id], '--template', 'off')
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'log4r'
|
2
|
+
|
3
|
+
module VagrantPlugins
|
4
|
+
module Parallels
|
5
|
+
module Action
|
6
|
+
class BoxUnregister
|
7
|
+
def initialize(app, env)
|
8
|
+
@app = app
|
9
|
+
@logger = Log4r::Logger.new('vagrant_parallels::action::box_unregister')
|
10
|
+
end
|
11
|
+
|
12
|
+
def call(env)
|
13
|
+
# If we don't have a box, nothing to do
|
14
|
+
if !env[:machine].box
|
15
|
+
return @app.call(env)
|
16
|
+
end
|
17
|
+
|
18
|
+
unregister_box(env)
|
19
|
+
|
20
|
+
# If we got interrupted, then the import could have been
|
21
|
+
# interrupted and its not a big deal. Just return out.
|
22
|
+
return if env[:interrupted]
|
23
|
+
|
24
|
+
# Register completed successfully. Continue the chain
|
25
|
+
@app.call(env)
|
26
|
+
end
|
27
|
+
|
28
|
+
def recover(env)
|
29
|
+
unregister_box(env)
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def unregister_box(env)
|
35
|
+
if env[:clone_id] && env[:machine].provider.driver.vm_exists?(env[:clone_id])
|
36
|
+
env[:ui].info I18n.t('vagrant_parallels.actions.vm.box.unregister')
|
37
|
+
env[:machine].provider.driver.unregister(env[:clone_id])
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -8,84 +8,85 @@ module VagrantPlugins
|
|
8
8
|
end
|
9
9
|
|
10
10
|
def call(env)
|
11
|
-
@env = env
|
12
11
|
if env[:machine].state.id != :stopped
|
13
12
|
raise Vagrant::Errors::VMPowerOffToPackage
|
14
13
|
end
|
15
14
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
compact_template
|
20
|
-
unregister_template
|
15
|
+
clone(env)
|
16
|
+
compact(env)
|
17
|
+
unregister_vm(env)
|
21
18
|
|
22
19
|
@app.call(env)
|
23
20
|
end
|
24
21
|
|
25
22
|
def recover(env)
|
26
|
-
|
27
|
-
unregister_template
|
23
|
+
unregister_vm(env)
|
28
24
|
end
|
29
25
|
|
30
26
|
private
|
31
27
|
|
32
|
-
def
|
28
|
+
def box_vm_name(env)
|
33
29
|
# Use configured name if it is specified, or generate the new one
|
34
|
-
name =
|
30
|
+
name = env[:machine].provider_config.name
|
35
31
|
if !name
|
36
|
-
name = "#{
|
32
|
+
name = "#{env[:root_path].basename.to_s}_#{env[:machine].name}"
|
37
33
|
name.gsub!(/[^-a-z0-9_]/i, '')
|
38
34
|
end
|
39
35
|
|
40
|
-
|
36
|
+
vm_name = "#{name}_box"
|
41
37
|
|
42
38
|
# Ensure that the name is not in use
|
43
39
|
ind = 0
|
44
|
-
while
|
40
|
+
while env[:machine].provider.driver.read_vms.has_key?(vm_name)
|
45
41
|
ind += 1
|
46
|
-
|
42
|
+
vm_name = "#{name}_box_#{ind}"
|
47
43
|
end
|
48
44
|
|
49
|
-
|
45
|
+
vm_name
|
50
46
|
end
|
51
47
|
|
52
|
-
def
|
53
|
-
|
48
|
+
def clone(env)
|
49
|
+
env[:ui].info I18n.t('vagrant.actions.vm.export.exporting')
|
54
50
|
|
55
51
|
options = {
|
56
|
-
|
57
|
-
dst: @env['export.temp_dir'].to_s
|
52
|
+
dst: env['export.temp_dir'].to_s
|
58
53
|
}
|
59
54
|
|
60
|
-
|
61
|
-
|
62
|
-
|
55
|
+
env[:package_box_id] = env[:machine].provider.driver.clone_vm(
|
56
|
+
env[:machine].id, options) do |progress|
|
57
|
+
env[:ui].clear_line
|
58
|
+
env[:ui].report_progress(progress, 100, false)
|
63
59
|
|
64
|
-
#
|
65
|
-
#
|
66
|
-
raise Vagrant::Errors::VagrantInterrupt if
|
60
|
+
# If we got interrupted, then rise an exception and 'recover'
|
61
|
+
# will be called to cleanup.
|
62
|
+
raise Vagrant::Errors::VagrantInterrupt if env[:interrupted]
|
67
63
|
end
|
68
64
|
|
65
|
+
# Set the box VM name
|
66
|
+
name = box_vm_name(env)
|
67
|
+
env[:machine].provider.driver.set_name(env[:package_box_id], name)
|
68
|
+
|
69
69
|
# Clear the line a final time so the next data can appear
|
70
70
|
# alone on the line.
|
71
|
-
|
71
|
+
env[:ui].clear_line
|
72
72
|
end
|
73
73
|
|
74
|
-
def
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
74
|
+
def compact(env)
|
75
|
+
env[:ui].info I18n.t('vagrant_parallels.actions.vm.export.compacting')
|
76
|
+
env[:machine].provider.driver.compact(env[:package_box_id]) do |progress|
|
77
|
+
env[:ui].clear_line
|
78
|
+
env[:ui].report_progress(progress, 100, false)
|
79
79
|
end
|
80
80
|
|
81
81
|
# Clear the line a final time so the next data can appear
|
82
82
|
# alone on the line.
|
83
|
-
|
83
|
+
env[:ui].clear_line
|
84
84
|
end
|
85
85
|
|
86
|
-
def
|
87
|
-
|
88
|
-
@env[:
|
86
|
+
def unregister_vm(env)
|
87
|
+
return if !env[:package_box_id]
|
88
|
+
@logger.info("Unregister the box VM: '#{env[:package_box_id]}'")
|
89
|
+
env[:machine].provider.driver.unregister(env[:package_box_id])
|
89
90
|
end
|
90
91
|
end
|
91
92
|
end
|
@@ -3,6 +3,7 @@ module VagrantPlugins
|
|
3
3
|
module Action
|
4
4
|
class ForwardPorts
|
5
5
|
include VagrantPlugins::Parallels::Util::CompileForwardedPorts
|
6
|
+
@@lock = Mutex.new
|
6
7
|
|
7
8
|
def initialize(app, env)
|
8
9
|
@app = app
|
@@ -21,13 +22,30 @@ module VagrantPlugins
|
|
21
22
|
|
22
23
|
# Get the ports we're forwarding
|
23
24
|
env[:forwarded_ports] ||= compile_forwarded_ports(env[:machine].config)
|
24
|
-
|
25
|
-
|
25
|
+
|
26
|
+
# Exit if there are no ports to forward
|
27
|
+
return @app.call(env) if env[:forwarded_ports].empty?
|
28
|
+
|
29
|
+
# Acquire both of class- and process-level locks so that we don't
|
30
|
+
# forward ports simultaneousely with someone else.
|
31
|
+
@@lock.synchronize do
|
32
|
+
begin
|
33
|
+
env[:machine].env.lock('forward_ports') do
|
34
|
+
env[:ui].output(I18n.t('vagrant.actions.vm.forward_ports.forwarding'))
|
35
|
+
forward_ports
|
36
|
+
end
|
37
|
+
rescue Errors::EnvironmentLockedError
|
38
|
+
sleep 1
|
39
|
+
retry
|
40
|
+
end
|
41
|
+
end
|
26
42
|
|
27
43
|
@app.call(env)
|
28
44
|
end
|
29
45
|
|
30
46
|
def forward_ports
|
47
|
+
all_rules = @env[:machine].provider.driver.read_forwarded_ports(true)
|
48
|
+
names_in_use = all_rules.collect { |r| r[:rule_name] }
|
31
49
|
ports = []
|
32
50
|
|
33
51
|
@env[:forwarded_ports].each do |fp|
|
@@ -43,11 +61,22 @@ module VagrantPlugins
|
|
43
61
|
@env[:ui].detail(I18n.t('vagrant_parallels.actions.vm.forward_ports.forwarding_entry',
|
44
62
|
message_attributes))
|
45
63
|
|
64
|
+
# In Parallels Desktop the scope port forwarding rules is global,
|
65
|
+
# so we have to keep their names unique.
|
66
|
+
unique_id = fp.id
|
67
|
+
# Append random suffix to get the unique rule name
|
68
|
+
while names_in_use.include?(unique_id)
|
69
|
+
suffix = (0...4).map { ('a'..'z').to_a[rand(26)] }.join
|
70
|
+
unique_id = "#{fp.id}_#{suffix}"
|
71
|
+
end
|
72
|
+
# Mark this rule name as in use
|
73
|
+
names_in_use << unique_id
|
74
|
+
|
46
75
|
# Add the options to the ports array to send to the driver later
|
47
76
|
ports << {
|
48
77
|
guestport: fp.guest_port,
|
49
78
|
hostport: fp.host_port,
|
50
|
-
name:
|
79
|
+
name: unique_id,
|
51
80
|
protocol: fp.protocol
|
52
81
|
}
|
53
82
|
end
|
@@ -57,21 +86,6 @@ module VagrantPlugins
|
|
57
86
|
@env[:machine].provider.driver.forward_ports(ports)
|
58
87
|
end
|
59
88
|
end
|
60
|
-
|
61
|
-
private
|
62
|
-
|
63
|
-
def get_unique_name(id)
|
64
|
-
all_rules = @env[:machine].provider.driver.read_forwarded_ports(true)
|
65
|
-
names_in_use = all_rules.collect { |r| r[:rule_name] }
|
66
|
-
|
67
|
-
# Append random suffix to get unique rule name
|
68
|
-
while names_in_use.include?(id)
|
69
|
-
suffix = (0...4).map { ('a'..'z').to_a[rand(26)] }.join
|
70
|
-
id = "#{id}_#{suffix}"
|
71
|
-
end
|
72
|
-
|
73
|
-
id
|
74
|
-
end
|
75
89
|
end
|
76
90
|
end
|
77
91
|
end
|
@@ -1,17 +1,19 @@
|
|
1
1
|
require 'nokogiri'
|
2
2
|
|
3
|
+
require 'digest/md5'
|
4
|
+
|
3
5
|
module VagrantPlugins
|
4
6
|
module Parallels
|
5
7
|
module Action
|
6
8
|
class Import
|
9
|
+
@@lock = Mutex.new
|
10
|
+
|
7
11
|
def initialize(app, env)
|
8
12
|
@app = app
|
9
13
|
@logger = Log4r::Logger.new('vagrant_parallels::action::import')
|
10
14
|
end
|
11
15
|
|
12
16
|
def call(env)
|
13
|
-
@machine = env[:machine]
|
14
|
-
|
15
17
|
# Disable requiring password for register and clone actions [GH-67].
|
16
18
|
# It is available only since PD 10.
|
17
19
|
if env[:machine].provider.pd_version_satisfies?('>= 10')
|
@@ -20,32 +22,54 @@ module VagrantPlugins
|
|
20
22
|
env[:machine].provider.driver.disable_password_restrictions(acts)
|
21
23
|
end
|
22
24
|
|
23
|
-
#
|
24
|
-
|
25
|
+
# Linked clones are supported only for PD 11 and higher
|
26
|
+
if env[:machine].provider_config.linked_clone \
|
27
|
+
&& env[:machine].provider.pd_version_satisfies?('>= 11')
|
28
|
+
# Linked clone creation should not be concurrent [GH-206]
|
29
|
+
@@lock.synchronize do
|
30
|
+
lock_key = Digest::MD5.hexdigest("#{env[:clone_id]}-linked-clone")
|
31
|
+
env[:machine].env.lock(lock_key, retry: true) do
|
32
|
+
clone_linked(env)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
else
|
36
|
+
clone_full(env)
|
37
|
+
end
|
25
38
|
|
26
|
-
#
|
27
|
-
#
|
28
|
-
|
39
|
+
# If we got interrupted, then the import could have been
|
40
|
+
# interrupted and its not a big deal. Just return out.
|
41
|
+
return if env[:interrupted]
|
29
42
|
|
30
|
-
#
|
31
|
-
|
43
|
+
# Flag as erroneous and return if import failed
|
44
|
+
raise Errors::VMCloneFailure if !env[:machine].id
|
32
45
|
|
33
|
-
|
34
|
-
|
46
|
+
if env[:machine].provider_config.regen_src_uuid \
|
47
|
+
&& env[:machine].provider.pd_version_satisfies?('< 11')
|
48
|
+
@logger.info('Regenerate SourceVmUuid by editing config.pvs file')
|
49
|
+
env[:machine].provider.driver.regenerate_src_uuid
|
50
|
+
end
|
35
51
|
|
36
|
-
#
|
37
|
-
|
52
|
+
# Remove 'Icon\r' file from VM home (bug in PD 11.0.0)
|
53
|
+
if env[:machine].provider.pd_version_satisfies?('= 11.0.0')
|
54
|
+
vm_home = env[:machine].provider.driver.read_settings.fetch('Home')
|
55
|
+
broken_icns = Dir[File.join(vm_home, 'Icon*')]
|
56
|
+
FileUtils.rm(broken_icns, :force => true)
|
57
|
+
end
|
58
|
+
|
59
|
+
# Copy the SSH key from the clone machine if we can
|
60
|
+
if env[:clone_machine]
|
61
|
+
key_path = env[:clone_machine].data_dir.join('private_key')
|
62
|
+
if key_path.file?
|
63
|
+
FileUtils.cp(key_path, env[:machine].data_dir.join('private_key'))
|
64
|
+
end
|
65
|
+
end
|
38
66
|
|
39
67
|
# Import completed successfully. Continue the chain
|
40
68
|
@app.call(env)
|
41
69
|
end
|
42
70
|
|
43
71
|
def recover(env)
|
44
|
-
|
45
|
-
tpl_name = template_name(template_path)
|
46
|
-
unregister_template(tpl_name)
|
47
|
-
|
48
|
-
if @machine.state.id != :not_created
|
72
|
+
if env[:machine] && env[:machine].state.id != :not_created
|
49
73
|
return if env['vagrant.error'].is_a?(Vagrant::Errors::VagrantError)
|
50
74
|
return if env['vagrant_parallels.error'].is_a?(Errors::VagrantParallelsError)
|
51
75
|
|
@@ -64,78 +88,12 @@ module VagrantPlugins
|
|
64
88
|
|
65
89
|
protected
|
66
90
|
|
67
|
-
def
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
def template_path
|
73
|
-
Pathname.glob(@machine.box.directory.join('*.pvm')).first
|
74
|
-
end
|
75
|
-
|
76
|
-
def template_name(tpl_path)
|
77
|
-
# Get template name from XML-based configuration file
|
78
|
-
tpl_config = tpl_path.join('config.pvs')
|
79
|
-
xml = Nokogiri::XML(File.open(tpl_config))
|
80
|
-
name = xml.xpath('//ParallelsVirtualMachine/Identification/VmName').text
|
81
|
-
|
82
|
-
if !name
|
83
|
-
raise Errors::ParallelsTplNameNotFound, config_path: tpl_config
|
84
|
-
end
|
85
|
-
|
86
|
-
name
|
87
|
-
end
|
88
|
-
|
89
|
-
def import(env, tpl_name)
|
90
|
-
# Linked clones are supported only for PD 11 and higher
|
91
|
-
if @machine.provider_config.use_linked_clone \
|
92
|
-
&& @machine.provider.pd_version_satisfies?('>= 11')
|
93
|
-
|
94
|
-
env[:ui].info I18n.t('vagrant_parallels.actions.vm.import.importing_linked',
|
95
|
-
:name => @machine.box.name)
|
96
|
-
opts = {
|
97
|
-
snapshot_id: snapshot_id(tpl_name),
|
98
|
-
linked: true
|
99
|
-
}
|
100
|
-
# Linked clone creation should not be concurrent [GH-206]
|
101
|
-
begin
|
102
|
-
@machine.env.lock("parallels_linked_clone") do
|
103
|
-
clone(env, tpl_name, opts)
|
104
|
-
end
|
105
|
-
rescue Vagrant::Errors::EnvironmentLockedError
|
106
|
-
sleep 1
|
107
|
-
retry
|
108
|
-
end
|
109
|
-
else
|
110
|
-
env[:ui].info I18n.t('vagrant.actions.vm.import.importing',
|
111
|
-
:name => @machine.box.name)
|
112
|
-
clone(env, tpl_name)
|
113
|
-
end
|
114
|
-
|
115
|
-
if @machine.provider_config.regen_src_uuid
|
116
|
-
@logger.info('Regenerate SourceVmUuid')
|
117
|
-
@machine.provider.driver.regenerate_src_uuid
|
118
|
-
end
|
119
|
-
|
120
|
-
# Remove 'Icon\r' file from VM home (bug in PD 11.0.0)
|
121
|
-
if @machine.provider.pd_version_satisfies?('= 11.0.0')
|
122
|
-
vm_home = @machine.provider.driver.read_settings.fetch('Home')
|
123
|
-
broken_icns = Dir[File.join(vm_home, 'Icon*')]
|
124
|
-
FileUtils.rm(broken_icns, :force => true)
|
125
|
-
end
|
126
|
-
end
|
127
|
-
|
128
|
-
def clone(env, tpl_name, opts={})
|
129
|
-
# Generate virtual machine name
|
130
|
-
vm_name = "#{tpl_name}_#{(Time.now.to_f * 1000.0).to_i}_#{rand(100000)}"
|
131
|
-
|
132
|
-
@machine.id = @machine.provider.driver.clone_vm(tpl_name, vm_name, opts) do |progress|
|
91
|
+
def clone_full(env)
|
92
|
+
env[:ui].info I18n.t('vagrant_parallels.actions.vm.clone.full')
|
93
|
+
env[:machine].id = env[:machine].provider.driver.clone_vm(
|
94
|
+
env[:clone_id]) do |progress|
|
133
95
|
env[:ui].clear_line
|
134
96
|
env[:ui].report_progress(progress, 100, false)
|
135
|
-
|
136
|
-
# # If we got interrupted, then the import could have been interrupted.
|
137
|
-
# Just rise an exception and then 'recover' will be called to cleanup.
|
138
|
-
raise Vagrant::Errors::VagrantInterrupt if env[:interrupted]
|
139
97
|
end
|
140
98
|
|
141
99
|
# Clear the line one last time since the progress meter doesn't disappear
|
@@ -143,26 +101,21 @@ module VagrantPlugins
|
|
143
101
|
env[:ui].clear_line
|
144
102
|
end
|
145
103
|
|
146
|
-
def
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
snap_id = @machine.provider.driver.create_snapshot(tpl_name, opts)
|
104
|
+
def clone_linked(env)
|
105
|
+
opts = {
|
106
|
+
snapshot_id: env[:clone_snapshot_id],
|
107
|
+
linked: true
|
108
|
+
}
|
109
|
+
env[:ui].info I18n.t('vagrant_parallels.actions.vm.clone.linked')
|
110
|
+
env[:machine].id = env[:machine].provider.driver.clone_vm(
|
111
|
+
env[:clone_id], opts) do |progress|
|
112
|
+
env[:ui].clear_line
|
113
|
+
env[:ui].report_progress(progress, 100, false)
|
157
114
|
end
|
158
115
|
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
def unregister_template(tpl_name)
|
164
|
-
@logger.info("Unregister the box template: '#{tpl_name}'")
|
165
|
-
@machine.provider.driver.unregister(tpl_name)
|
116
|
+
# Clear the line one last time since the progress meter doesn't disappear
|
117
|
+
# immediately.
|
118
|
+
env[:ui].clear_line
|
166
119
|
end
|
167
120
|
end
|
168
121
|
end
|