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.
Files changed (38) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +7 -4
  3. data/CHANGELOG.md +33 -0
  4. data/Gemfile +2 -2
  5. data/README.md +1 -1
  6. data/debug.log +1237 -1
  7. data/lib/vagrant-parallels/action.rb +8 -0
  8. data/lib/vagrant-parallels/action/box_register.rb +113 -0
  9. data/lib/vagrant-parallels/action/box_unregister.rb +43 -0
  10. data/lib/vagrant-parallels/action/export.rb +36 -35
  11. data/lib/vagrant-parallels/action/forward_ports.rb +32 -18
  12. data/lib/vagrant-parallels/action/import.rb +59 -106
  13. data/lib/vagrant-parallels/action/network.rb +17 -13
  14. data/lib/vagrant-parallels/action/prepare_clone_snapshot.rb +67 -0
  15. data/lib/vagrant-parallels/action/set_name.rb +1 -1
  16. data/lib/vagrant-parallels/action/snapshot_delete.rb +25 -0
  17. data/lib/vagrant-parallels/action/snapshot_restore.rb +23 -0
  18. data/lib/vagrant-parallels/action/snapshot_save.rb +23 -0
  19. data/lib/vagrant-parallels/cap.rb +63 -0
  20. data/lib/vagrant-parallels/config.rb +7 -3
  21. data/lib/vagrant-parallels/driver/base.rb +61 -28
  22. data/lib/vagrant-parallels/driver/meta.rb +20 -10
  23. data/lib/vagrant-parallels/driver/pd_11.rb +0 -21
  24. data/lib/vagrant-parallels/errors.rb +14 -6
  25. data/lib/vagrant-parallels/guest_cap/darwin/install_parallels_tools.rb +34 -0
  26. data/lib/vagrant-parallels/plugin.rb +23 -8
  27. data/lib/vagrant-parallels/version.rb +1 -1
  28. data/locales/en.yml +31 -17
  29. data/test/acceptance/provider/linked_clone_spec.rb +6 -2
  30. data/test/acceptance/skeletons/linked_clone/Vagrantfile +1 -1
  31. data/test/unit/base.rb +1 -0
  32. data/test/unit/cap_test.rb +96 -0
  33. data/test/unit/support/shared/pd_driver_examples.rb +7 -10
  34. metadata +12 -6
  35. data/lib/vagrant-parallels/cap/forwarded_ports.rb +0 -22
  36. data/lib/vagrant-parallels/cap/host_address.rb +0 -15
  37. data/lib/vagrant-parallels/cap/nic_mac_addresses.rb +0 -17
  38. 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
- @tpl_name = gen_template_name
17
-
18
- export
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
- @env = env
27
- unregister_template
23
+ unregister_vm(env)
28
24
  end
29
25
 
30
26
  private
31
27
 
32
- def gen_template_name
28
+ def box_vm_name(env)
33
29
  # Use configured name if it is specified, or generate the new one
34
- name = @env[:machine].provider_config.name
30
+ name = env[:machine].provider_config.name
35
31
  if !name
36
- name = "#{@env[:root_path].basename.to_s}_#{@env[:machine].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
- tpl_name = "#{name}_box"
36
+ vm_name = "#{name}_box"
41
37
 
42
38
  # Ensure that the name is not in use
43
39
  ind = 0
44
- while @env[:machine].provider.driver.read_vms.has_key?(tpl_name)
40
+ while env[:machine].provider.driver.read_vms.has_key?(vm_name)
45
41
  ind += 1
46
- tpl_name = "#{name}_box_#{ind}"
42
+ vm_name = "#{name}_box_#{ind}"
47
43
  end
48
44
 
49
- tpl_name
45
+ vm_name
50
46
  end
51
47
 
52
- def export
53
- @env[:ui].info I18n.t('vagrant.actions.vm.export.exporting')
48
+ def clone(env)
49
+ env[:ui].info I18n.t('vagrant.actions.vm.export.exporting')
54
50
 
55
51
  options = {
56
- template: true,
57
- dst: @env['export.temp_dir'].to_s
52
+ dst: env['export.temp_dir'].to_s
58
53
  }
59
54
 
60
- @env[:machine].provider.driver.clone_vm(@env[:machine].id, @tpl_name, options) do |progress|
61
- @env[:ui].clear_line
62
- @env[:ui].report_progress(progress, 100, false)
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
- # # If we got interrupted, then the import could have been interrupted.
65
- # Just rise an exception and then 'recover' will be called to cleanup.
66
- raise Vagrant::Errors::VagrantInterrupt if @env[:interrupted]
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
- @env[:ui].clear_line
71
+ env[:ui].clear_line
72
72
  end
73
73
 
74
- def compact_template
75
- @env[:ui].info I18n.t('vagrant_parallels.actions.vm.export.compacting')
76
- @env[:machine].provider.driver.compact(@tpl_name) do |progress|
77
- @env[:ui].clear_line
78
- @env[:ui].report_progress(progress, 100, false)
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
- @env[:ui].clear_line
83
+ env[:ui].clear_line
84
84
  end
85
85
 
86
- def unregister_template
87
- @logger.info("Unregister the box template: '#{@tpl_name}'")
88
- @env[:machine].provider.driver.unregister(@tpl_name)
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
- env[:ui].output(I18n.t('vagrant.actions.vm.forward_ports.forwarding'))
25
- forward_ports
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: get_unique_name(fp.id),
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
- # Register template to be able to clone it further
24
- register_template(template_path.to_s)
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
- # Get template name. It might be changed during registration if name
27
- # collision has been occurred
28
- tpl_name = template_name(template_path)
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
- # Import VM, e.q. clone it from registered template
31
- import(env, tpl_name)
43
+ # Flag as erroneous and return if import failed
44
+ raise Errors::VMCloneFailure if !env[:machine].id
32
45
 
33
- # Hide template since we dont need it anymore
34
- unregister_template(tpl_name)
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
- # Flag as erroneous and return if import failed
37
- raise Errors::VMImportFailure if !@machine.id
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
- # We should to unregister template
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 register_template(tpl_path_s)
68
- @logger.info("Register the box template: '#{tpl_path_s}'")
69
- @machine.provider.driver.register(tpl_path_s)
70
- end
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 snapshot_id(tpl_name)
147
- snap_id = @machine.provider.driver.read_current_snapshot(tpl_name)
148
-
149
- # If there is no current snapshot, just create the new one.
150
- if !snap_id
151
- @logger.info('Create a new snapshot')
152
- opts = {
153
- name: 'vagrant_linked_clone',
154
- desc: 'Snapshot to create linked clones for Vagrant'
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
- @logger.info("User this snapshot ID to create a linked clone: #{snap_id}")
160
- snap_id
161
- end
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