vagrant-libvirt 0.11.2 → 0.12.1

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 (33) hide show
  1. checksums.yaml +4 -4
  2. data/lib/vagrant-libvirt/action/create_domain.rb +15 -1
  3. data/lib/vagrant-libvirt/action/create_domain_volume.rb +1 -0
  4. data/lib/vagrant-libvirt/action/create_network_interfaces.rb +8 -4
  5. data/lib/vagrant-libvirt/action/create_networks.rb +1 -1
  6. data/lib/vagrant-libvirt/action/destroy_domain_confirm.rb +22 -0
  7. data/lib/vagrant-libvirt/action/forward_ports.rb +1 -1
  8. data/lib/vagrant-libvirt/action/handle_box_image.rb +6 -3
  9. data/lib/vagrant-libvirt/action/start_domain.rb +38 -9
  10. data/lib/vagrant-libvirt/action.rb +0 -2
  11. data/lib/vagrant-libvirt/config.rb +78 -28
  12. data/lib/vagrant-libvirt/templates/domain.xml.erb +25 -14
  13. data/lib/vagrant-libvirt/templates/public_interface.xml.erb +22 -17
  14. data/lib/vagrant-libvirt/util/network_util.rb +27 -22
  15. data/lib/vagrant-libvirt/version +1 -1
  16. data/spec/support/libvirt_acceptance_context.rb +1 -1
  17. data/spec/support/matchers/have_file_content.rb +1 -1
  18. data/spec/support/unit_context.rb +0 -3
  19. data/spec/unit/action/clean_machine_folder_spec.rb +3 -3
  20. data/spec/unit/action/create_domain_volume_spec/one_disk_in_storage.xml +1 -0
  21. data/spec/unit/action/create_domain_volume_spec/three_disks_in_storage_disk_0.xml +1 -0
  22. data/spec/unit/action/create_domain_volume_spec/three_disks_in_storage_disk_1.xml +1 -0
  23. data/spec/unit/action/create_domain_volume_spec/three_disks_in_storage_disk_2.xml +1 -0
  24. data/spec/unit/action/create_network_interfaces.rb +355 -0
  25. data/spec/unit/action/handle_box_image_spec.rb +9 -2
  26. data/spec/unit/action/start_domain_spec.rb +42 -0
  27. data/spec/unit/action_spec.rb +62 -1
  28. data/spec/unit/cap/mount_9p_spec.rb +4 -0
  29. data/spec/unit/config_spec.rb +39 -10
  30. data/spec/unit/driver_spec.rb +29 -18
  31. data/spec/unit/templates/domain_all_settings.xml +2 -2
  32. data/spec/unit/templates/domain_spec.rb +2 -1
  33. metadata +5 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 40dbf1a78ed383e5c289059d869c281c778fee7414a0a1711849d9dcba16df52
4
- data.tar.gz: 2bf17eb2166d56a0386d6bbd70d6548d89def585aaf6f10c929f8afc546496bc
3
+ metadata.gz: 8ea176b68227366ddb6ac763a2e66c55cffaa58e9d4cc188f3f8b6c62bb3cd06
4
+ data.tar.gz: a8cfb80de7f57fbcd2e4bec2fdf7f7043a81f410da00606a5f88897374535baf
5
5
  SHA512:
6
- metadata.gz: e9fa89d429ae04d5375930e3bfec06d3cf2c152803e8dc6a3fcb9c4a8ac4e81e1bafe08639fe689e9535cf3889bb1fd548c196ebe064abbad1edbfd85619ce0f
7
- data.tar.gz: 4713ea077cc23984256c1a0ed55a67ec44c0a687f3a7c72916762a65807995c4fd5e1206f0ed86cc69008f8bf51a7cfff07b36f6947cd90bd29e136c2649c9f7
6
+ metadata.gz: 9b005c6323cee5bfe5facbe14d5b3f7acddd9076b428d126acd220080b5946107795eee6726893bdfc7e9e67b08534a8c475b9f1d6c8de79f79dcf8c125564e8
7
+ data.tar.gz: 257c7b4bf7c7390c0013101eb6541d43e2d60d871309053201376b5cfff5439610f5aacb05775b24b37ddc374b2d8dff4deab0a8163c4821a5f34c7c5d76ed35
@@ -36,7 +36,11 @@ module VagrantPlugins
36
36
  @nodeset = config.nodeset
37
37
  @features = config.features
38
38
  @features_hyperv = config.features_hyperv
39
+ @clock_absolute = config.clock_absolute
40
+ @clock_adjustment = config.clock_adjustment
41
+ @clock_basis = config.clock_basis
39
42
  @clock_offset = config.clock_offset
43
+ @clock_timezone = config.clock_timezone
40
44
  @clock_timers = config.clock_timers
41
45
  @launchsecurity_data = config.launchsecurity_data
42
46
  @shares = config.shares
@@ -198,6 +202,8 @@ module VagrantPlugins
198
202
  dir = File.dirname(serial[:source][:path])
199
203
  begin
200
204
  FileUtils.mkdir_p(dir)
205
+ FileUtils.touch(serial[:source][:path])
206
+ File.truncate(serial[:source][:path], 0) unless serial[:source].fetch(:append, false)
201
207
  rescue ::Errno::EACCES
202
208
  raise Errors::SerialCannotCreatePathError,
203
209
  path: dir
@@ -234,7 +240,15 @@ module VagrantPlugins
234
240
  env[:ui].info(" -- Feature (HyperV): name=#{feature[:name]}, state=#{feature[:state]}")
235
241
  end
236
242
  end
237
- env[:ui].info(" -- Clock offset: #{@clock_offset}")
243
+ if not @clock_absolute.nil?
244
+ env[:ui].info(" -- Clock absolute: #{@clock_absolute}")
245
+ elsif not @clock_adjustment.nil?
246
+ env[:ui].info(" -- Clock adjustment: #{@clock_adjustment}")
247
+ elsif not @clock_timezone.nil?
248
+ env[:ui].info(" -- Clock timezone: #{@clock_timezone}")
249
+ else
250
+ env[:ui].info(" -- Clock offset: #{@clock_offset}")
251
+ end
238
252
  @clock_timers.each do |timer|
239
253
  env[:ui].info(" -- Clock timer: #{timer.map { |k,v| "#{k}=#{v}"}.join(', ')}")
240
254
  end
@@ -60,6 +60,7 @@ module VagrantPlugins
60
60
  xml.group storage_gid(env)
61
61
  xml.label 'virt_image_t'
62
62
  end
63
+ xml.compat '1.1'
63
64
  end
64
65
  xml.backingStore do
65
66
  xml.path(@backing_file)
@@ -4,6 +4,9 @@ require 'log4r'
4
4
  require 'vagrant/util/network_ip'
5
5
  require 'vagrant/util/scoped_hash_override'
6
6
 
7
+ require 'vagrant-libvirt/util/erb_template'
8
+ require 'vagrant-libvirt/util/network_util'
9
+
7
10
  module VagrantPlugins
8
11
  module ProviderLibvirt
9
12
  module Action
@@ -40,7 +43,7 @@ module VagrantPlugins
40
43
 
41
44
  # Vagrant gives you adapter 0 by default
42
45
  # Assign interfaces to slots.
43
- configured_networks(env, @logger).each do |options|
46
+ configured_networks(env[:machine], @logger).each do |options|
44
47
  # don't need to create interface for this type
45
48
  next if options[:iface_type] == :forwarded_port
46
49
 
@@ -78,7 +81,7 @@ module VagrantPlugins
78
81
  @driver_name = iface_configuration.fetch(:driver_name, false)
79
82
  @driver_iommu = iface_configuration.fetch(:driver_iommu, false )
80
83
  @driver_queues = iface_configuration.fetch(:driver_queues, false)
81
- @device_name = iface_configuration.fetch(:iface_name, false)
84
+ @device_name = iface_configuration.fetch(:iface_name, nil)
82
85
  @mtu = iface_configuration.fetch(:mtu, nil)
83
86
  @pci_bus = iface_configuration.fetch(:bus, nil)
84
87
  @pci_slot = iface_configuration.fetch(:slot, nil)
@@ -96,6 +99,7 @@ module VagrantPlugins
96
99
  @driver_iommu = iface_configuration.fetch(:driver_iommu, false )
97
100
  @driver_name = iface_configuration.fetch(:driver_name, false)
98
101
  @driver_queues = iface_configuration.fetch(:driver_queues, false)
102
+ @device_name = iface_configuration.fetch(:iface_name, nil)
99
103
  @portgroup = iface_configuration.fetch(:portgroup, nil)
100
104
  @network_name = iface_configuration.fetch(:network_name, @network_name)
101
105
  template_name = 'public_interface'
@@ -146,7 +150,7 @@ module VagrantPlugins
146
150
  # FIXME: all options for network driver should be hash from Vagrantfile
147
151
  driver_options = {}
148
152
  driver_options[:name] = @driver_name if @driver_name
149
- driver_options[:iommu] = @driver_iommu ? "on" : "off" if @nic_model_type == 'virtio'
153
+ driver_options[:iommu] = @driver_iommu ? "on" : "off" if @model_type == 'virtio'
150
154
  driver_options[:queues] = @driver_queues if @driver_queues
151
155
 
152
156
  @udp_tunnel ||= {}
@@ -169,7 +173,7 @@ module VagrantPlugins
169
173
  @logger.debug {
170
174
  "Attaching Network Device with XML:\n#{xml}"
171
175
  }
172
- domain.attach_device(xml)
176
+ env[:machine].provider.driver.attach_device(xml)
173
177
  rescue => e
174
178
  raise Errors::AttachDeviceError,
175
179
  error_message: e.message
@@ -47,7 +47,7 @@ module VagrantPlugins
47
47
  @@lock.synchronize do
48
48
  # Iterate over networks If some network is not
49
49
  # available, create it if possible. Otherwise raise an error.
50
- configured_networks(env, @logger).each do |options|
50
+ configured_networks(env[:machine], @logger).each do |options|
51
51
  # Only need to create private networks
52
52
  next if options[:iface_type] != :private_network ||
53
53
  options.fetch(:tunnel_type, nil)
@@ -0,0 +1,22 @@
1
+
2
+ require "vagrant/action/builtin/confirm"
3
+
4
+ module VagrantPlugins
5
+ module VagrantLibvirt
6
+ module Action
7
+ class DestroyDomainConfirm < Vagrant::Action::Builtin::Confirm
8
+ def initialize(app, env)
9
+ force_key = :force_confirm_destroy
10
+ message = I18n.t("vagrant_libvirt.destroy_domain.confirmation",
11
+ name: env[:machine].name)
12
+
13
+ super(app, env, message, force_key, allowed: ["y", "n", "Y", "N"])
14
+ end
15
+
16
+ def call(env)
17
+
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -93,7 +93,7 @@ module VagrantPlugins
93
93
  -N
94
94
  #{ssh_info[:host]}
95
95
  )
96
- params += '-g' if gateway_ports
96
+ params <<= '-g' if gateway_ports
97
97
 
98
98
  options = (%W(
99
99
  User=#{ssh_info[:username]}
@@ -43,6 +43,7 @@ module VagrantPlugins
43
43
  :name => HandleBoxImage.get_volume_name(env[:machine].box, 'box', image_path, env[:ui]),
44
44
  :virtual_size => HandleBoxImage.get_virtual_size(env),
45
45
  :format => box_format,
46
+ :compat => "1.1",
46
47
  }]
47
48
  else
48
49
  # Handle box v2 format
@@ -57,7 +58,7 @@ module VagrantPlugins
57
58
  raise Errors::BoxFormatMissingAttribute, attribute: "disks[#{i}]['path']" if disks[i]['path'].nil?
58
59
 
59
60
  image_path = HandleBoxImage.get_box_image_path(env[:machine].box, disks[i]['path'])
60
- format, virtual_size = HandleBoxImage.get_box_disk_settings(image_path)
61
+ format, virtual_size, compat = HandleBoxImage.get_box_disk_settings(image_path)
61
62
  volume_name = HandleBoxImage.get_volume_name(
62
63
  env[:machine].box,
63
64
  disks[i].fetch('name', disks[i]['path'].sub(/#{File.extname(disks[i]['path'])}$/, '')),
@@ -76,7 +77,8 @@ module VagrantPlugins
76
77
  :path => image_path,
77
78
  :name => volume_name,
78
79
  :virtual_size => virtual_size,
79
- :format => HandleBoxImage.verify_box_format(format)
80
+ :format => HandleBoxImage.verify_box_format(format),
81
+ :compat => compat,
80
82
  }
81
83
  }
82
84
  end
@@ -180,8 +182,9 @@ module VagrantPlugins
180
182
  image_info = JSON.parse(stdout)
181
183
  format = image_info['format']
182
184
  virtual_size = ByteNumber.new(image_info['virtual-size'])
185
+ compat = image_info.fetch("format-specific", {}).fetch("data", {}).fetch("compat", "0.10")
183
186
 
184
- return format, virtual_size
187
+ return format, virtual_size, compat
185
188
  end
186
189
 
187
190
  def send_box_image(env, config, box_image_file, box_volume)
@@ -166,12 +166,29 @@ module VagrantPlugins
166
166
  xml_descr.delete_element('/domain/cpu')
167
167
  end
168
168
 
169
- # Clock
169
+ # Clock - can change in complicated ways, so just build a new clock and compare
170
+ newclock = REXML::Element.new('newclock')
171
+ if not config.clock_absolute.nil?
172
+ newclock.add_attribute('offset', 'absolute')
173
+ newclock.add_attribute('start', config.clock_absolute)
174
+ elsif not config.clock_adjustment.nil?
175
+ newclock.add_attribute('offset', 'variable')
176
+ newclock.add_attribute('basis', config.clock_basis)
177
+ newclock.add_attribute('adjustment', config.clock_adjustment)
178
+ elsif not config.clock_timezone.nil?
179
+ newclock.add_attribute('offset', 'timezone')
180
+ newclock.add_attribute('timezone', config.clock_timezone)
181
+ else
182
+ newclock.add_attribute('offset', config.clock_offset)
183
+ end
170
184
  clock = REXML::XPath.first(xml_descr, '/domain/clock')
171
- if clock.attributes['offset'] != config.clock_offset
172
- @logger.debug "clock offset changed"
185
+ if clock.attributes != newclock.attributes
186
+ @logger.debug "clock definition changed"
173
187
  descr_changed = true
174
- clock.attributes['offset'] = config.clock_offset
188
+ clock.attributes.clear
189
+ newclock.attributes.each do |attr, value|
190
+ clock.add_attribute(attr, value)
191
+ end
175
192
  end
176
193
 
177
194
  # clock timers - because timers can be added/removed, just rebuild and then compare
@@ -272,13 +289,25 @@ module VagrantPlugins
272
289
  graphics.attributes['listen'] = config.graphics_ip
273
290
  graphics.delete_element('//listen')
274
291
  end
275
- if graphics.attributes['autoport'] != config.graphics_autoport
276
- descr_changed = true
277
- graphics.attributes['autoport'] = config.graphics_autoport
278
- if config.graphics_autoport == 'no'
279
- graphics.attributes.delete('autoport')
292
+ unless config.graphics_port.nil? or config.graphics_port == -1
293
+ if graphics.attributes['autoport'] != 'no'
294
+ descr_changed = true
295
+ graphics.attributes['autoport'] = 'no'
296
+ end
297
+ if graphics.attributes['port'] != config.graphics_port
298
+ descr_changed = true
280
299
  graphics.attributes['port'] = config.graphics_port
281
300
  end
301
+ else
302
+ if graphics.attributes['autoport'] != config.graphics_autoport
303
+ descr_changed = true
304
+ graphics.attributes['autoport'] = config.graphics_autoport
305
+ if config.graphics_autoport == 'no'
306
+ graphics.attributes['port'] = config.graphics_port
307
+ else
308
+ graphics.attributes['port'] = '-1'
309
+ end
310
+ end
282
311
  end
283
312
  if graphics.attributes['websocket'] != config.graphics_websocket.to_s
284
313
  descr_changed = true
@@ -128,9 +128,7 @@ module VagrantPlugins
128
128
  private_class_method def self.action_start
129
129
  Vagrant::Action::Builder.new.tap do |b|
130
130
  b.use Call, IsRunning do |env, b2|
131
- # If the VM is running, run the necessary provisioners
132
131
  if env[:result]
133
- b2.use action_provision
134
132
  next
135
133
  end
136
134
 
@@ -7,11 +7,13 @@ require 'vagrant/action/builtin/mixin_synced_folders'
7
7
 
8
8
  require 'vagrant-libvirt/errors'
9
9
  require 'vagrant-libvirt/util/resolvers'
10
+ require 'vagrant-libvirt/util/network_util'
10
11
 
11
12
  module VagrantPlugins
12
13
  module ProviderLibvirt
13
14
  class Config < Vagrant.plugin('2', :config)
14
15
  include Vagrant::Action::Builtin::MixinSyncedFolders
16
+ include VagrantPlugins::ProviderLibvirt::Util::NetworkUtil
15
17
 
16
18
  # manually specify URI
17
19
  # will supersede most other options if provided
@@ -68,6 +70,8 @@ module VagrantPlugins
68
70
  attr_accessor :management_network_mtu
69
71
  attr_accessor :management_network_keep
70
72
  attr_accessor :management_network_driver_iommu
73
+ attr_accessor :management_network_iface_name
74
+ attr_accessor :management_network_model_type
71
75
 
72
76
  # System connection information
73
77
  attr_accessor :system_uri
@@ -95,7 +99,11 @@ module VagrantPlugins
95
99
  attr_accessor :shares
96
100
  attr_accessor :features
97
101
  attr_accessor :features_hyperv
102
+ attr_accessor :clock_absolute
103
+ attr_accessor :clock_adjustment
104
+ attr_accessor :clock_basis
98
105
  attr_accessor :clock_offset
106
+ attr_accessor :clock_timezone
99
107
  attr_accessor :clock_timers
100
108
  attr_accessor :launchsecurity_data
101
109
  attr_accessor :numa_nodes
@@ -222,6 +230,8 @@ module VagrantPlugins
222
230
  ]
223
231
 
224
232
  def initialize
233
+ @logger = Log4r::Logger.new("vagrant_libvirt::config")
234
+
225
235
  @uri = UNSET_VALUE
226
236
  @driver = UNSET_VALUE
227
237
  @host = UNSET_VALUE
@@ -249,6 +259,8 @@ module VagrantPlugins
249
259
  @management_network_mtu = UNSET_VALUE
250
260
  @management_network_keep = UNSET_VALUE
251
261
  @management_network_driver_iommu = UNSET_VALUE
262
+ @management_network_iface_name = UNSET_VALUE
263
+ @management_network_model_type = UNSET_VALUE
252
264
 
253
265
  # System connection information
254
266
  @system_uri = UNSET_VALUE
@@ -272,7 +284,11 @@ module VagrantPlugins
272
284
  @shares = UNSET_VALUE
273
285
  @features = UNSET_VALUE
274
286
  @features_hyperv = UNSET_VALUE
287
+ @clock_absolute = UNSET_VALUE
288
+ @clock_adjustment = UNSET_VALUE
289
+ @clock_basis = UNSET_VALUE
275
290
  @clock_offset = UNSET_VALUE
291
+ @clock_timezone = UNSET_VALUE
276
292
  @clock_timers = []
277
293
  @launchsecurity_data = UNSET_VALUE
278
294
  @numa_nodes = UNSET_VALUE
@@ -720,7 +736,7 @@ module VagrantPlugins
720
736
 
721
737
  # Disk driver options for primary disk
722
738
  def disk_driver(options = {})
723
- supported_opts = [:cache, :io, :copy_on_read, :discard, :detect_zeroes]
739
+ supported_opts = [:cache, :io, :copy_on_read, :discard, :detect_zeroes, :type]
724
740
  @disk_driver_opts = options.select { |k,_| supported_opts.include? k }
725
741
  end
726
742
 
@@ -959,6 +975,8 @@ module VagrantPlugins
959
975
  @management_network_mtu = nil if @management_network_mtu == UNSET_VALUE
960
976
  @management_network_keep = false if @management_network_keep == UNSET_VALUE
961
977
  @management_network_driver_iommu = false if @management_network_driver_iommu == UNSET_VALUE
978
+ @management_network_iface_name = nil if @management_network_iface_name == UNSET_VALUE
979
+ @management_network_model_type = 'virtio' if @management_network_model_type == UNSET_VALUE
962
980
 
963
981
  # Domain specific settings.
964
982
  @title = '' if @title == UNSET_VALUE
@@ -995,7 +1013,11 @@ module VagrantPlugins
995
1013
  @shares = nil if @shares == UNSET_VALUE
996
1014
  @features = ['acpi','apic','pae'] if @features == UNSET_VALUE
997
1015
  @features_hyperv = [] if @features_hyperv == UNSET_VALUE
1016
+ @clock_absolute = nil if @clock_absolute == UNSET_VALUE
1017
+ @clock_adjustment = nil if @clock_adjustment == UNSET_VALUE
1018
+ @clock_basis = 'utc' if @clock_basis == UNSET_VALUE
998
1019
  @clock_offset = 'utc' if @clock_offset == UNSET_VALUE
1020
+ @clock_timezone = nil if @clock_timezone == UNSET_VALUE
999
1021
  @clock_timers = [] if @clock_timers == UNSET_VALUE
1000
1022
  @launchsecurity_data = nil if @launchsecurity_data == UNSET_VALUE
1001
1023
  @numa_nodes = @numa_nodes == UNSET_VALUE ? nil : _generate_numa
@@ -1206,27 +1228,7 @@ module VagrantPlugins
1206
1228
  errors << "#{e}"
1207
1229
  end
1208
1230
 
1209
- machine.config.vm.networks.each_with_index do |network, index|
1210
- type, opts = network
1211
-
1212
- if opts[:mac]
1213
- if opts[:mac] =~ /\A([0-9a-fA-F]{12})\z/
1214
- opts[:mac] = opts[:mac].scan(/../).join(':')
1215
- end
1216
- unless opts[:mac] =~ /\A([0-9a-fA-F]{2}:){5}([0-9a-fA-F]{2})\z/
1217
- errors << "Configured NIC MAC '#{opts[:mac]}' is not in 'xx:xx:xx:xx:xx:xx' or 'xxxxxxxxxxxx' format"
1218
- end
1219
- end
1220
-
1221
- # only interested in public networks where portgroup is nil, as then source will be a host device
1222
- if type == :public_network && opts[:portgroup] == nil
1223
- devices = host_devices(machine)
1224
- hostdev = opts.fetch(:dev, 'eth0')
1225
- if !devices.include?(hostdev)
1226
- errors << "network configuration #{index} for machine #{machine.name} is a public_network referencing host device '#{hostdev}' which does not exist, consider adding ':dev => ....' referencing one of #{devices.join(", ")}"
1227
- end
1228
- end
1229
- end
1231
+ errors = validate_networks(machine, errors)
1230
1232
 
1231
1233
  if !machine.provider_config.volume_cache.nil? and machine.provider_config.volume_cache != UNSET_VALUE
1232
1234
  machine.ui.warn("Libvirt Provider: volume_cache is deprecated. Use disk_driver :cache => '#{machine.provider_config.volume_cache}' instead.")
@@ -1250,6 +1252,10 @@ module VagrantPlugins
1250
1252
  end
1251
1253
  end
1252
1254
 
1255
+ if [@clock_absolute, @clock_adjustment, @clock_timezone].count {|clock| !clock.nil?} > 1
1256
+ errors << "At most, only one of [clock_absolute, clock_adjustment, clock_timezone] may be set."
1257
+ end
1258
+
1253
1259
  errors = validate_sysinfo(machine, errors)
1254
1260
 
1255
1261
  { 'Libvirt Provider' => errors }
@@ -1320,8 +1326,8 @@ module VagrantPlugins
1320
1326
  end
1321
1327
  end
1322
1328
 
1323
- # Extract host values from uri if provided, otherwise nil
1324
- @host = uri.host
1329
+ # Extract host values from uri if provided, otherwise set empty string
1330
+ @host = uri.host || ""
1325
1331
  @port = uri.port
1326
1332
  # only override username if there is a value provided
1327
1333
  @username = nil if @username == UNSET_VALUE
@@ -1389,11 +1395,55 @@ module VagrantPlugins
1389
1395
  end
1390
1396
  end
1391
1397
 
1392
- def host_devices(machine)
1393
- machine.provider.driver.host_devices.select do |dev|
1394
- next if dev.empty?
1395
- dev != "lo" && !@host_device_exclude_prefixes.any? { |exclude| dev.start_with?(exclude) }
1398
+ def validate_networks(machine, errors)
1399
+ begin
1400
+ networks = configured_networks(machine, @logger)
1401
+ rescue Errors::VagrantLibvirtError => e
1402
+ errors << "#{e}"
1403
+
1404
+ return
1396
1405
  end
1406
+
1407
+ return if networks.empty?
1408
+
1409
+ networks.each_with_index do |network, index|
1410
+ if network[:mac]
1411
+ if network[:mac] =~ /\A([0-9a-fA-F]{12})\z/
1412
+ network[:mac] = network[:mac].scan(/../).join(':')
1413
+ end
1414
+ unless network[:mac] =~ /\A([0-9a-fA-F]{2}:){5}([0-9a-fA-F]{2})\z/
1415
+ errors << "Configured NIC MAC '#{network[:mac]}' is not in 'xx:xx:xx:xx:xx:xx' or 'xxxxxxxxxxxx' format"
1416
+ end
1417
+ end
1418
+
1419
+ # only interested in public networks where portgroup is nil, as then source will be a host device
1420
+ if network[:iface_type] == :public_network && network[:portgroup] == nil
1421
+ exclude_prefixes = @host_device_exclude_prefixes
1422
+ # for qemu sessions the management network injected will be a public_network trying to use a libvirt managed device
1423
+ if index == 0 and machine.provider_config.mgmt_attach and machine.provider_config.qemu_use_session == true
1424
+ exclude_prefixes.delete('virbr')
1425
+ end
1426
+
1427
+ devices = machine.provider.driver.host_devices.select do |dev|
1428
+ next if dev.empty?
1429
+ dev != "lo" && !exclude_prefixes.any? { |exclude| dev.start_with?(exclude) }
1430
+ end
1431
+ hostdev = network.fetch(:dev, 'eth0')
1432
+
1433
+ if !devices.include?(hostdev)
1434
+ errors << "network configuration #{index} for machine #{machine.name} is a public_network referencing host device '#{hostdev}' which does not exist, consider adding ':dev => ....' referencing one of #{devices.join(", ")}"
1435
+ end
1436
+ end
1437
+
1438
+ unless network[:iface_name].nil?
1439
+ restricted_devnames = ['vnet', 'vif', 'macvtap', 'macvlan']
1440
+ if restricted_devnames.any? { |restricted| network[:iface_name].start_with?(restricted) }
1441
+ errors << "network configuration for machine #{machine.name} with setting :libvirt__iface_name => '#{network[:iface_name]}' starts with a restricted prefix according to libvirt docs https://libvirt.org/formatdomain.html#overriding-the-target-element, please use a device name that does not start with one of #{restricted_devnames.join(", ")}"
1442
+ end
1443
+ end
1444
+ end
1445
+
1446
+ errors
1397
1447
  end
1398
1448
 
1399
1449
  def validate_sysinfo(machine, errors)
@@ -132,7 +132,15 @@
132
132
  </hyperv>
133
133
  <%- end -%>
134
134
  </features>
135
+ <%- if not @clock_absolute.nil? -%>
136
+ <clock offset='absolute' start='<%= @clock_absolute %>'>
137
+ <%- elsif not @clock_adjustment.nil? -%>
138
+ <clock offset='variable' basis='<%= @clock_basis %>' adjustment='<%= @clock_adjustment %>'>
139
+ <%- elsif not @clock_timezone.nil? -%>
140
+ <clock offset='timezone' timezone='<%= @clock_timezone %>'>
141
+ <%- else -%>
135
142
  <clock offset='<%= @clock_offset %>'>
143
+ <%- end -%>
136
144
  <%- @clock_timers.each do |clock_timer| -%>
137
145
  <timer<% clock_timer.each do |attr, value| %> <%= attr %>='<%= value %>'<% end %>/>
138
146
  <%- end -%>
@@ -144,11 +152,11 @@
144
152
  <%- @domain_volumes.each_with_index do |volume, index| -%>
145
153
  <disk type='file' device='disk'>
146
154
  <alias name='ua-box-volume-<%= index -%>'/>
147
- <driver name='qemu' type='qcow2' <%=
148
- @disk_driver_opts.empty? ? "cache='#{volume[:cache]}'" :
149
- @disk_driver_opts.reject { |k,v| v.nil? }
150
- .map { |k,v| "#{k}='#{v}'"}
151
- .join(' ') -%>/>
155
+ <driver name='qemu' <%=
156
+ {:type => 'qcow2', :cache => "#{volume[:cache]}"}.merge(@disk_driver_opts)
157
+ .reject { |k,v| v.nil? }
158
+ .map { |k,v| "#{k}='#{v}'"}
159
+ .join(' ') -%>/>
152
160
  <source file='<%= volume[:absolute_path] %>'/>
153
161
  <%# we need to ensure a unique target dev -%>
154
162
  <target dev='<%= volume[:device] %>' bus='<%= volume[:bus] %>'/>
@@ -167,12 +175,12 @@
167
175
  <%- @disks.each_with_index do |d, index| -%>
168
176
  <disk type='file' device='disk'>
169
177
  <alias name='ua-disk-volume-<%= index -%>'/>
170
- <driver name='qemu' type='<%= d[:type] %>' <%=
171
- d.select { |k,_| [:cache, :io, :copy_on_read, :discard, :detect_zeroes].include? k }
172
- .reject { |k,v| v.nil? }
173
- .map { |k,v| "#{k}='#{v}'"}
174
- .join(' ')
175
- -%>/>
178
+ <driver name='qemu' <%=
179
+ {:type => 'qcow2'}.merge(d)
180
+ .select { |k,_| [:type, :cache, :io, :copy_on_read, :discard, :detect_zeroes].include? k }
181
+ .reject { |k,v| v.nil? }
182
+ .map { |k,v| "#{k}='#{v}'"}
183
+ .join(' ') -%>/>
176
184
  <source file='<%= d[:absolute_path] %>'/>
177
185
  <target dev='<%= d[:device] %>' bus='<%= d[:bus] %>'/>
178
186
  <%- if d[:address_type] || @disk_address_type -%>
@@ -208,9 +216,12 @@
208
216
  <%- end -%>
209
217
  <%- @serials.each_with_index do |serial, port| -%>
210
218
  <serial type='<%= serial[:type] %>'>
211
- <%- unless serial[:source].nil? -%>
212
- <source path='<%= serial[:source][:path] %>'/>
213
- <%- end -%>
219
+ <%- unless serial[:source].nil?
220
+ source = serial[:source]
221
+ seclabel = serial[:source][:seclabel]
222
+ -%>
223
+ <source path='<%= source[:path] %>' append='<%= source.fetch(:append, 'on') %>'/>
224
+ <%- end -%>
214
225
  <target port='<%= port %>'/>
215
226
  </serial>
216
227
  <%- end -%>
@@ -1,34 +1,39 @@
1
1
  <interface type='<%= @type %>'<% if @trust_guest_rx_filters %> trustGuestRxFilters='yes'<% end %>>
2
2
  <alias name='ua-net-<%= @iface_number %>'/>
3
- <% if @mac %>
3
+ <%- if @mac %>
4
4
  <mac address='<%= @mac %>'/>
5
- <% end %>
6
- <%if @type == 'direct'%>
5
+ <%- end %>
6
+ <%- if @type == 'direct'%>
7
7
  <source dev='<%= @device %>' mode='<%= @mode %>'/>
8
- <% elsif !@portgroup.nil? %>
8
+ <%- elsif !@portgroup.nil? %>
9
9
  <source network='<%=@network_name%>' portgroup='<%=@portgroup%>'/>
10
- <% else %>
10
+ <%- else %>
11
11
  <source bridge='<%=@device%>'/>
12
- <% end %>
12
+ <%- end %>
13
+ <%- unless @device_name.nil? %>
14
+ <target dev='<%= @device_name %>'/>
15
+ <%- end %>
13
16
  <model type='<%=@model_type%>'/>
14
- <% if @driver_name and @driver_queues %>
17
+ <%- if @driver_name and @driver_queues %>
15
18
  <driver <% if @driver_iommu %> iommu="on" <% end %> name='<%=@driver_name%>' queues='<%=@driver_queues%>'/>
16
- <% elsif @driver_queues %>
19
+ <%- elsif @driver_queues %>
17
20
  <driver <% if @driver_iommu %> iommu="on" <% end %> queues='<%=@driver_queues%>'/>
18
- <% elsif @driver_name %>
21
+ <%- elsif @driver_name %>
19
22
  <driver <% if @driver_iommu %> iommu="on" <% end %> name='<%=@driver_name%>'/>
20
- <% elsif @driver_iommu %>
23
+ <%- elsif @driver_iommu %>
21
24
  <driver iommu='on' />
25
+ <%- end %>
26
+ <% if @mtu %>
27
+ <mtu size="<%= @mtu %>" />
22
28
  <% end %>
23
-
24
- <% if @ovs %>
29
+ <%- if @ovs %>
25
30
  <virtualport type='openvswitch'>
26
- <% if @ovs_interfaceid %>
31
+ <%- if @ovs_interfaceid %>
27
32
  <parameters interfaceid='<%=@ovs_interfaceid%>'/>
28
- <% end %>
33
+ <%- end %>
29
34
  </virtualport>
30
- <% end %>
31
- <% if @pci_bus and @pci_slot %>
35
+ <%- end %>
36
+ <%- if @pci_bus and @pci_slot %>
32
37
  <address type='pci' bus='<%=@pci_bus%>' slot='<%=@pci_slot%>' />
33
- <% end %>
38
+ <%- end %>
34
39
  </interface>