vagrant-libvirt 0.7.0 → 0.8.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.
Files changed (57) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +25 -9
  3. data/lib/vagrant-libvirt/action/cleanup_on_failure.rb +76 -0
  4. data/lib/vagrant-libvirt/action/create_domain.rb +45 -23
  5. data/lib/vagrant-libvirt/action/create_network_interfaces.rb +5 -1
  6. data/lib/vagrant-libvirt/action/create_networks.rb +13 -0
  7. data/lib/vagrant-libvirt/action/destroy_domain.rb +106 -21
  8. data/lib/vagrant-libvirt/action/destroy_networks.rb +1 -1
  9. data/lib/vagrant-libvirt/action/forward_ports.rb +12 -11
  10. data/lib/vagrant-libvirt/action/wait_till_up.rb +6 -32
  11. data/lib/vagrant-libvirt/action.rb +67 -80
  12. data/lib/vagrant-libvirt/config.rb +45 -33
  13. data/lib/vagrant-libvirt/driver.rb +3 -1
  14. data/lib/vagrant-libvirt/errors.rb +8 -0
  15. data/lib/vagrant-libvirt/templates/domain.xml.erb +223 -226
  16. data/lib/vagrant-libvirt/templates/private_network.xml.erb +4 -1
  17. data/lib/vagrant-libvirt/util/network_util.rb +13 -2
  18. data/lib/vagrant-libvirt/util/resolvers.rb +80 -0
  19. data/lib/vagrant-libvirt/version +1 -1
  20. data/locales/en.yml +13 -0
  21. data/spec/spec_helper.rb +33 -28
  22. data/spec/support/libvirt_context.rb +3 -3
  23. data/spec/unit/action/cleanup_on_failure_spec.rb +131 -0
  24. data/spec/unit/action/create_domain_spec/additional_disks_domain.xml +6 -18
  25. data/spec/unit/action/create_domain_spec/custom_disk_settings.xml +43 -0
  26. data/spec/unit/action/create_domain_spec/default_domain.xml +6 -18
  27. data/spec/unit/action/create_domain_spec/two_disk_settings.xml +49 -0
  28. data/spec/unit/action/create_domain_spec.rb +51 -7
  29. data/spec/unit/action/create_domain_volume_spec.rb +5 -3
  30. data/spec/unit/action/destroy_domain_spec/additional_disks_domain.xml +47 -0
  31. data/spec/unit/action/destroy_domain_spec/box_multiple_disks.xml +55 -0
  32. data/spec/unit/action/destroy_domain_spec/box_multiple_disks_and_additional_and_custom_disks.xml +72 -0
  33. data/spec/unit/action/destroy_domain_spec/box_multiple_disks_and_additional_and_custom_disks_no_aliases.xml +67 -0
  34. data/spec/unit/action/destroy_domain_spec/box_multiple_disks_and_additional_disks.xml +67 -0
  35. data/spec/unit/action/destroy_domain_spec/cdrom_domain.xml +48 -0
  36. data/spec/unit/action/destroy_domain_spec.rb +134 -30
  37. data/spec/unit/action/forward_ports_spec.rb +10 -2
  38. data/spec/unit/action/prepare_nfs_settings_spec.rb +4 -0
  39. data/spec/unit/action/start_domain_spec/clock_timer_rtc.xml +6 -18
  40. data/spec/unit/action/start_domain_spec/default.xml +6 -18
  41. data/spec/unit/action/start_domain_spec/default_added_tpm_path.xml +6 -18
  42. data/spec/unit/action/start_domain_spec/default_added_tpm_version.xml +6 -18
  43. data/spec/unit/action/start_domain_spec/existing.xml +1 -1
  44. data/spec/unit/action/wait_till_up_spec.rb +2 -42
  45. data/spec/unit/action_spec.rb +2 -0
  46. data/spec/unit/config_spec.rb +85 -26
  47. data/spec/unit/driver_spec.rb +17 -8
  48. data/spec/unit/provider_spec.rb +11 -0
  49. data/spec/unit/templates/domain_all_settings.xml +52 -79
  50. data/spec/unit/templates/domain_cpu_mode_passthrough.xml +39 -0
  51. data/spec/unit/templates/domain_custom_cpu_model.xml +6 -18
  52. data/spec/unit/templates/domain_defaults.xml +6 -18
  53. data/spec/unit/templates/domain_spec.rb +36 -13
  54. data/spec/unit/templates/tpm/version_1.2.xml +6 -18
  55. data/spec/unit/templates/tpm/version_2.0.xml +6 -18
  56. data/spec/unit/util/resolvers_spec.rb +116 -0
  57. metadata +62 -64
@@ -22,60 +22,34 @@ module VagrantPlugins
22
22
  # Initialize metrics if they haven't been
23
23
  env[:metrics] ||= {}
24
24
 
25
- # Get domain object
26
- domain = env[:machine].provider.driver.get_domain(env[:machine])
25
+ driver = env[:machine].provider.driver
26
+ domain = driver.get_domain(env[:machine])
27
+
27
28
  if domain.nil?
28
29
  raise Errors::NoDomainError,
29
30
  error_message: "Domain #{env[:machine].id} not found"
30
31
  end
31
32
 
32
- # Wait for domain to obtain an ip address. Ip address is searched
33
- # from arp table, either locally or remotely via ssh, if Libvirt
34
- # connection was done via ssh.
35
33
  env[:ip_address] = nil
36
34
  @logger.debug("Searching for IP for MAC address: #{domain.mac}")
37
35
  env[:ui].info(I18n.t('vagrant_libvirt.waiting_for_ip'))
38
36
 
37
+ # Wait for domain to obtain an ip address. Ip address is searched
38
+ # from dhcp leases table via libvirt, or via qemu agent if enabled.
39
39
  env[:metrics]['instance_ip_time'] = Util::Timer.time do
40
40
  retryable(on: Fog::Errors::TimeoutError, tries: 300) do
41
41
  # just return if interrupted and let the warden call recover
42
42
  return if env[:interrupted]
43
43
 
44
44
  # Wait for domain to obtain an ip address
45
- env[:ip_address] = env[:machine].provider.driver.get_domain_ipaddress(env[:machine], domain)
45
+ env[:ip_address] = driver.get_domain_ipaddress(env[:machine], domain)
46
46
  end
47
47
  end
48
-
49
48
  @logger.info("Got IP address #{env[:ip_address]}")
50
49
  @logger.info("Time for getting IP: #{env[:metrics]['instance_ip_time']}")
51
50
 
52
51
  @app.call(env)
53
52
  end
54
-
55
- def recover(env)
56
- # Undo the import
57
- terminate(env)
58
- end
59
-
60
- def terminate(env)
61
- if env[:machine].state.id != :not_created
62
- # If we're not supposed to destroy on error then just return
63
- return unless env[:destroy_on_error]
64
-
65
- if env[:halt_on_error]
66
- halt_env = env.dup
67
- halt_env.delete(:interrupted)
68
- halt_env[:config_validate] = false
69
- env[:action_runner].run(Action.action_halt, halt_env)
70
- else
71
- destroy_env = env.dup
72
- destroy_env.delete(:interrupted)
73
- destroy_env[:config_validate] = false
74
- destroy_env[:force_confirm_destroy] = true
75
- env[:action_runner].run(Action.action_destroy, destroy_env)
76
- end
77
- end
78
- end
79
53
  end
80
54
  end
81
55
  end
@@ -6,6 +6,58 @@ require 'log4r'
6
6
  module VagrantPlugins
7
7
  module ProviderLibvirt
8
8
  module Action
9
+ action_root = Pathname.new(File.expand_path('../action', __FILE__))
10
+ autoload :CleanupOnFailure, action_root.join('cleanup_on_failure')
11
+ autoload :ClearForwardedPorts, action_root.join('forward_ports')
12
+ autoload :CreateDomain, action_root.join('create_domain')
13
+ autoload :CreateDomainVolume, action_root.join('create_domain_volume')
14
+ autoload :CreateNetworkInterfaces, action_root.join('create_network_interfaces')
15
+ autoload :CreateNetworks, action_root.join('create_networks')
16
+ autoload :CleanMachineFolder, action_root.join('clean_machine_folder')
17
+ autoload :DestroyDomain, action_root.join('destroy_domain')
18
+ autoload :DestroyNetworks, action_root.join('destroy_networks')
19
+ autoload :ForwardPorts, action_root.join('forward_ports')
20
+ autoload :HaltDomain, action_root.join('halt_domain')
21
+ autoload :HandleBoxImage, action_root.join('handle_box_image')
22
+ autoload :HandleStoragePool, action_root.join('handle_storage_pool')
23
+ autoload :IsCreated, action_root.join('is_created')
24
+ autoload :IsRunning, action_root.join('is_running')
25
+ autoload :IsSuspended, action_root.join('is_suspended')
26
+ autoload :MessageAlreadyCreated, action_root.join('message_already_created')
27
+ autoload :MessageNotCreated, action_root.join('message_not_created')
28
+ autoload :MessageNotRunning, action_root.join('message_not_running')
29
+ autoload :MessageNotSuspended, action_root.join('message_not_suspended')
30
+ autoload :MessageWillNotDestroy, action_root.join('message_will_not_destroy')
31
+ autoload :PackageDomain, action_root.join('package_domain')
32
+ autoload :PrepareNFSSettings, action_root.join('prepare_nfs_settings')
33
+ autoload :PrepareNFSValidIds, action_root.join('prepare_nfs_valid_ids')
34
+ autoload :PruneNFSExports, action_root.join('prune_nfs_exports')
35
+ autoload :ReadMacAddresses, action_root.join('read_mac_addresses')
36
+ autoload :RemoveLibvirtImage, action_root.join('remove_libvirt_image')
37
+ autoload :RemoveStaleVolume, action_root.join('remove_stale_volume')
38
+ autoload :ResumeDomain, action_root.join('resume_domain')
39
+ autoload :SetNameOfDomain, action_root.join('set_name_of_domain')
40
+ autoload :SetBootOrder, action_root.join('set_boot_order')
41
+ autoload :SetupComplete, action_root.join('cleanup_on_failure')
42
+ # I don't think we need it anymore
43
+ autoload :ShareFolders, action_root.join('share_folders')
44
+ autoload :ShutdownDomain, action_root.join('shutdown_domain')
45
+ autoload :StartDomain, action_root.join('start_domain')
46
+ autoload :StartShutdownTimer, action_root.join('shutdown_domain')
47
+ autoload :SuspendDomain, action_root.join('suspend_domain')
48
+ autoload :TimedProvision, action_root.join('timed_provision')
49
+ autoload :WaitTillUp, action_root.join('wait_till_up')
50
+
51
+ autoload :HandleBox, 'vagrant/action/builtin/handle_box'
52
+ autoload :Package, 'vagrant/action/general/package'
53
+ autoload :PackageSetupFiles, 'vagrant/action/general/package_setup_files'
54
+ autoload :PackageSetupFolders, 'vagrant/action/general/package_setup_folders'
55
+ autoload :ProvisionerCleanup, 'vagrant/action/builtin/provisioner_cleanup'
56
+ autoload :SSHRun, 'vagrant/action/builtin/ssh_run'
57
+ autoload :SyncedFolderCleanup, 'vagrant/action/builtin/synced_folder_cleanup'
58
+ autoload :SyncedFolders, 'vagrant/action/builtin/synced_folders'
59
+ autoload :WaitForCommunicator, 'vagrant/action/builtin/wait_for_communicator'
60
+
9
61
  # Include the built-in & general modules so we can use them as top-level things.
10
62
  include Vagrant::Action::Builtin
11
63
  include Vagrant::Action::General
@@ -24,6 +76,8 @@ module VagrantPlugins
24
76
  b.use ConfigValidate
25
77
  b.use BoxCheckOutdated
26
78
  b.use Call, IsCreated do |env, b2|
79
+ b2.use CleanupOnFailure
80
+
27
81
  # Create VM if not yet created.
28
82
  if !env[:result]
29
83
  b2.use SetNameOfDomain
@@ -31,37 +85,31 @@ module VagrantPlugins
31
85
  b2.use CreateDomain
32
86
  b2.use CreateNetworks
33
87
  b2.use CreateNetworkInterfaces
34
- b2.use SetBootOrder
35
- b2.use StartDomain
88
+
89
+ b2.use action_start
90
+
91
+ b2.use SetupComplete
36
92
  else
37
93
  b2.use HandleStoragePool
38
94
  b2.use HandleBox
39
95
  b2.use HandleBoxImage
40
96
  b2.use CreateDomainVolume
41
97
  b2.use CreateDomain
42
-
43
- b2.use Provision
44
- b2.use PrepareNFSValidIds
45
- b2.use SyncedFolderCleanup
46
- b2.use SyncedFolders
47
- b2.use PrepareNFSSettings
48
- b2.use ShareFolders
49
98
  b2.use CreateNetworks
50
99
  b2.use CreateNetworkInterfaces
51
- b2.use SetBootOrder
52
100
 
53
- b2.use StartDomain
54
- b2.use WaitTillUp
55
- b2.use WaitForCommunicator, [:running]
101
+ b2.use action_start
56
102
 
57
- b2.use ForwardPorts
58
103
  b2.use SetHostname
59
- # b2.use SyncFolders
60
104
  end
61
105
  else
62
106
  env[:halt_on_error] = true
107
+ b2.use CreateNetworks
63
108
  b2.use action_start
64
109
  end
110
+
111
+ # corresponding action to CleanupOnFailure
112
+ b2.use SetupComplete
65
113
  end
66
114
  end
67
115
  end
@@ -82,28 +130,25 @@ module VagrantPlugins
82
130
  b2.use Call, IsSuspended do |env2, b3|
83
131
  # if vm is suspended resume it then exit
84
132
  if env2[:result]
85
- b3.use CreateNetworks
86
133
  b3.use ResumeDomain
87
134
  next
88
135
  end
89
136
 
90
137
  if !env[:machine].config.vm.box
91
138
  # With no box, we just care about network creation and starting it
92
- b3.use CreateNetworks
93
139
  b3.use SetBootOrder
94
140
  b3.use StartDomain
95
141
  else
96
142
  # VM is not running or suspended.
97
-
98
143
  b3.use Provision
99
144
 
100
- # Ensure networks are created and active
101
- b3.use CreateNetworks
102
- b3.use SetBootOrder
103
-
104
145
  b3.use PrepareNFSValidIds
105
146
  b3.use SyncedFolderCleanup
106
147
  b3.use SyncedFolders
148
+ b3.use PrepareNFSSettings
149
+ b3.use ShareFolders
150
+
151
+ b3.use SetBootOrder
107
152
 
108
153
  # Start it..
109
154
  b3.use StartDomain
@@ -114,8 +159,6 @@ module VagrantPlugins
114
159
  b3.use WaitForCommunicator, [:running]
115
160
 
116
161
  b3.use ForwardPorts
117
- b3.use PrepareNFSSettings
118
- b3.use ShareFolders
119
162
  end
120
163
  end
121
164
  end
@@ -264,7 +307,6 @@ module VagrantPlugins
264
307
  end
265
308
 
266
309
  b3.use Provision
267
- # b3.use SyncFolders
268
310
  end
269
311
  end
270
312
  end
@@ -342,61 +384,6 @@ module VagrantPlugins
342
384
  end
343
385
  end
344
386
 
345
- action_root = Pathname.new(File.expand_path('../action', __FILE__))
346
- autoload :PackageDomain, action_root.join('package_domain')
347
- autoload :CreateDomain, action_root.join('create_domain')
348
- autoload :CreateDomainVolume, action_root.join('create_domain_volume')
349
- autoload :CreateNetworkInterfaces, action_root.join('create_network_interfaces')
350
- autoload :CreateNetworks, action_root.join('create_networks')
351
- autoload :CleanMachineFolder, action_root.join('clean_machine_folder')
352
- autoload :DestroyDomain, action_root.join('destroy_domain')
353
- autoload :DestroyNetworks, action_root.join('destroy_networks')
354
- autoload :ForwardPorts, action_root.join('forward_ports')
355
- autoload :ClearForwardedPorts, action_root.join('forward_ports')
356
- autoload :HaltDomain, action_root.join('halt_domain')
357
- autoload :StartShutdownTimer, action_root.join('shutdown_domain')
358
- autoload :ShutdownDomain, action_root.join('shutdown_domain')
359
- autoload :HandleBoxImage, action_root.join('handle_box_image')
360
- autoload :HandleStoragePool, action_root.join('handle_storage_pool')
361
- autoload :RemoveLibvirtImage, action_root.join('remove_libvirt_image')
362
- autoload :IsCreated, action_root.join('is_created')
363
- autoload :IsRunning, action_root.join('is_running')
364
- autoload :IsSuspended, action_root.join('is_suspended')
365
- autoload :MessageAlreadyCreated, action_root.join('message_already_created')
366
- autoload :MessageNotCreated, action_root.join('message_not_created')
367
- autoload :MessageNotRunning, action_root.join('message_not_running')
368
- autoload :MessageNotSuspended, action_root.join('message_not_suspended')
369
- autoload :MessageWillNotDestroy, action_root.join('message_will_not_destroy')
370
-
371
- autoload :RemoveStaleVolume, action_root.join('remove_stale_volume')
372
-
373
- autoload :PrepareNFSSettings, action_root.join('prepare_nfs_settings')
374
- autoload :PrepareNFSValidIds, action_root.join('prepare_nfs_valid_ids')
375
- autoload :PruneNFSExports, action_root.join('prune_nfs_exports')
376
-
377
- autoload :ReadMacAddresses, action_root.join('read_mac_addresses')
378
- autoload :ResumeDomain, action_root.join('resume_domain')
379
- autoload :SetNameOfDomain, action_root.join('set_name_of_domain')
380
- autoload :SetBootOrder, action_root.join('set_boot_order')
381
-
382
- # I don't think we need it anymore
383
- autoload :ShareFolders, action_root.join('share_folders')
384
- autoload :StartDomain, action_root.join('start_domain')
385
- autoload :SuspendDomain, action_root.join('suspend_domain')
386
- autoload :TimedProvision, action_root.join('timed_provision')
387
-
388
- autoload :WaitTillUp, action_root.join('wait_till_up')
389
- autoload :PrepareNFSValidIds, action_root.join('prepare_nfs_valid_ids')
390
-
391
- autoload :Package, 'vagrant/action/general/package'
392
- autoload :PackageSetupFiles, 'vagrant/action/general/package_setup_files'
393
- autoload :PackageSetupFolders, 'vagrant/action/general/package_setup_folders'
394
- autoload :SSHRun, 'vagrant/action/builtin/ssh_run'
395
- autoload :HandleBox, 'vagrant/action/builtin/handle_box'
396
- autoload :SyncedFolders, 'vagrant/action/builtin/synced_folders'
397
- autoload :SyncedFolderCleanup, 'vagrant/action/builtin/synced_folder_cleanup'
398
- autoload :ProvisionerCleanup, 'vagrant/action/builtin/provisioner_cleanup'
399
- autoload :WaitForCommunicator, 'vagrant/action/builtin/wait_for_communicator'
400
387
  end
401
388
  end
402
389
  end
@@ -4,15 +4,8 @@ require 'cgi'
4
4
 
5
5
  require 'vagrant'
6
6
 
7
- class Numeric
8
- Alphabet = ('a'..'z').to_a
9
- def vdev
10
- s = String.new
11
- q = self
12
- (q, r = (q - 1).divmod(26)) && s.prepend(Alphabet[r]) until q.zero?
13
- "vd#{s}"
14
- end
15
- end
7
+ require 'vagrant-libvirt/errors'
8
+ require 'vagrant-libvirt/util/resolvers'
16
9
 
17
10
  module VagrantPlugins
18
11
  module ProviderLibvirt
@@ -69,6 +62,7 @@ module VagrantPlugins
69
62
  attr_accessor :management_network_pci_slot
70
63
  attr_accessor :management_network_domain
71
64
  attr_accessor :management_network_mtu
65
+ attr_accessor :management_network_keep
72
66
 
73
67
  # System connection information
74
68
  attr_accessor :system_uri
@@ -227,6 +221,7 @@ module VagrantPlugins
227
221
  @management_network_pci_bus = UNSET_VALUE
228
222
  @management_network_domain = UNSET_VALUE
229
223
  @management_network_mtu = UNSET_VALUE
224
+ @management_network_keep = UNSET_VALUE
230
225
 
231
226
  # System connection information
232
227
  @system_uri = UNSET_VALUE
@@ -346,24 +341,13 @@ module VagrantPlugins
346
341
  # Use Qemu agent to get ip address
347
342
  @qemu_use_agent = UNSET_VALUE
348
343
 
349
- @serials = []
344
+ @serials = UNSET_VALUE
350
345
  end
351
346
 
352
347
  def boot(device)
353
348
  @boot_order << device # append
354
349
  end
355
350
 
356
- def _get_device(disks)
357
- # skip existing devices and also the first one (vda)
358
- exist = disks.collect { |x| x[:device] } + [1.vdev.to_s]
359
- skip = 1 # we're 1 based, not 0 based...
360
- loop do
361
- dev = skip.vdev # get lettered device
362
- return dev unless exist.include?(dev)
363
- skip += 1
364
- end
365
- end
366
-
367
351
  def _get_cdrom_dev(cdroms)
368
352
  exist = Hash[cdroms.collect { |x| [x[:dev], true] }]
369
353
  # hda - hdc
@@ -516,7 +500,9 @@ module VagrantPlugins
516
500
  target_address: options[:target_address],
517
501
  target_name: options[:target_name],
518
502
  target_port: options[:target_port],
519
- target_type: options[:target_type])
503
+ target_type: options[:target_type],
504
+ disabled: options[:disabled],
505
+ )
520
506
  end
521
507
 
522
508
  def random(options = {})
@@ -715,6 +701,8 @@ module VagrantPlugins
715
701
  end
716
702
 
717
703
  def serial(options={})
704
+ @serials = [] if @serials == UNSET_VALUE
705
+
718
706
  options = {
719
707
  :type => "pty",
720
708
  :source => nil,
@@ -840,6 +828,7 @@ module VagrantPlugins
840
828
  @management_network_pci_slot = nil if @management_network_pci_slot == UNSET_VALUE
841
829
  @management_network_domain = nil if @management_network_domain == UNSET_VALUE
842
830
  @management_network_mtu = nil if @management_network_mtu == UNSET_VALUE
831
+ @management_network_keep = false if @management_network_keep == UNSET_VALUE
843
832
 
844
833
  # Domain specific settings.
845
834
  @title = '' if @title == UNSET_VALUE
@@ -892,7 +881,7 @@ module VagrantPlugins
892
881
  @graphics_port = -1 if @graphics_port == UNSET_VALUE
893
882
  @graphics_ip = '127.0.0.1' if @graphics_ip == UNSET_VALUE
894
883
  @video_type = 'cirrus' if @video_type == UNSET_VALUE
895
- @video_vram = 9216 if @video_vram == UNSET_VALUE
884
+ @video_vram = 16384 if @video_vram == UNSET_VALUE
896
885
  @video_accel3d = false if @video_accel3d == UNSET_VALUE
897
886
  @graphics_gl = @video_accel3d if @graphics_gl == UNSET_VALUE
898
887
  @sound_type = nil if @sound_type == UNSET_VALUE
@@ -914,10 +903,6 @@ module VagrantPlugins
914
903
 
915
904
  # Storage
916
905
  @disks = [] if @disks == UNSET_VALUE
917
- @disks.map! do |disk|
918
- disk[:device] = _get_device(@disks) if disk[:device].nil?
919
- disk
920
- end
921
906
  @cdroms = [] if @cdroms == UNSET_VALUE
922
907
  @cdroms.map! do |cdrom|
923
908
  cdrom[:dev] = _get_cdrom_dev(@cdroms) if cdrom[:dev].nil?
@@ -928,7 +913,18 @@ module VagrantPlugins
928
913
  @inputs = [{ type: 'mouse', bus: 'ps2' }] if @inputs == UNSET_VALUE
929
914
 
930
915
  # Channels
931
- @channels = [] if @channels == UNSET_VALUE
916
+ if @channels == UNSET_VALUE
917
+ @channels = []
918
+ if @qemu_use_agent == true
919
+ if @channels.all? { |channel| !channel.fetch(:target_name, '').start_with?('org.qemu.guest_agent.') }
920
+ channel(:type => 'unix', :target_name => 'org.qemu.guest_agent.0', :target_type => 'virtio')
921
+ end
922
+ end
923
+ end
924
+
925
+ # filter channels of anything explicitly disabled so it's possible to inject an entry to
926
+ # avoid the automatic addition of the guest_agent above, and disable it from subsequent use.
927
+ @channels = @channels.reject { |channel| channel[:disabled] }.tap {|channel| channel.delete(:disabled) }
932
928
 
933
929
  # PCI device passthrough
934
930
  @pcis = [] if @pcis == UNSET_VALUE
@@ -971,12 +967,17 @@ module VagrantPlugins
971
967
 
972
968
  @qemu_use_agent = false if @qemu_use_agent == UNSET_VALUE
973
969
 
974
- @serials = [{:type => 'pty', :source => nil}] if @serials == []
970
+ @serials = [{:type => 'pty', :source => nil}] if @serials == UNSET_VALUE
975
971
  end
976
972
 
977
973
  def validate(machine)
978
974
  errors = _detected_errors
979
975
 
976
+ # technically this shouldn't occur, but ensure that if somehow it does, it gets rejected.
977
+ if @cpu_mode == 'host-passthrough' && @cpu_model != ''
978
+ errors << "cannot set cpu_model with cpu_mode of 'host-passthrough'. leave model unset or switch mode."
979
+ end
980
+
980
981
  # The @uri and @qemu_use_session should not conflict
981
982
  uri = _parse_uri(@uri)
982
983
  if (uri.scheme.start_with? "qemu") && (uri.path.include? "session")
@@ -998,7 +999,6 @@ module VagrantPlugins
998
999
  end
999
1000
  end
1000
1001
 
1001
-
1002
1002
  machine.provider_config.disks.each do |disk|
1003
1003
  if disk[:path] && (disk[:path][0] == '/')
1004
1004
  errors << "absolute volume paths like '#{disk[:path]}' not yet supported"
@@ -1011,6 +1011,16 @@ module VagrantPlugins
1011
1011
  end
1012
1012
  end
1013
1013
 
1014
+ # this won't be able to fully resolve the disks until the box has
1015
+ # been downloaded and any devices that need to be assigned to the
1016
+ # disks contained have been allocated
1017
+ disk_resolver = ::VagrantPlugins::ProviderLibvirt::Util::DiskDeviceResolver.new
1018
+ begin
1019
+ disk_resolver.resolve(machine.provider_config.disks)
1020
+ rescue Errors::VagrantLibvirtError => e
1021
+ errors << "#{e}"
1022
+ end
1023
+
1014
1024
  machine.config.vm.networks.each do |_type, opts|
1015
1025
  if opts[:mac]
1016
1026
  if opts[:mac] =~ /\A([0-9a-fA-F]{12})\z/
@@ -1053,9 +1063,11 @@ module VagrantPlugins
1053
1063
  c.merge!(other.qemu_env) if other.qemu_env != UNSET_VALUE
1054
1064
  result.qemu_env = c
1055
1065
 
1056
- s = serials.dup
1057
- s += other.serials
1058
- result.serials = s
1066
+ if serials != UNSET_VALUE
1067
+ s = serials.dup
1068
+ s += other.serials
1069
+ result.serials = s
1070
+ end
1059
1071
  end
1060
1072
  end
1061
1073
 
@@ -135,7 +135,9 @@ module VagrantPlugins
135
135
  end
136
136
 
137
137
  # TODO: terminated no longer appears to be a valid fog state, remove?
138
- return :not_created if domain.nil? || domain.state.to_sym == :terminated
138
+ return :not_created if domain.nil?
139
+ return :unknown if domain.state.nil?
140
+ return :not_created if domain.state.to_sym == :terminated
139
141
 
140
142
  state = domain.state.tr('-', '_').to_sym
141
143
  if state == :running
@@ -18,6 +18,14 @@ module VagrantPlugins
18
18
  error_key(:package_not_supported)
19
19
  end
20
20
 
21
+ class DuplicateDiskDevice < VagrantLibvirtError
22
+ error_key(:duplicate_disk_device)
23
+ end
24
+
25
+ class NoDiskDeviceAvailable < VagrantLibvirtError
26
+ error_key(:no_disk_device_available)
27
+ end
28
+
21
29
  # Storage pools and volumes exceptions
22
30
  class NoStoragePool < VagrantLibvirtError
23
31
  error_key(:no_storage_pool)