vagrant-libvirt 0.1.2 → 0.5.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 (72) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +530 -100
  3. data/lib/vagrant-libvirt/action.rb +7 -1
  4. data/lib/vagrant-libvirt/action/clean_machine_folder.rb +28 -0
  5. data/lib/vagrant-libvirt/action/create_domain.rb +78 -22
  6. data/lib/vagrant-libvirt/action/create_domain_volume.rb +57 -57
  7. data/lib/vagrant-libvirt/action/create_network_interfaces.rb +1 -3
  8. data/lib/vagrant-libvirt/action/create_networks.rb +11 -4
  9. data/lib/vagrant-libvirt/action/destroy_domain.rb +1 -1
  10. data/lib/vagrant-libvirt/action/forward_ports.rb +40 -40
  11. data/lib/vagrant-libvirt/action/halt_domain.rb +25 -9
  12. data/lib/vagrant-libvirt/action/handle_box_image.rb +163 -72
  13. data/lib/vagrant-libvirt/action/is_running.rb +1 -3
  14. data/lib/vagrant-libvirt/action/is_suspended.rb +4 -4
  15. data/lib/vagrant-libvirt/action/package_domain.rb +10 -4
  16. data/lib/vagrant-libvirt/action/start_domain.rb +86 -29
  17. data/lib/vagrant-libvirt/action/wait_till_up.rb +8 -52
  18. data/lib/vagrant-libvirt/cap/{mount_p9.rb → mount_9p.rb} +2 -2
  19. data/lib/vagrant-libvirt/cap/mount_virtiofs.rb +37 -0
  20. data/lib/vagrant-libvirt/cap/public_address.rb +16 -0
  21. data/lib/vagrant-libvirt/cap/{synced_folder.rb → synced_folder_9p.rb} +4 -5
  22. data/lib/vagrant-libvirt/cap/synced_folder_virtiofs.rb +109 -0
  23. data/lib/vagrant-libvirt/config.rb +257 -34
  24. data/lib/vagrant-libvirt/driver.rb +49 -32
  25. data/lib/vagrant-libvirt/errors.rb +24 -1
  26. data/lib/vagrant-libvirt/plugin.rb +19 -5
  27. data/lib/vagrant-libvirt/provider.rb +2 -9
  28. data/lib/vagrant-libvirt/templates/domain.xml.erb +40 -10
  29. data/lib/vagrant-libvirt/templates/private_network.xml.erb +1 -1
  30. data/lib/vagrant-libvirt/templates/public_interface.xml.erb +5 -1
  31. data/lib/vagrant-libvirt/util.rb +1 -0
  32. data/lib/vagrant-libvirt/util/erb_template.rb +6 -7
  33. data/lib/vagrant-libvirt/util/network_util.rb +21 -3
  34. data/lib/vagrant-libvirt/util/ui.rb +23 -0
  35. data/lib/vagrant-libvirt/version +1 -0
  36. data/lib/vagrant-libvirt/version.rb +72 -1
  37. data/locales/en.yml +12 -0
  38. data/spec/spec_helper.rb +37 -3
  39. data/spec/support/binding_proc.rb +24 -0
  40. data/spec/support/libvirt_context.rb +3 -1
  41. data/spec/support/matchers/have_file_content.rb +63 -0
  42. data/spec/support/sharedcontext.rb +7 -3
  43. data/spec/unit/action/clean_machine_folder_spec.rb +48 -0
  44. data/spec/unit/action/create_domain_spec.rb +166 -0
  45. data/spec/unit/action/create_domain_spec/default_system_storage_pool.xml +17 -0
  46. data/spec/unit/action/create_domain_spec/default_user_storage_pool.xml +17 -0
  47. data/spec/unit/action/create_domain_volume_spec.rb +102 -0
  48. data/spec/unit/action/create_domain_volume_spec/one_disk_in_storage.xml +21 -0
  49. data/spec/unit/action/create_domain_volume_spec/three_disks_in_storage_disk_0.xml +21 -0
  50. data/spec/unit/action/create_domain_volume_spec/three_disks_in_storage_disk_1.xml +21 -0
  51. data/spec/unit/action/create_domain_volume_spec/three_disks_in_storage_disk_2.xml +21 -0
  52. data/spec/unit/action/destroy_domain_spec.rb +3 -3
  53. data/spec/unit/action/forward_ports_spec.rb +202 -0
  54. data/spec/unit/action/halt_domain_spec.rb +90 -0
  55. data/spec/unit/action/handle_box_image_spec.rb +363 -0
  56. data/spec/unit/action/set_name_of_domain_spec.rb +2 -2
  57. data/spec/unit/action/start_domain_spec.rb +231 -0
  58. data/spec/unit/action/start_domain_spec/clock_timer_rtc.xml +50 -0
  59. data/spec/unit/action/start_domain_spec/default.xml +48 -0
  60. data/spec/unit/action/start_domain_spec/default_added_tpm_path.xml +48 -0
  61. data/spec/unit/action/start_domain_spec/default_added_tpm_version.xml +48 -0
  62. data/spec/unit/action/wait_till_up_spec.rb +22 -21
  63. data/spec/unit/config_spec.rb +438 -0
  64. data/spec/unit/provider_spec.rb +11 -0
  65. data/spec/unit/templates/domain_all_settings.xml +16 -3
  66. data/spec/unit/templates/domain_custom_cpu_model.xml +4 -1
  67. data/spec/unit/templates/domain_defaults.xml +4 -1
  68. data/spec/unit/templates/domain_spec.rb +102 -3
  69. data/spec/unit/templates/tpm/version_1.2.xml +54 -0
  70. data/spec/unit/templates/tpm/version_2.0.xml +53 -0
  71. metadata +108 -16
  72. data/lib/vagrant-libvirt/action/halt_confirm.rb +0 -20
@@ -0,0 +1,16 @@
1
+ module VagrantPlugins
2
+ module ProviderLibvirt
3
+ module Cap
4
+ class PublicAddress
5
+ def self.public_address(machine)
6
+ # This does not need to be a globally routable address, it
7
+ # only needs to be accessible from the machine running
8
+ # Vagrant.
9
+ ssh_info = machine.ssh_info
10
+ return nil if !ssh_info
11
+ ssh_info[:host]
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -6,10 +6,9 @@ require 'digest/md5'
6
6
  require 'vagrant/util/subprocess'
7
7
  require 'vagrant/errors'
8
8
  require 'vagrant-libvirt/errors'
9
- # require_relative "helper"
10
9
 
11
10
  module VagrantPlugins
12
- module SyncedFolder9p
11
+ module SyncedFolder9P
13
12
  class SyncedFolder < Vagrant.plugin('2', :synced_folder)
14
13
  include Vagrant::Util
15
14
  include VagrantPlugins::ProviderLibvirt::Util::ErbTemplate
@@ -69,10 +68,10 @@ module VagrantPlugins
69
68
  end
70
69
  end
71
70
 
72
- # TODO: once up, mount folders
71
+ # once up, mount folders
73
72
  def enable(machine, folders, _opts)
74
73
  # Go through each folder and mount
75
- machine.ui.info('mounting p9 share in guest')
74
+ machine.ui.info('mounting 9p share in guest')
76
75
  # Only mount folders that have a guest path specified.
77
76
  mount_folders = {}
78
77
  folders.each do |id, opts|
@@ -83,7 +82,7 @@ module VagrantPlugins
83
82
  end
84
83
  # Mount the actual folder
85
84
  machine.guest.capability(
86
- :mount_p9_shared_folder, mount_folders
85
+ :mount_9p_shared_folder, mount_folders
87
86
  )
88
87
  end
89
88
 
@@ -0,0 +1,109 @@
1
+ require 'log4r'
2
+ require 'ostruct'
3
+ require 'nokogiri'
4
+ require 'digest/md5'
5
+
6
+ require 'vagrant/util/subprocess'
7
+ require 'vagrant/errors'
8
+ require 'vagrant-libvirt/errors'
9
+
10
+ module VagrantPlugins
11
+ module SyncedFolderVirtioFS
12
+ class SyncedFolder < Vagrant.plugin('2', :synced_folder)
13
+ include Vagrant::Util
14
+ include VagrantPlugins::ProviderLibvirt::Util::ErbTemplate
15
+
16
+ def initialize(*args)
17
+ super
18
+ @logger = Log4r::Logger.new('vagrant_libvirt::synced_folders::virtiofs')
19
+ end
20
+
21
+ def usable?(machine, _raise_error = false)
22
+ # bail now if not using Libvirt since checking version would throw error
23
+ return false unless machine.provider_name == :libvirt
24
+
25
+ # virtiofs support introduced since 6.2.0
26
+ # version number format is major * 1,000,000 + minor * 1,000 + release
27
+ libvirt_version = machine.provider.driver.connection.client.libversion
28
+ libvirt_version >= 6_002_000
29
+ end
30
+
31
+ def prepare(machine, folders, _opts)
32
+ raise Vagrant::Errors::Error('No Libvirt connection') if machine.provider.driver.connection.nil?
33
+ @conn = machine.provider.driver.connection.client
34
+
35
+ begin
36
+ # loop through folders
37
+ folders.each do |id, folder_opts|
38
+ folder_opts.merge!(target: id,
39
+ mount: true,
40
+ readonly: nil) { |_k, ov, _nv| ov }
41
+
42
+ mount_tag = Digest::MD5.new.update(folder_opts[:hostpath]).to_s[0, 31]
43
+ folder_opts[:mount_tag] = mount_tag
44
+
45
+ machine.ui.info "================\nMachine id: #{machine.id}\nShould be mounting folders\n #{id}, opts: #{folder_opts}"
46
+
47
+ #xml = to_xml('filesystem', folder_opts)
48
+ xml = Nokogiri::XML::Builder.new do |xml|
49
+ xml.filesystem(type: 'mount', accessmode: 'passthrough') do
50
+ xml.driver(type: 'virtiofs')
51
+ xml.source(dir: folder_opts[:hostpath])
52
+ xml.target(dir: mount_tag)
53
+ xml.readonly unless folder_opts[:readonly].nil?
54
+ end
55
+ end.to_xml(
56
+ save_with: Nokogiri::XML::Node::SaveOptions::NO_DECLARATION |
57
+ Nokogiri::XML::Node::SaveOptions::NO_EMPTY_TAGS |
58
+ Nokogiri::XML::Node::SaveOptions::FORMAT
59
+ )
60
+ # puts "<<<<< XML:\n #{xml}\n >>>>>"
61
+ @conn.lookup_domain_by_uuid(machine.id).attach_device(xml, 0)
62
+ end
63
+ rescue => e
64
+ machine.ui.error("could not attach device because: #{e}")
65
+ raise VagrantPlugins::ProviderLibvirt::Errors::AttachDeviceError,
66
+ error_message: e.message
67
+ end
68
+ end
69
+
70
+ # once up, mount folders
71
+ def enable(machine, folders, _opts)
72
+ # Go through each folder and mount
73
+ machine.ui.info('mounting virtiofs share in guest')
74
+ # Only mount folders that have a guest path specified.
75
+ mount_folders = {}
76
+ folders.each do |id, opts|
77
+ next unless opts[:mount] && opts[:guestpath] && !opts[:guestpath].empty?
78
+ mount_folders[id] = opts.dup
79
+ end
80
+ # Mount the actual folder
81
+ machine.guest.capability(
82
+ :mount_virtiofs_shared_folder, mount_folders
83
+ )
84
+ end
85
+
86
+ def cleanup(machine, _opts)
87
+ if machine.provider.driver.connection.nil?
88
+ raise Vagrant::Errors::Error('No Libvirt connection')
89
+ end
90
+ @conn = machine.provider.driver.connection.client
91
+ begin
92
+ if machine.id && machine.id != ''
93
+ dom = @conn.lookup_domain_by_uuid(machine.id)
94
+ Nokogiri::XML(dom.xml_desc).xpath(
95
+ '/domain/devices/filesystem'
96
+ ).each do |xml|
97
+ dom.detach_device(xml.to_s)
98
+ machine.ui.info 'Cleaned up shared folders'
99
+ end
100
+ end
101
+ rescue => e
102
+ machine.ui.error("could not detach device because: #{e}")
103
+ raise VagrantPlugins::ProviderLibvirt::Errors::DetachDeviceError,
104
+ error_message: e.message
105
+ end
106
+ end
107
+ end
108
+ end
109
+ end
@@ -37,6 +37,11 @@ module VagrantPlugins
37
37
  # ID SSH key file
38
38
  attr_accessor :id_ssh_key_file
39
39
 
40
+ attr_accessor :proxy_command
41
+
42
+ # Forward port with id 'ssh'
43
+ attr_accessor :forward_ssh_port
44
+
40
45
  # Libvirt storage pool name, where box image and instance snapshots will
41
46
  # be stored.
42
47
  attr_accessor :storage_pool_name
@@ -59,6 +64,7 @@ module VagrantPlugins
59
64
  attr_accessor :management_network_pci_bus
60
65
  attr_accessor :management_network_pci_slot
61
66
  attr_accessor :management_network_domain
67
+ attr_accessor :management_network_mtu
62
68
 
63
69
  # System connection information
64
70
  attr_accessor :system_uri
@@ -67,6 +73,8 @@ module VagrantPlugins
67
73
  attr_accessor :default_prefix
68
74
 
69
75
  # Domain specific settings used while creating new domain.
76
+ attr_accessor :title
77
+ attr_accessor :description
70
78
  attr_accessor :uuid
71
79
  attr_accessor :memory
72
80
  attr_accessor :nodeset
@@ -82,6 +90,8 @@ module VagrantPlugins
82
90
  attr_accessor :shares
83
91
  attr_accessor :features
84
92
  attr_accessor :features_hyperv
93
+ attr_accessor :clock_offset
94
+ attr_accessor :clock_timers
85
95
  attr_accessor :numa_nodes
86
96
  attr_accessor :loader
87
97
  attr_accessor :nvram
@@ -91,9 +101,10 @@ module VagrantPlugins
91
101
  attr_accessor :machine_virtual_size
92
102
  attr_accessor :disk_bus
93
103
  attr_accessor :disk_device
104
+ attr_accessor :disk_driver_opts
94
105
  attr_accessor :nic_model_type
95
106
  attr_accessor :nested
96
- attr_accessor :volume_cache
107
+ attr_accessor :volume_cache # deprecated, kept for backwards compatibility; use disk_driver
97
108
  attr_accessor :kernel
98
109
  attr_accessor :cmd_line
99
110
  attr_accessor :initrd
@@ -115,6 +126,13 @@ module VagrantPlugins
115
126
  attr_accessor :tpm_model
116
127
  attr_accessor :tpm_type
117
128
  attr_accessor :tpm_path
129
+ attr_accessor :tpm_version
130
+
131
+ # Configure the memballoon
132
+ attr_accessor :memballoon_enabled
133
+ attr_accessor :memballoon_model
134
+ attr_accessor :memballoon_pci_bus
135
+ attr_accessor :memballoon_pci_slot
118
136
 
119
137
  # Sets the max number of NICs that can be created
120
138
  # Default set to 8. Don't change the default unless you know
@@ -179,6 +197,9 @@ module VagrantPlugins
179
197
  @username = UNSET_VALUE
180
198
  @password = UNSET_VALUE
181
199
  @id_ssh_key_file = UNSET_VALUE
200
+ @socket = UNSET_VALUE
201
+ @proxy_command = UNSET_VALUE
202
+ @forward_ssh_port = UNSET_VALUE # forward port with id 'ssh'
182
203
  @storage_pool_name = UNSET_VALUE
183
204
  @snapshot_pool_name = UNSET_VALUE
184
205
  @random_hostname = UNSET_VALUE
@@ -192,11 +213,14 @@ module VagrantPlugins
192
213
  @management_network_pci_slot = UNSET_VALUE
193
214
  @management_network_pci_bus = UNSET_VALUE
194
215
  @management_network_domain = UNSET_VALUE
216
+ @management_network_mtu = UNSET_VALUE
195
217
 
196
218
  # System connection information
197
219
  @system_uri = UNSET_VALUE
198
220
 
199
221
  # Domain specific settings.
222
+ @title = UNSET_VALUE
223
+ @description = UNSET_VALUE
200
224
  @uuid = UNSET_VALUE
201
225
  @memory = UNSET_VALUE
202
226
  @nodeset = UNSET_VALUE
@@ -211,6 +235,8 @@ module VagrantPlugins
211
235
  @shares = UNSET_VALUE
212
236
  @features = UNSET_VALUE
213
237
  @features_hyperv = UNSET_VALUE
238
+ @clock_offset = UNSET_VALUE
239
+ @clock_timers = []
214
240
  @numa_nodes = UNSET_VALUE
215
241
  @loader = UNSET_VALUE
216
242
  @nvram = UNSET_VALUE
@@ -219,6 +245,7 @@ module VagrantPlugins
219
245
  @machine_virtual_size = UNSET_VALUE
220
246
  @disk_bus = UNSET_VALUE
221
247
  @disk_device = UNSET_VALUE
248
+ @disk_driver_opts = {}
222
249
  @nic_model_type = UNSET_VALUE
223
250
  @nested = UNSET_VALUE
224
251
  @volume_cache = UNSET_VALUE
@@ -241,6 +268,12 @@ module VagrantPlugins
241
268
  @tpm_model = UNSET_VALUE
242
269
  @tpm_type = UNSET_VALUE
243
270
  @tpm_path = UNSET_VALUE
271
+ @tpm_version = UNSET_VALUE
272
+
273
+ @memballoon_enabled = UNSET_VALUE
274
+ @memballoon_model = UNSET_VALUE
275
+ @memballoon_pci_bus = UNSET_VALUE
276
+ @memballoon_pci_slot = UNSET_VALUE
244
277
 
245
278
  @nic_adapter_count = UNSET_VALUE
246
279
 
@@ -369,10 +402,39 @@ module VagrantPlugins
369
402
  raise 'Feature name AND state must be specified'
370
403
  end
371
404
 
405
+ if options[:name] == 'spinlocks' && options[:retries].nil?
406
+ raise 'Feature spinlocks requires retries parameter'
407
+ end
408
+
372
409
  @features_hyperv = [] if @features_hyperv == UNSET_VALUE
373
410
 
374
- @features_hyperv.push(name: options[:name],
375
- state: options[:state])
411
+ if options[:name] == 'spinlocks'
412
+ @features_hyperv.push(name: options[:name],
413
+ state: options[:state],
414
+ retries: options[:retries])
415
+ else
416
+ @features_hyperv.push(name: options[:name],
417
+ state: options[:state])
418
+ end
419
+ end
420
+
421
+ def clock_timer(options = {})
422
+ if options[:name].nil?
423
+ raise 'Clock timer name must be specified'
424
+ end
425
+
426
+ options.each do |key, value|
427
+ case key
428
+ when :name, :track, :tickpolicy, :frequency, :mode, :present
429
+ if value.nil?
430
+ raise "Value of timer option #{key} is nil"
431
+ end
432
+ else
433
+ raise "Unknown clock timer option: #{key}"
434
+ end
435
+ end
436
+
437
+ @clock_timers.push(options.dup)
376
438
  end
377
439
 
378
440
  def cputopology(options = {})
@@ -547,6 +609,12 @@ module VagrantPlugins
547
609
  @smartcard_dev[:source_service] = options[:source_service] if @smartcard_dev[:type] == 'tcp'
548
610
  end
549
611
 
612
+ # Disk driver options for primary disk
613
+ def disk_driver(options = {})
614
+ supported_opts = [:cache, :io, :copy_on_read, :discard, :detect_zeroes]
615
+ @disk_driver_opts = options.select { |k,_| supported_opts.include? k }
616
+ end
617
+
550
618
  # NOTE: this will run twice for each time it's needed- keep it idempotent
551
619
  def storage(storage_type, options = {})
552
620
  if storage_type == :file
@@ -570,11 +638,13 @@ module VagrantPlugins
570
638
  # as will the address unit number (unit=0, unit=1, etc)
571
639
 
572
640
  options = {
641
+ type: 'raw',
573
642
  bus: 'ide',
574
643
  path: nil
575
644
  }.merge(options)
576
645
 
577
646
  cdrom = {
647
+ type: options[:type],
578
648
  dev: options[:dev],
579
649
  bus: options[:bus],
580
650
  path: options[:path]
@@ -600,7 +670,13 @@ module VagrantPlugins
600
670
  cache: options[:cache] || 'default',
601
671
  allow_existing: options[:allow_existing],
602
672
  shareable: options[:shareable],
603
- serial: options[:serial]
673
+ serial: options[:serial],
674
+ io: options[:io],
675
+ copy_on_read: options[:copy_on_read],
676
+ discard: options[:discard],
677
+ detect_zeroes: options[:detect_zeroes],
678
+ pool: options[:pool], # overrides storage_pool setting for additional disks
679
+ wwn: options[:wwn],
604
680
  }
605
681
 
606
682
  @disks << disk # append
@@ -618,14 +694,31 @@ module VagrantPlugins
618
694
  @qemu_env.merge!(options)
619
695
  end
620
696
 
621
- # code to generate URI from a config moved out of the connect action
622
- def _generate_uri
697
+ def _default_uri
698
+ # Determine if any settings except driver provided explicitly, if not
699
+ # and the LIBVIRT_DEFAULT_URI var is set, use that.
700
+ #
701
+ # Skipping driver because that may be set on individual boxes rather
702
+ # than by the user.
703
+ if [
704
+ @connect_via_ssh, @host, @username, @password,
705
+ @id_ssh_key_file, @qemu_use_session, @socket,
706
+ ].none?{ |v| v != UNSET_VALUE }
707
+ if ENV.fetch('LIBVIRT_DEFAULT_URI', '') != ""
708
+ @uri = ENV['LIBVIRT_DEFAULT_URI']
709
+ end
710
+ end
711
+ end
712
+
713
+ # code to generate URI from from either the LIBVIRT_URI environment
714
+ # variable or a config moved out of the connect action
715
+ def _generate_uri(qemu_use_session)
623
716
  # builds the Libvirt connection URI from the given driver config
624
717
  # Setup connection uri.
625
718
  uri = @driver.dup
626
719
  virt_path = case uri
627
720
  when 'qemu', 'kvm'
628
- @qemu_use_session ? '/session' : '/system'
721
+ qemu_use_session ? '/session' : '/system'
629
722
  when 'openvz', 'uml', 'phyp', 'parallels'
630
723
  '/system'
631
724
  when '@en', 'esx'
@@ -639,42 +732,65 @@ module VagrantPlugins
639
732
  uri = 'qemu' # use QEMU uri for KVM domain type
640
733
  end
641
734
 
642
- if @connect_via_ssh
735
+ # turn on ssh if an ssh key file is explicitly provided
736
+ if @connect_via_ssh == UNSET_VALUE && @id_ssh_key_file && @id_ssh_key_file != UNSET_VALUE
737
+ @connect_via_ssh = true
738
+ end
739
+
740
+ params = {}
741
+
742
+ if @connect_via_ssh == true
743
+ finalize_id_ssh_key_file
744
+
643
745
  uri << '+ssh://'
644
- uri << @username + '@' if @username
746
+ uri << @username + '@' if @username && @username != UNSET_VALUE
645
747
 
646
- uri << if @host
647
- @host
648
- else
649
- 'localhost'
650
- end
748
+ uri << ( @host && @host != UNSET_VALUE ? @host : 'localhost' )
749
+
750
+ params['no_verify'] = '1'
751
+ params['keyfile'] = @id_ssh_key_file if @id_ssh_key_file
651
752
  else
652
753
  uri << '://'
653
- uri << @host if @host
754
+ uri << @host if @host && @host != UNSET_VALUE
654
755
  end
655
756
 
656
757
  uri << virt_path
657
- uri << '?no_verify=1'
658
758
 
659
- if @id_ssh_key_file
660
- # set ssh key for access to Libvirt host
661
- uri << "\&keyfile="
662
- # if no slash, prepend $HOME/.ssh/
663
- @id_ssh_key_file.prepend("#{`echo ${HOME}`.chomp}/.ssh/") if @id_ssh_key_file !~ /\A\//
664
- uri << @id_ssh_key_file
665
- end
666
759
  # set path to Libvirt socket
667
- uri << "\&socket=" + @socket if @socket
760
+ params['socket'] = @socket if @socket
761
+
762
+ uri << "?" + params.map{|pair| pair.join('=')}.join('&') if !params.empty?
668
763
  uri
669
764
  end
670
765
 
766
+ def _parse_uri(uri)
767
+ begin
768
+ URI.parse(uri)
769
+ rescue
770
+ raise "@uri set to invalid uri '#{uri}'"
771
+ end
772
+ end
773
+
671
774
  def finalize!
775
+ _default_uri if @uri == UNSET_VALUE
776
+
777
+ # settings which _generate_uri
672
778
  @driver = 'kvm' if @driver == UNSET_VALUE
673
- @host = nil if @host == UNSET_VALUE
674
- @connect_via_ssh = false if @connect_via_ssh == UNSET_VALUE
675
- @username = nil if @username == UNSET_VALUE
676
779
  @password = nil if @password == UNSET_VALUE
677
- @id_ssh_key_file = 'id_rsa' if @id_ssh_key_file == UNSET_VALUE
780
+ @socket = nil if @socket == UNSET_VALUE
781
+
782
+ # If uri isn't set then let's build one from various sources.
783
+ # Default to passing false for qemu_use_session if it's not set.
784
+ if @uri == UNSET_VALUE
785
+ @uri = _generate_uri(@qemu_use_session == UNSET_VALUE ? false : @qemu_use_session)
786
+ end
787
+
788
+ finalize_from_uri
789
+ finalize_proxy_command
790
+
791
+ # forward port with id 'ssh'
792
+ @forward_ssh_port = false if @forward_ssh_port == UNSET_VALUE
793
+
678
794
  @storage_pool_name = 'default' if @storage_pool_name == UNSET_VALUE
679
795
  @snapshot_pool_name = @storage_pool_name if @snapshot_pool_name == UNSET_VALUE
680
796
  @storage_pool_path = nil if @storage_pool_path == UNSET_VALUE
@@ -689,14 +805,12 @@ module VagrantPlugins
689
805
  @management_network_pci_bus = nil if @management_network_pci_bus == UNSET_VALUE
690
806
  @management_network_pci_slot = nil if @management_network_pci_slot == UNSET_VALUE
691
807
  @management_network_domain = nil if @management_network_domain == UNSET_VALUE
808
+ @management_network_mtu = nil if @management_network_mtu == UNSET_VALUE
692
809
  @system_uri = 'qemu:///system' if @system_uri == UNSET_VALUE
693
810
 
694
- @qemu_use_session = false if @qemu_use_session == UNSET_VALUE
695
-
696
- # generate a URI if none is supplied
697
- @uri = _generate_uri if @uri == UNSET_VALUE
698
-
699
811
  # Domain specific settings.
812
+ @title = '' if @title == UNSET_VALUE
813
+ @description = '' if @description == UNSET_VALUE
700
814
  @uuid = '' if @uuid == UNSET_VALUE
701
815
  @memory = 512 if @memory == UNSET_VALUE
702
816
  @nodeset = nil if @nodeset == UNSET_VALUE
@@ -717,6 +831,8 @@ module VagrantPlugins
717
831
  @shares = nil if @shares == UNSET_VALUE
718
832
  @features = ['acpi','apic','pae'] if @features == UNSET_VALUE
719
833
  @features_hyperv = [] if @features_hyperv == UNSET_VALUE
834
+ @clock_offset = 'utc' if @clock_offset == UNSET_VALUE
835
+ @clock_timers = [] if @clock_timers == UNSET_VALUE
720
836
  @numa_nodes = @numa_nodes == UNSET_VALUE ? nil : _generate_numa
721
837
  @loader = nil if @loader == UNSET_VALUE
722
838
  @nvram = nil if @nvram == UNSET_VALUE
@@ -725,9 +841,10 @@ module VagrantPlugins
725
841
  @machine_virtual_size = nil if @machine_virtual_size == UNSET_VALUE
726
842
  @disk_bus = 'virtio' if @disk_bus == UNSET_VALUE
727
843
  @disk_device = 'vda' if @disk_device == UNSET_VALUE
844
+ @disk_driver_opts = {} if @disk_driver_opts == UNSET_VALUE
728
845
  @nic_model_type = nil if @nic_model_type == UNSET_VALUE
729
846
  @nested = false if @nested == UNSET_VALUE
730
- @volume_cache = 'default' if @volume_cache == UNSET_VALUE
847
+ @volume_cache = nil if @volume_cache == UNSET_VALUE
731
848
  @kernel = nil if @kernel == UNSET_VALUE
732
849
  @cmd_line = '' if @cmd_line == UNSET_VALUE
733
850
  @initrd = '' if @initrd == UNSET_VALUE
@@ -749,6 +866,11 @@ module VagrantPlugins
749
866
  @tpm_model = 'tpm-tis' if @tpm_model == UNSET_VALUE
750
867
  @tpm_type = 'passthrough' if @tpm_type == UNSET_VALUE
751
868
  @tpm_path = nil if @tpm_path == UNSET_VALUE
869
+ @tpm_version = nil if @tpm_version == UNSET_VALUE
870
+ @memballoon_enabled = nil if @memballoon_enabled == UNSET_VALUE
871
+ @memballoon_model = 'virtio' if @memballoon_model == UNSET_VALUE
872
+ @memballoon_pci_bus = '0x00' if @memballoon_pci_bus == UNSET_VALUE
873
+ @memballoon_pci_slot = '0x0f' if @memballoon_pci_slot == UNSET_VALUE
752
874
  @nic_adapter_count = 8 if @nic_adapter_count == UNSET_VALUE
753
875
  @emulator_path = nil if @emulator_path == UNSET_VALUE
754
876
 
@@ -814,6 +936,14 @@ module VagrantPlugins
814
936
  def validate(machine)
815
937
  errors = _detected_errors
816
938
 
939
+ # The @uri and @qemu_use_session should not conflict
940
+ uri = _parse_uri(@uri)
941
+ if (uri.scheme.start_with? "qemu") && (uri.path.include? "session")
942
+ if @qemu_use_session != true
943
+ errors << "the URI and qemu_use_session configuration conflict: uri:'#{@uri}' qemu_use_session:'#{@qemu_use_session}'"
944
+ end
945
+ end
946
+
817
947
  machine.provider_config.disks.each do |disk|
818
948
  if disk[:path] && (disk[:path][0] == '/')
819
949
  errors << "absolute volume paths like '#{disk[:path]}' not yet supported"
@@ -832,6 +962,14 @@ module VagrantPlugins
832
962
  end
833
963
  end
834
964
 
965
+ if !machine.provider_config.volume_cache.nil? and machine.provider_config.volume_cache != UNSET_VALUE
966
+ machine.ui.warn("Libvirt Provider: volume_cache is deprecated. Use disk_driver :cache => '#{machine.provider_config.volume_cache}' instead.")
967
+
968
+ if !machine.provider_config.disk_driver_opts.empty?
969
+ machine.ui.warn("Libvirt Provider: volume_cache has no effect when disk_driver is defined.")
970
+ end
971
+ end
972
+
835
973
  { 'Libvirt Provider' => errors }
836
974
  end
837
975
 
@@ -845,11 +983,96 @@ module VagrantPlugins
845
983
  c += other.cdroms
846
984
  result.cdroms = c
847
985
 
986
+ result.disk_driver_opts = disk_driver_opts.merge(other.disk_driver_opts)
987
+
988
+ c = clock_timers.dup
989
+ c += other.clock_timers
990
+ result.clock_timers = c
991
+
848
992
  c = qemu_env != UNSET_VALUE ? qemu_env.dup : {}
849
993
  c.merge!(other.qemu_env) if other.qemu_env != UNSET_VALUE
850
994
  result.qemu_env = c
851
995
  end
852
996
  end
997
+
998
+ private
999
+
1000
+ def finalize_from_uri
1001
+ # Parse uri to extract individual components
1002
+ uri = _parse_uri(@uri)
1003
+
1004
+ # only set @connect_via_ssh if not explicitly to avoid overriding
1005
+ # and allow an error to occur if the @uri and @connect_via_ssh disagree
1006
+ @connect_via_ssh = uri.scheme.include? "ssh" if @connect_via_ssh == UNSET_VALUE
1007
+
1008
+ # Set qemu_use_session based on the URI if it wasn't set by the user
1009
+ if @qemu_use_session == UNSET_VALUE
1010
+ if (uri.scheme.start_with? "qemu") && (uri.path.include? "session")
1011
+ @qemu_use_session = true
1012
+ else
1013
+ @qemu_use_session = false
1014
+ end
1015
+ end
1016
+
1017
+ # Extract host and username values from uri if provided, otherwise nil
1018
+ @host = uri.host
1019
+ @username = uri.user
1020
+
1021
+ finalize_id_ssh_key_file
1022
+ end
1023
+
1024
+ def resolve_ssh_key_file(key_file)
1025
+ # set ssh key for access to Libvirt host
1026
+ # if no slash, prepend $HOME/.ssh/
1027
+ key_file.prepend("#{ENV['HOME']}/.ssh/") if key_file && key_file !~ /\A\//
1028
+
1029
+ key_file
1030
+ end
1031
+
1032
+ def finalize_id_ssh_key_file
1033
+ # resolve based on the following roles
1034
+ # 1) if @connect_via_ssh is set to true, and id_ssh_key_file not current set,
1035
+ # set default if the file exists
1036
+ # 2) if supplied the key name, attempt to expand based on user home
1037
+ # 3) otherwise set to nil
1038
+
1039
+ if @connect_via_ssh == true && @id_ssh_key_file == UNSET_VALUE
1040
+ # set default if using ssh while allowing a user using nil to disable this
1041
+ id_ssh_key_file = resolve_ssh_key_file('id_rsa')
1042
+ id_ssh_key_file = nil if !File.file?(id_ssh_key_file)
1043
+ elsif @id_ssh_key_file != UNSET_VALUE
1044
+ id_ssh_key_file = resolve_ssh_key_file(@id_ssh_key_file)
1045
+ else
1046
+ id_ssh_key_file = nil
1047
+ end
1048
+
1049
+ @id_ssh_key_file = id_ssh_key_file
1050
+ end
1051
+
1052
+ def finalize_proxy_command
1053
+ if @connect_via_ssh
1054
+ if @proxy_command == UNSET_VALUE
1055
+ proxy_command = "ssh '#{@host}' "
1056
+ proxy_command << "-l '#{@username}' " if @username
1057
+ proxy_command << "-i '#{@id_ssh_key_file}' " if @id_ssh_key_file
1058
+ proxy_command << '-W %h:%p'
1059
+ else
1060
+ inputs = { host: @host }
1061
+ inputs[:username] = @username if @username
1062
+ inputs[:id_ssh_key_file] = @id_ssh_key_file if @id_ssh_key_file
1063
+
1064
+ proxy_command = @proxy_command
1065
+ # avoid needing to escape '%' symbols
1066
+ inputs.each do |key, value|
1067
+ proxy_command.gsub!("{#{key}}", value)
1068
+ end
1069
+ end
1070
+
1071
+ @proxy_command = proxy_command
1072
+ else
1073
+ @proxy_command = nil
1074
+ end
1075
+ end
853
1076
  end
854
1077
  end
855
1078
  end