vagrant-libvirt 0.11.2 → 0.12.1

Sign up to get free protection for your applications and to get access to all the features.
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>