vagrant-libvirt 0.8.2 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. checksums.yaml +4 -4
  2. data/lib/vagrant-libvirt/action/create_domain.rb +19 -91
  3. data/lib/vagrant-libvirt/action/destroy_domain.rb +20 -4
  4. data/lib/vagrant-libvirt/action/destroy_networks.rb +1 -1
  5. data/lib/vagrant-libvirt/action/handle_box_image.rb +2 -0
  6. data/lib/vagrant-libvirt/action/resolve_disk_settings.rb +174 -0
  7. data/lib/vagrant-libvirt/action/start_domain.rb +41 -1
  8. data/lib/vagrant-libvirt/action.rb +4 -0
  9. data/lib/vagrant-libvirt/config.rb +4 -0
  10. data/lib/vagrant-libvirt/templates/domain.xml.erb +2 -2
  11. data/lib/vagrant-libvirt/util/domain_flags.rb +15 -0
  12. data/lib/vagrant-libvirt/util.rb +1 -0
  13. data/lib/vagrant-libvirt/version +1 -1
  14. data/locales/en.yml +4 -2
  15. data/spec/support/libvirt_context.rb +4 -0
  16. data/spec/unit/action/cleanup_on_failure_spec.rb +0 -2
  17. data/spec/unit/action/create_domain_spec.rb +113 -147
  18. data/spec/unit/action/create_domain_volume_spec.rb +0 -3
  19. data/spec/unit/action/destroy_domain_spec.rb +43 -10
  20. data/spec/unit/action/handle_box_image_spec.rb +13 -13
  21. data/spec/unit/action/package_domain_spec.rb +0 -5
  22. data/spec/unit/action/resolve_disk_settings_spec/default_domain.xml +43 -0
  23. data/spec/unit/action/resolve_disk_settings_spec/default_no_aliases.xml +42 -0
  24. data/spec/unit/action/{create_domain_spec → resolve_disk_settings_spec}/default_system_storage_pool.xml +0 -0
  25. data/spec/unit/action/resolve_disk_settings_spec/multi_volume_box.xml +55 -0
  26. data/spec/unit/action/resolve_disk_settings_spec/multi_volume_box_additional_and_custom_no_aliases.xml +67 -0
  27. data/spec/unit/action/resolve_disk_settings_spec/multi_volume_box_additional_storage.xml +67 -0
  28. data/spec/unit/action/resolve_disk_settings_spec.rb +361 -0
  29. data/spec/unit/action/start_domain_spec/existing_added_nvram.xml +62 -0
  30. data/spec/unit/action/start_domain_spec/nvram_domain.xml +64 -0
  31. data/spec/unit/action/start_domain_spec/nvram_domain_other_setting.xml +64 -0
  32. data/spec/unit/action/start_domain_spec/nvram_domain_removed.xml +64 -0
  33. data/spec/unit/action/start_domain_spec.rb +64 -6
  34. data/spec/unit/action/wait_till_up_spec.rb +0 -2
  35. data/spec/unit/action_spec.rb +0 -3
  36. data/spec/unit/config_spec.rb +18 -0
  37. data/spec/unit/driver_spec.rb +2 -0
  38. data/spec/unit/templates/domain_all_settings.xml +2 -2
  39. data/spec/unit/templates/domain_spec.rb +2 -2
  40. metadata +37 -15
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c7f252cbd53f8459e02a21e94449e6fef1ce762f1d053433970015fad9d00fef
4
- data.tar.gz: 54af8a7a564e8ffdd0f18d3d3eca44367ac7613fb4892af995c5d202d8e429ea
3
+ metadata.gz: 79027c1097a7e8136b8d56f74fd0b27932bf17c48387de84c57626c2bd348714
4
+ data.tar.gz: cd6acea3cf183191ea6bbee6e60d7a1fc76a5f0b556f273f60657238283841ce
5
5
  SHA512:
6
- metadata.gz: 00c708fba6fb82cec02b0b68730da87975964584b8b189bfcd77857b3b386ff81609bd135423872dcd04cd7e071f10f1cf7806d97b28565ed27464d2b2021857
7
- data.tar.gz: abbbe10ad322fec1a49b9f3463fa7a50c9e46bce93c8c6aa505ca3c4fbd5e6a3b4bfa248e912d0608e5aefdd3427ce819e6bff9f0807da187a187c2e9085d13e
6
+ metadata.gz: 6d6483a73ce398e6fd057b2fc0503392c628ad1fc228d9d954b9a5e31d9a65ab883c25f30cb9360ce5eff46554492dd010b68d741f3c8935e64228207bf2f210
7
+ data.tar.gz: 1a083a93899bb48d4d750aa8967bdcb8e6b1b0b9a8fb0d88c912097444cd202c52fe0330f81a1e4803dde184b06e035c8bd8d32397035c186653b978db790e12
@@ -16,20 +16,6 @@ module VagrantPlugins
16
16
  @app = app
17
17
  end
18
18
 
19
- def _disk_name(name, disk)
20
- "#{name}-#{disk[:device]}.#{disk[:type]}" # disk name
21
- end
22
-
23
- def _disks_print(disks)
24
- disks.collect do |x|
25
- "#{x[:device]}(#{x[:type]}, #{x[:bus]}, #{x[:size]})"
26
- end.join(', ')
27
- end
28
-
29
- def _cdroms_print(cdroms)
30
- cdroms.collect { |x| x[:dev] }.join(', ')
31
- end
32
-
33
19
  def call(env)
34
20
  # Get config.
35
21
  config = env[:machine].provider_config
@@ -58,8 +44,6 @@ module VagrantPlugins
58
44
  @nvram = config.nvram
59
45
  @machine_type = config.machine_type
60
46
  @machine_arch = config.machine_arch
61
- @disk_bus = config.disk_bus
62
- @disk_device = config.disk_device
63
47
  @disk_driver_opts = config.disk_driver_opts
64
48
  @nested = config.nested
65
49
  @memory_size = config.memory.to_i * 1024
@@ -94,9 +78,8 @@ module VagrantPlugins
94
78
 
95
79
  # Storage
96
80
  @storage_pool_name = config.storage_pool_name
97
- @snapshot_pool_name = config.snapshot_pool_name
98
- @domain_volumes = []
99
- @disks = config.disks
81
+ @domain_volumes = env[:domain_volumes] || []
82
+ @disks = env[:disks] || []
100
83
  @cdroms = config.cdroms
101
84
 
102
85
  # Input
@@ -139,77 +122,19 @@ module VagrantPlugins
139
122
  @memballoon_pci_bus = config.memballoon_pci_bus
140
123
  @memballoon_pci_slot = config.memballoon_pci_slot
141
124
 
142
- config = env[:machine].provider_config
143
125
  @domain_type = config.driver
144
126
 
145
127
  @os_type = 'hvm'
146
128
 
147
- resolver = ::VagrantPlugins::ProviderLibvirt::Util::DiskDeviceResolver.new(prefix=@disk_device[0..1])
148
-
149
- # Get path to domain image from the storage pool selected if we have a box.
150
- if env[:machine].config.vm.box
151
- if @snapshot_pool_name != @storage_pool_name
152
- pool_name = @snapshot_pool_name
153
- else
154
- pool_name = @storage_pool_name
155
- end
156
-
157
- # special handling for domain volume
158
- env[:box_volumes][0][:device] = env[:box_volumes][0].fetch(:device, @disk_device)
159
-
160
- resolver.resolve!(env[:box_volumes])
161
-
162
- @logger.debug "Search for volumes in pool: #{pool_name}"
163
- env[:box_volumes].each_index do |index|
164
- suffix_index = index > 0 ? "_#{index}" : ''
165
- domain_volume = env[:machine].provider.driver.connection.volumes.all(
166
- name: "#{@name}#{suffix_index}.img"
167
- ).find { |x| x.pool_name == pool_name }
168
- raise Errors::DomainVolumeExists if domain_volume.nil?
169
-
170
- @domain_volumes.push({
171
- :dev => env[:box_volumes][index][:device],
172
- :cache => @domain_volume_cache,
173
- :bus => @disk_bus,
174
- :path => domain_volume.path,
175
- :virtual_size => env[:box_volumes][index][:virtual_size]
176
- })
177
- end
178
-
129
+ env[:domain_volumes].each_with_index do |vol, index|
130
+ suffix_index = index > 0 ? "_#{index}" : ''
131
+ domain_volume = env[:machine].provider.driver.connection.volumes.all(
132
+ name: "#{@name}#{suffix_index}.img"
133
+ ).find { |x| x.pool_name == vol[:pool] }
134
+ raise Errors::NoDomainVolume if domain_volume.nil?
179
135
  end
180
136
 
181
- # If we have a box, take the path from the domain volume and set our storage_prefix.
182
- # If not, we dump the storage pool xml to get its defined path.
183
- # the default storage prefix is typically: /var/lib/libvirt/images/
184
- if env[:machine].config.vm.box
185
- storage_prefix = File.dirname(@domain_volumes[0][:path]) + '/' # steal
186
- else
187
- storage_prefix = get_disk_storage_prefix(env, @storage_pool_name)
188
- end
189
-
190
- resolver.resolve!(@disks)
191
-
192
137
  @disks.each do |disk|
193
- disk[:path] ||= _disk_name(@name, disk)
194
-
195
- # On volume creation, the <path> element inside <target>
196
- # is oddly ignored; instead the path is taken from the
197
- # <name> element:
198
- # http://www.redhat.com/archives/libvir-list/2008-August/msg00329.html
199
- disk[:name] = disk[:path]
200
-
201
- disk[:absolute_path] = storage_prefix + disk[:path]
202
-
203
- if not disk[:pool].nil?
204
- disk_pool_name = disk[:pool]
205
- @logger.debug "Overriding pool name with: #{disk_pool_name}"
206
- disk_storage_prefix = get_disk_storage_prefix(env, disk_pool_name)
207
- disk[:absolute_path] = disk_storage_prefix + disk[:path]
208
- @logger.debug "Overriding disk path with: #{disk[:absolute_path]}"
209
- else
210
- disk_pool_name = @storage_pool_name
211
- end
212
-
213
138
  # make the disk. equivalent to:
214
139
  # qemu-img create -f qcow2 <path> 5g
215
140
  begin
@@ -221,13 +146,13 @@ module VagrantPlugins
221
146
  owner: storage_uid(env),
222
147
  group: storage_gid(env),
223
148
  #:allocation => ?,
224
- pool_name: disk_pool_name
149
+ pool_name: disk[:pool],
225
150
  )
226
151
  rescue Libvirt::Error => e
227
152
  # It is hard to believe that e contains just a string
228
153
  # and no useful error code!
229
154
  msg = "Call to virStorageVolCreateXML failed: " +
230
- "storage volume '#{disk[:path]}' exists already"
155
+ "storage volume '#{disk[:absolute_path]}' exists already"
231
156
  if e.message == msg and disk[:allow_existing]
232
157
  disk[:preexisting] = true
233
158
  else
@@ -300,7 +225,7 @@ module VagrantPlugins
300
225
  end
301
226
  env[:ui].info(" -- Storage pool: #{@storage_pool_name}")
302
227
  @domain_volumes.each do |volume|
303
- env[:ui].info(" -- Image(#{volume[:dev]}): #{volume[:path]}, #{volume[:bus]}, #{volume[:virtual_size].to_GB}G")
228
+ env[:ui].info(" -- Image(#{volume[:device]}): #{volume[:absolute_path]}, #{volume[:bus]}, #{volume[:virtual_size].to_GB}G")
304
229
  end
305
230
 
306
231
  if not @disk_driver_opts.empty?
@@ -466,11 +391,14 @@ module VagrantPlugins
466
391
  end
467
392
 
468
393
  private
469
- def get_disk_storage_prefix(env, disk_pool_name)
470
- disk_storage_pool = env[:machine].provider.driver.connection.client.lookup_storage_pool_by_name(disk_pool_name)
471
- raise Errors::NoStoragePool if disk_storage_pool.nil?
472
- xml = Nokogiri::XML(disk_storage_pool.xml_desc)
473
- disk_storage_prefix = xml.xpath('/pool/target/path').inner_text.to_s + '/'
394
+ def _disks_print(disks)
395
+ disks.collect do |x|
396
+ "#{x[:device]}(#{x[:type]}, #{x[:bus]}, #{x[:size]})"
397
+ end.join(', ')
398
+ end
399
+
400
+ def _cdroms_print(cdroms)
401
+ cdroms.collect { |x| x[:dev] }.join(', ')
474
402
  end
475
403
  end
476
404
  end
@@ -1,7 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'log4r'
4
- require 'rexml'
4
+
5
+ begin
6
+ require 'rexml'
7
+ rescue LoadError
8
+ require 'rexml/rexml'
9
+ end
5
10
 
6
11
  module VagrantPlugins
7
12
  module ProviderLibvirt
@@ -43,21 +48,24 @@ module VagrantPlugins
43
48
 
44
49
  domain = env[:machine].provider.driver.connection.servers.get(env[:machine].id.to_s)
45
50
 
51
+ undefine_flags = 0
52
+ undefine_flags |= ProviderLibvirt::Util::DomainFlags::VIR_DOMAIN_UNDEFINE_KEEP_NVRAM if env[:machine].provider_config.nvram
53
+
46
54
  if env[:machine].provider_config.disks.empty? &&
47
55
  env[:machine].provider_config.cdroms.empty?
48
56
  # if using default configuration of disks and cdroms
49
57
  # cdroms are consider volumes, but cannot be destroyed
50
- domain.destroy(destroy_volumes: true)
58
+ destroy_domain(domain, destroy_volumes: true, flags: undefine_flags)
51
59
  else
52
60
  domain_xml = libvirt_domain.xml_desc(1)
53
61
  xml_descr = REXML::Document.new(domain_xml)
54
62
  disks_xml = REXML::XPath.match(xml_descr, '/domain/devices/disk[@device="disk"]')
55
63
  have_aliases = !(REXML::XPath.match(disks_xml, './alias[@name="ua-box-volume-0"]').first).nil?
56
64
  if !have_aliases
57
- env[:ui].warn(I18n.t('vagrant_libvirt.destroy.obsolete_method'))
65
+ env[:ui].warn(I18n.t('vagrant_libvirt.domain_xml.obsolete_method'))
58
66
  end
59
67
 
60
- domain.destroy(destroy_volumes: false)
68
+ destroy_domain(domain, destroy_volumes: false, flags: undefine_flags)
61
69
 
62
70
  volumes = domain.volumes
63
71
 
@@ -164,6 +172,14 @@ module VagrantPlugins
164
172
  libvirt_disk.destroy if libvirt_disk
165
173
  end
166
174
  end
175
+
176
+ def destroy_domain(domain, destroy_volumes:, flags:)
177
+ if domain.method(:destroy).parameters.first.include?(:flags)
178
+ domain.destroy(destroy_volumes: destroy_volumes, flags: flags)
179
+ else
180
+ domain.destroy(destroy_volumes: destroy_volumes)
181
+ end
182
+ end
167
183
  end
168
184
  end
169
185
  end
@@ -68,7 +68,7 @@ module VagrantPlugins
68
68
  # Shutdown network first.
69
69
  # Undefine network.
70
70
  begin
71
- libvirt_network.destroy
71
+ libvirt_network.destroy if libvirt_network.active?
72
72
  libvirt_network.undefine
73
73
  @logger.info 'Undefined it'
74
74
  rescue => e
@@ -104,6 +104,8 @@ module VagrantPlugins
104
104
  end
105
105
  # save for use by later actions
106
106
  env[:box_volumes][0][:virtual_size] = box_virtual_size
107
+ # special handling for domain volume
108
+ env[:box_volumes][0][:device] ||= config.disk_device
107
109
 
108
110
  # while inside the synchronize block take care not to call the next
109
111
  # action in the chain, as must exit this block first to prevent
@@ -0,0 +1,174 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'log4r'
4
+ require 'rexml'
5
+
6
+ require 'vagrant-libvirt/util/resolvers'
7
+
8
+ module VagrantPlugins
9
+ module ProviderLibvirt
10
+ module Action
11
+ class ResolveDiskSettings
12
+ def initialize(app, _env)
13
+ @logger = Log4r::Logger.new('vagrant_libvirt::action::resolve_disk_devices')
14
+ @app = app
15
+ end
16
+
17
+ def call(env)
18
+ # Get config.
19
+ config = env[:machine].provider_config
20
+
21
+ domain_name = env[:domain_name] # only set on create
22
+ disk_bus = config.disk_bus
23
+ disk_device = config.disk_device
24
+ domain_volume_cache = config.volume_cache || 'default'
25
+
26
+ # Storage
27
+ storage_pool_name = config.storage_pool_name
28
+ snapshot_pool_name = config.snapshot_pool_name
29
+ domain_volumes = []
30
+ disks = config.disks.dup
31
+
32
+ resolver = ::VagrantPlugins::ProviderLibvirt::Util::DiskDeviceResolver.new(disk_device[0..1])
33
+
34
+ # Get path to domain image from the storage pool selected if we have a box.
35
+ if env[:machine].config.vm.box
36
+ pool_name = if snapshot_pool_name == storage_pool_name
37
+ storage_pool_name
38
+ else
39
+ snapshot_pool_name
40
+ end
41
+
42
+ if env[:box_volumes].nil?
43
+ # domain must be already created, need to read domain volumes from domain XML
44
+ libvirt_domain = env[:machine].provider.driver.connection.client.lookup_domain_by_uuid(
45
+ env[:machine].id
46
+ )
47
+ domain_xml = libvirt_domain.xml_desc(1)
48
+ xml_descr = REXML::Document.new(domain_xml)
49
+ domain_name = xml_descr.elements['domain'].elements['name'].text
50
+ disks_xml = REXML::XPath.match(xml_descr, '/domain/devices/disk[@device="disk"]')
51
+ have_aliases = !REXML::XPath.match(disks_xml, './alias[@name="ua-box-volume-0"]').first.nil?
52
+ env[:ui].warn(I18n.t('vagrant_libvirt.domain_xml.obsolete_method')) unless have_aliases
53
+
54
+ if have_aliases
55
+ REXML::XPath.match(disks_xml,
56
+ './alias[contains(@name, "ua-box-volume-")]').each_with_index do |alias_xml, idx|
57
+ domain_volumes.push(volume_from_xml(alias_xml.parent, domain_name, idx))
58
+ end
59
+ else
60
+ # fallback to try and infer which boxes are box images, as they are listed first
61
+ # as soon as there is no match, can exit
62
+ disks_xml.each_with_index do |box_disk_xml, idx|
63
+ diskname = box_disk_xml.elements['source'].attributes['file'].rpartition('/').last
64
+
65
+ break if volume_name(domain_name, idx) != diskname
66
+
67
+ domain_volumes.push(volume_from_xml(box_disk_xml, domain_name, idx))
68
+ end
69
+ end
70
+ else
71
+
72
+ @logger.debug "Search for volumes in pool: #{pool_name}"
73
+ env[:box_volumes].each_index do |index|
74
+ domain_volume = env[:machine].provider.driver.connection.volumes.all(
75
+ name: volume_name(domain_name, index)
76
+ ).find { |x| x.pool_name == pool_name }
77
+ raise Errors::NoDomainVolume if domain_volume.nil?
78
+
79
+ domain_volumes.push(
80
+ {
81
+ name: volume_name(domain_name, index),
82
+ device: env[:box_volumes][index][:device],
83
+ cache: domain_volume_cache,
84
+ bus: disk_bus,
85
+ absolute_path: domain_volume.path,
86
+ virtual_size: env[:box_volumes][index][:virtual_size],
87
+ pool: pool_name,
88
+ }
89
+ )
90
+ end
91
+ end
92
+
93
+ resolver.resolve!(domain_volumes)
94
+
95
+ # If we have a box, take the path from the domain volume and set our storage_prefix.
96
+ # If not, we dump the storage pool xml to get its defined path.
97
+ # the default storage prefix is typically: /var/lib/libvirt/images/
98
+ storage_prefix = "#{File.dirname(domain_volumes[0][:absolute_path])}/" # steal
99
+ else
100
+ # Ensure domain name is set for subsequent steps if restarting a machine without a box
101
+ libvirt_domain = env[:machine].provider.driver.connection.client.lookup_domain_by_uuid(
102
+ env[:machine].id
103
+ )
104
+ domain_xml = libvirt_domain.xml_desc(1)
105
+ xml_descr = REXML::Document.new(domain_xml)
106
+ domain_name = xml_descr.elements['domain'].elements['name'].text
107
+
108
+ storage_prefix = get_disk_storage_prefix(env[:machine], storage_pool_name)
109
+ end
110
+
111
+ resolver.resolve!(disks)
112
+
113
+ disks.each do |disk|
114
+ disk[:path] ||= disk_name(domain_name, disk)
115
+
116
+ # On volume creation, the <path> element inside <target>
117
+ # is oddly ignored; instead the path is taken from the
118
+ # <name> element:
119
+ # http://www.redhat.com/archives/libvir-list/2008-August/msg00329.html
120
+ disk[:name] = disk[:path]
121
+
122
+ disk[:absolute_path] = storage_prefix + disk[:path]
123
+
124
+ if disk[:pool].nil?
125
+ disk[:pool] = storage_pool_name
126
+ else
127
+ @logger.debug "Overriding pool name with: #{disk[:pool]}"
128
+ disk_storage_prefix = get_disk_storage_prefix(env[:machine], disk[:pool])
129
+ disk[:absolute_path] = disk_storage_prefix + disk[:path]
130
+ @logger.debug "Overriding disk path with: #{disk[:absolute_path]}"
131
+ end
132
+ end
133
+
134
+ env[:domain_volumes] = domain_volumes
135
+ env[:disks] = disks
136
+
137
+ @app.call(env)
138
+ end
139
+
140
+ private
141
+
142
+ def disk_name(name, disk)
143
+ "#{name}-#{disk[:device]}.#{disk[:type]}" # disk name
144
+ end
145
+
146
+ def get_disk_storage_prefix(machine, disk_pool_name)
147
+ disk_storage_pool = machine.provider.driver.connection.client.lookup_storage_pool_by_name(disk_pool_name)
148
+ raise Errors::NoStoragePool if disk_storage_pool.nil?
149
+
150
+ xml = Nokogiri::XML(disk_storage_pool.xml_desc)
151
+ "#{xml.xpath('/pool/target/path').inner_text}/"
152
+ end
153
+
154
+ def volume_name(domain_name, index)
155
+ domain_name + (index.zero? ? '.img' : "_#{index}.img")
156
+ end
157
+
158
+ def volume_from_xml(device_xml, domain_name, index)
159
+ driver = device_xml.elements['driver']
160
+ source = device_xml.elements['source']
161
+ target = device_xml.elements['target']
162
+
163
+ {
164
+ name: volume_name(domain_name, index),
165
+ device: target.attributes['dev'],
166
+ cache: driver.attributes['cache'],
167
+ bus: target.attributes['bus'],
168
+ absolute_path: source.attributes['file'],
169
+ }
170
+ end
171
+ end
172
+ end
173
+ end
174
+ end
@@ -375,10 +375,50 @@ module VagrantPlugins
375
375
  end
376
376
  end
377
377
 
378
+ loader = REXML::XPath.first(xml_descr, '/domain/os/loader')
379
+ if config.loader
380
+ if loader.nil?
381
+ descr_changed = true
382
+ loader = REXML::Element.new('loader')
383
+ REXML::XPath.first(xml_descr, '/domain/os').insert_after('//type', loader)
384
+ loader.text = config.loader
385
+ else
386
+ if (loader.text or '').strip != config.loader
387
+ descr_changed = true
388
+ loader.text = config.loader
389
+ end
390
+ end
391
+ loader.attributes['type'] = config.nvram ? 'pflash' : 'rom'
392
+ elsif !loader.nil?
393
+ descr_changed = true
394
+ loader.parent.delete_element(loader)
395
+ end
396
+
397
+ undefine_flags = 0
398
+ nvram = REXML::XPath.first(xml_descr, '/domain/os/nvram')
399
+ if config.nvram
400
+ if nvram.nil?
401
+ descr_changed = true
402
+ nvram = REXML::Element.new('nvram')
403
+ REXML::XPath.first(xml_descr, '/domain/os').insert_after(loader, nvram)
404
+ nvram.text = config.nvram
405
+ else
406
+ if (nvram.text or '').strip != config.nvram
407
+ descr_changed = true
408
+ nvram.text = config.nvram
409
+ end
410
+ undefine_flags |= ProviderLibvirt::Util::DomainFlags::VIR_DOMAIN_UNDEFINE_KEEP_NVRAM
411
+ end
412
+ elsif !nvram.nil?
413
+ descr_changed = true
414
+ undefine_flags |= ProviderLibvirt::Util::DomainFlags::VIR_DOMAIN_UNDEFINE_NVRAM
415
+ nvram.parent.delete_element(nvram)
416
+ end
417
+
378
418
  # Apply
379
419
  if descr_changed
380
420
  begin
381
- libvirt_domain.undefine
421
+ libvirt_domain.undefine(undefine_flags)
382
422
  new_descr = String.new
383
423
  xml_descr.write new_descr
384
424
  env[:machine].provider.driver.connection.servers.create(xml: new_descr)
@@ -35,6 +35,7 @@ module VagrantPlugins
35
35
  autoload :ReadMacAddresses, action_root.join('read_mac_addresses')
36
36
  autoload :RemoveLibvirtImage, action_root.join('remove_libvirt_image')
37
37
  autoload :RemoveStaleVolume, action_root.join('remove_stale_volume')
38
+ autoload :ResolveDiskSettings, action_root.join('resolve_disk_settings')
38
39
  autoload :ResumeDomain, action_root.join('resume_domain')
39
40
  autoload :SetNameOfDomain, action_root.join('set_name_of_domain')
40
41
  autoload :SetBootOrder, action_root.join('set_boot_order')
@@ -81,6 +82,7 @@ module VagrantPlugins
81
82
  b2.use SetNameOfDomain
82
83
 
83
84
  if !env[:machine].config.vm.box
85
+ b2.use ResolveDiskSettings
84
86
  b2.use CreateDomain
85
87
  b2.use CreateNetworks
86
88
  b2.use CreateNetworkInterfaces
@@ -94,6 +96,7 @@ module VagrantPlugins
94
96
  b2.use HandleBox
95
97
  b2.use HandleBoxImage
96
98
  b2.use CreateDomainVolume
99
+ b2.use ResolveDiskSettings
97
100
  b2.use CreateDomain
98
101
  b2.use CreateNetworks
99
102
  b2.use CreateNetworkInterfaces
@@ -104,6 +107,7 @@ module VagrantPlugins
104
107
  end
105
108
  else
106
109
  env[:halt_on_error] = true
110
+ b2.use ResolveDiskSettings
107
111
  b2.use CreateNetworks
108
112
  b2.use action_start
109
113
  end
@@ -994,6 +994,10 @@ module VagrantPlugins
994
994
  errors << "libvirt.qemu_use_agent must be a boolean."
995
995
  end
996
996
 
997
+ if !@nvram.nil? && @loader.nil?
998
+ errors << "use of 'nvram' requires a 'loader' to be specified, please add one to the configuration"
999
+ end
1000
+
997
1001
  if @qemu_use_agent == true
998
1002
  # if qemu agent is used to optain domain ip configuration, at least
999
1003
  # one qemu channel has to be configured. As there are various options,
@@ -117,9 +117,9 @@
117
117
  @disk_driver_opts.reject { |k,v| v.nil? }
118
118
  .map { |k,v| "#{k}='#{v}'"}
119
119
  .join(' ') -%>/>
120
- <source file='<%= volume[:path] %>'/>
120
+ <source file='<%= volume[:absolute_path] %>'/>
121
121
  <%# we need to ensure a unique target dev -%>
122
- <target dev='<%= volume[:dev] %>' bus='<%= volume[:bus] %>'/>
122
+ <target dev='<%= volume[:device] %>' bus='<%= volume[:bus] %>'/>
123
123
  </disk>
124
124
  <%- end -%>
125
125
  <%# additional disks -%>
@@ -0,0 +1,15 @@
1
+ # Ripped from https://libvirt.org/html/libvirt-libvirt-domain.html#types
2
+ module VagrantPlugins
3
+ module ProviderLibvirt
4
+ module Util
5
+ module DomainFlags
6
+ # virDomainUndefineFlagsValues
7
+ VIR_DOMAIN_UNDEFINE_MANAGED_SAVE = 1 # Also remove any managed save
8
+ VIR_DOMAIN_UNDEFINE_SNAPSHOTS_METADATA = 2 # If last use of domain, then also remove any snapshot metadata
9
+ VIR_DOMAIN_UNDEFINE_NVRAM = 4 # Also remove any nvram file
10
+ VIR_DOMAIN_UNDEFINE_KEEP_NVRAM = 8 # Keep nvram file
11
+ VIR_DOMAIN_UNDEFINE_CHECKPOINTS_METADATA = 16 # If last use of domain, then also remove any checkpoint metadata Future undefine control flags should come here.
12
+ end
13
+ end
14
+ end
15
+ end
@@ -9,6 +9,7 @@ module VagrantPlugins
9
9
  autoload :NetworkUtil, 'vagrant-libvirt/util/network_util'
10
10
  autoload :StorageUtil, 'vagrant-libvirt/util/storage_util'
11
11
  autoload :ErrorCodes, 'vagrant-libvirt/util/error_codes'
12
+ autoload :DomainFlags, 'vagrant-libvirt/util/domain_flags'
12
13
  autoload :Ui, 'vagrant-libvirt/util/ui'
13
14
  end
14
15
  end
@@ -1 +1 @@
1
- 0.8.2
1
+ 0.9.0
data/locales/en.yml CHANGED
@@ -58,9 +58,11 @@ en:
58
58
  remove_stale_volume: |-
59
59
  Remove stale volume...
60
60
 
61
- destroy:
61
+ domain_xml:
62
62
  obsolete_method: |
63
- Destroying machine that was originally created without device aliases (pre 0.6.0), using fallback approach.
63
+ Machine that was originally created without device aliases (pre 0.6.0), using fall-back approach for device identification.
64
+
65
+ destroy:
64
66
  unexpected_volumes: |
65
67
  Unexpected number of volumes detected, possibly additional volumes attached outside of vagrant-libvirt.
66
68
  Attempting to handle this correctly, however may experience unexpected behaviour in the domain destroy.
@@ -10,6 +10,7 @@ shared_context 'libvirt' do
10
10
  let(:libvirt_context) { true }
11
11
  let(:id) { 'dummy-vagrant_dummy' }
12
12
  let(:connection) { double('connection') }
13
+ let(:driver) { instance_double(VagrantPlugins::ProviderLibvirt::Driver) }
13
14
  let(:domain) { instance_double(::Fog::Libvirt::Compute::Server) }
14
15
  let(:libvirt_client) { instance_double(::Libvirt::Connect) }
15
16
  let(:libvirt_domain) { instance_double(::Libvirt::Domain) }
@@ -33,5 +34,8 @@ shared_context 'libvirt' do
33
34
 
34
35
  allow(machine).to receive(:id).and_return(id)
35
36
  allow(Log4r::Logger).to receive(:new).and_return(logger)
37
+
38
+ allow(machine.provider).to receive('driver').and_return(driver)
39
+ allow(driver).to receive(:connection).and_return(connection)
36
40
  end
37
41
  end
@@ -34,8 +34,6 @@ describe VagrantPlugins::ProviderLibvirt::Action::CleanupOnFailure do
34
34
  let(:state) { double('state') }
35
35
 
36
36
  before do
37
- allow_any_instance_of(VagrantPlugins::ProviderLibvirt::Driver)
38
- .to receive(:connection).and_return(connection)
39
37
  allow(machine).to receive(:id).and_return('test-machine-id')
40
38
  allow(machine).to receive(:state).and_return(state)
41
39