vagrant-parallels 1.5.1 → 1.6.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.
- 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
|