vagrant-libvirt 0.8.0 → 0.9.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 (41) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +9 -6
  3. data/lib/vagrant-libvirt/action/create_domain.rb +19 -91
  4. data/lib/vagrant-libvirt/action/destroy_domain.rb +20 -4
  5. data/lib/vagrant-libvirt/action/destroy_networks.rb +1 -1
  6. data/lib/vagrant-libvirt/action/handle_box_image.rb +2 -0
  7. data/lib/vagrant-libvirt/action/resolve_disk_settings.rb +174 -0
  8. data/lib/vagrant-libvirt/action/start_domain.rb +41 -1
  9. data/lib/vagrant-libvirt/action.rb +14 -6
  10. data/lib/vagrant-libvirt/config.rb +12 -4
  11. data/lib/vagrant-libvirt/templates/domain.xml.erb +13 -8
  12. data/lib/vagrant-libvirt/util/domain_flags.rb +15 -0
  13. data/lib/vagrant-libvirt/util.rb +1 -0
  14. data/lib/vagrant-libvirt/version +1 -1
  15. data/locales/en.yml +4 -2
  16. data/spec/support/libvirt_context.rb +4 -0
  17. data/spec/unit/action/cleanup_on_failure_spec.rb +0 -2
  18. data/spec/unit/action/create_domain_spec.rb +113 -147
  19. data/spec/unit/action/create_domain_volume_spec.rb +0 -3
  20. data/spec/unit/action/destroy_domain_spec.rb +43 -10
  21. data/spec/unit/action/handle_box_image_spec.rb +13 -13
  22. data/spec/unit/action/package_domain_spec.rb +0 -5
  23. data/spec/unit/action/resolve_disk_settings_spec/default_domain.xml +43 -0
  24. data/spec/unit/action/resolve_disk_settings_spec/default_no_aliases.xml +42 -0
  25. data/spec/unit/action/{create_domain_spec → resolve_disk_settings_spec}/default_system_storage_pool.xml +0 -0
  26. data/spec/unit/action/resolve_disk_settings_spec/multi_volume_box.xml +55 -0
  27. data/spec/unit/action/resolve_disk_settings_spec/multi_volume_box_additional_and_custom_no_aliases.xml +67 -0
  28. data/spec/unit/action/resolve_disk_settings_spec/multi_volume_box_additional_storage.xml +67 -0
  29. data/spec/unit/action/resolve_disk_settings_spec.rb +361 -0
  30. data/spec/unit/action/start_domain_spec/existing_added_nvram.xml +62 -0
  31. data/spec/unit/action/start_domain_spec/nvram_domain.xml +64 -0
  32. data/spec/unit/action/start_domain_spec/nvram_domain_other_setting.xml +64 -0
  33. data/spec/unit/action/start_domain_spec/nvram_domain_removed.xml +64 -0
  34. data/spec/unit/action/start_domain_spec.rb +64 -6
  35. data/spec/unit/action/wait_till_up_spec.rb +0 -2
  36. data/spec/unit/action_spec.rb +0 -3
  37. data/spec/unit/config_spec.rb +18 -0
  38. data/spec/unit/driver_spec.rb +2 -0
  39. data/spec/unit/templates/domain_all_settings.xml +8 -2
  40. data/spec/unit/templates/domain_spec.rb +3 -2
  41. metadata +38 -16
@@ -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 -%>
@@ -230,15 +230,20 @@
230
230
  <backend model='random'>/dev/random</backend>
231
231
  </rng>
232
232
  <%- end -%>
233
- <%- @pcis.each do |pci| -%>
233
+ <%-
234
+ @pcis.each do |pci|
235
+ pci = pci.reject { |k,v| v.nil? }
236
+ guest_prefix = "guest_"
237
+ pci_host = pci.select { |k,_| !k.to_s.start_with?(guest_prefix) }
238
+ pci_guest = pci.select { |k,_| k.to_s.start_with?(guest_prefix) }
239
+ -%>
234
240
  <hostdev mode='subsystem' type='pci' managed='yes'>
235
241
  <source>
236
- <address <%= pci.select { |k,_| [:domain, :bus, :slot, :function].include? k }
237
- .reject { |k,v| v.nil? }
238
- .map { |k,v| "#{k.to_s}='#{v}'" }
239
- .join(' ')
240
- -%>/>
242
+ <address <%= pci_host.map { |k,v| "#{k.to_s}='#{v}'" } .join(' ') -%>/>
241
243
  </source>
244
+ <%- if !pci_guest.empty? -%>
245
+ <address type='pci' <%= pci_guest.map { |k,v| "#{k.to_s[guest_prefix.length..-1]}='#{v}'" } .join(' ') -%>/>
246
+ <%- end -%>
242
247
  </hostdev>
243
248
  <%- end -%>
244
249
  <%- @usbs.each do |usb| -%>
@@ -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.0
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
 
@@ -21,15 +21,9 @@ describe VagrantPlugins::ProviderLibvirt::Action::CreateDomain do
21
21
  let(:domain_volume) { instance_double(::Fog::Libvirt::Compute::Volume) }
22
22
 
23
23
  let(:domain_xml) { File.read(File.join(File.dirname(__FILE__), File.basename(__FILE__, '.rb'), domain_xml_file)) }
24
- let(:storage_pool_xml) { File.read(File.join(File.dirname(__FILE__), File.basename(__FILE__, '.rb'), storage_pool_xml_file)) }
25
- let(:libvirt_storage_pool) { double('storage_pool') }
26
24
 
27
25
  describe '#call' do
28
26
  before do
29
- allow_any_instance_of(VagrantPlugins::ProviderLibvirt::Driver)
30
- .to receive(:connection).and_return(connection)
31
- allow(connection).to receive(:client).and_return(libvirt_client)
32
-
33
27
  allow(connection).to receive(:servers).and_return(servers)
34
28
  allow(connection).to receive(:volumes).and_return(volumes)
35
29
  allow(volumes).to receive(:all).and_return([domain_volume])
@@ -43,15 +37,17 @@ describe VagrantPlugins::ProviderLibvirt::Action::CreateDomain do
43
37
 
44
38
  env[:domain_name] = "vagrant-test_default"
45
39
 
46
- env[:box_volumes] = []
47
- env[:box_volumes].push({
40
+ env[:domain_volumes] = []
41
+ env[:domain_volumes].push({
42
+ :device=>'vda',
43
+ :bus=>'virtio',
44
+ :cache=>'default',
45
+ :absolute_path=>'/var/lib/libvirt/images/vagrant-test_default.img',
48
46
  :path=>"/test/box.img",
49
- :name=>"test_vagrant_box_image_1.1.1_0.img",
47
+ :name=>'test_vagrant_box_image_1.1.1_0.img',
50
48
  :virtual_size=> ByteNumber.new(5),
49
+ :pool=>'default',
51
50
  })
52
- # should be ignored for system session and used for user session
53
- allow(Process).to receive(:uid).and_return(9999)
54
- allow(Process).to receive(:gid).and_return(9999)
55
51
  end
56
52
 
57
53
  context 'connection => qemu:///system' do
@@ -61,123 +57,99 @@ describe VagrantPlugins::ProviderLibvirt::Action::CreateDomain do
61
57
  allow(machine.provider_config).to receive(:qemu_use_session).and_return(false)
62
58
  end
63
59
 
64
- context 'default pool' do
65
- it 'should execute correctly' do
66
- expect(servers).to receive(:create).with(xml: domain_xml).and_return(machine)
67
- expect(volumes).to_not receive(:create) # additional disks only
68
-
69
- expect(subject.call(env)).to be_nil
70
- end
71
-
72
- context 'with no box' do
73
- let(:storage_pool_xml_file) { 'default_system_storage_pool.xml' }
74
- let(:vagrantfile) do
75
- <<-EOF
76
- Vagrant.configure('2') do |config|
77
- config.vm.define :test
78
- end
79
- EOF
80
- end
60
+ it 'should execute correctly' do
61
+ expect(servers).to receive(:create).with(xml: domain_xml).and_return(machine)
62
+ expect(volumes).to_not receive(:create) # additional disks only
81
63
 
82
- it 'should query for the storage pool path' do
83
- expect(libvirt_client).to receive(:lookup_storage_pool_by_name).and_return(libvirt_storage_pool)
84
- expect(libvirt_storage_pool).to receive(:xml_desc).and_return(storage_pool_xml)
85
- expect(servers).to receive(:create).and_return(machine)
64
+ expect(subject.call(env)).to be_nil
65
+ end
86
66
 
87
- expect(subject.call(env)).to be_nil
88
- end
67
+ context 'additional disks' do
68
+ let(:disks) do
69
+ [
70
+ :device => 'vdb',
71
+ :cache => 'default',
72
+ :bus => 'virtio',
73
+ :type => 'qcow2',
74
+ :absolute_path => '/var/lib/libvirt/images/vagrant-test_default-vdb.qcow2',
75
+ :virtual_size => ByteNumber.new(20*1024*1024*1024),
76
+ :pool => 'default',
77
+ ]
89
78
  end
90
79
 
91
- context 'additional disks' do
92
- let(:vagrantfile_providerconfig) do
93
- <<-EOF
94
- libvirt.storage :file, :size => '20G'
95
- EOF
96
- end
97
-
98
- context 'volume create failed' do
99
- it 'should raise an exception' do
100
- expect(volumes).to receive(:create).and_raise(Libvirt::Error)
101
-
102
- expect{ subject.call(env) }.to raise_error(VagrantPlugins::ProviderLibvirt::Errors::FogCreateDomainVolumeError)
103
- end
104
- end
80
+ before do
81
+ env[:disks] = disks
82
+ end
105
83
 
106
- context 'volume create succeeded' do
107
- let(:domain_xml_file) { 'additional_disks_domain.xml' }
108
-
109
- it 'should complete' do
110
- expect(volumes).to receive(:create).with(
111
- hash_including(
112
- :path => "/var/lib/libvirt/images/vagrant-test_default-vdb.qcow2",
113
- :owner => 0,
114
- :group => 0,
115
- :pool_name => "default",
116
- )
117
- )
118
- expect(servers).to receive(:create).with(xml: domain_xml).and_return(machine)
84
+ context 'volume create failed' do
85
+ it 'should raise an exception' do
86
+ expect(volumes).to receive(:create).and_raise(Libvirt::Error)
119
87
 
120
- expect(subject.call(env)).to be_nil
121
- end
88
+ expect{ subject.call(env) }.to raise_error(VagrantPlugins::ProviderLibvirt::Errors::FogCreateDomainVolumeError)
122
89
  end
123
90
  end
124
91
 
125
- context 'with custom disk device setting' do
126
- let(:domain_xml_file) { 'custom_disk_settings.xml' }
127
- let(:vagrantfile_providerconfig) {
128
- <<-EOF
129
- libvirt.disk_device = 'sda'
130
- EOF
131
- }
92
+ context 'volume create succeeded' do
93
+ let(:domain_xml_file) { 'additional_disks_domain.xml' }
132
94
 
133
- it 'should set the domain device' do
134
- expect(ui).to receive(:info).with(/ -- Image\(sda\):.*/)
95
+ it 'should complete' do
96
+ expect(volumes).to receive(:create).with(
97
+ hash_including(
98
+ :path => "/var/lib/libvirt/images/vagrant-test_default-vdb.qcow2",
99
+ :owner => 0,
100
+ :group => 0,
101
+ :pool_name => "default",
102
+ )
103
+ )
135
104
  expect(servers).to receive(:create).with(xml: domain_xml).and_return(machine)
136
105
 
137
106
  expect(subject.call(env)).to be_nil
138
107
  end
139
108
  end
109
+ end
140
110
 
141
- context 'with two domain disks' do
142
- let(:domain_xml_file) { 'two_disk_settings.xml' }
143
- let(:domain_volume_2) { double('domain_volume 2') }
144
-
145
- before do
146
- expect(volumes).to receive(:all).and_return([domain_volume])
147
- expect(volumes).to receive(:all).and_return([domain_volume_2])
148
- expect(domain_volume_2).to receive(:pool_name).and_return('default')
149
- expect(domain_volume_2).to receive(:path).and_return('/var/lib/libvirt/images/vagrant-test_default_1.img')
150
-
151
- env[:box_volumes].push({
152
- :path=>"/test/box_1.img",
153
- :name=>"test_vagrant_box_image_1.1.1_1.img",
154
- :virtual_size=> ByteNumber.new(5),
155
- })
156
- end
111
+ context 'with custom disk device setting' do
112
+ let(:domain_xml_file) { 'custom_disk_settings.xml' }
157
113
 
158
- it 'should correctly assign device entries' do
159
- expect(ui).to receive(:info).with(/ -- Image\(vda\):.*/)
160
- expect(ui).to receive(:info).with(/ -- Image\(vdb\):.*/)
161
- expect(servers).to receive(:create).with(xml: domain_xml).and_return(machine)
114
+ before do
115
+ env[:domain_volumes][0][:device] = 'sda'
116
+ end
162
117
 
163
- expect(subject.call(env)).to be_nil
164
- end
118
+ it 'should set the domain device' do
119
+ expect(ui).to receive(:info).with(/ -- Image\(sda\):.*/)
120
+ expect(servers).to receive(:create).with(xml: domain_xml).and_return(machine)
121
+
122
+ expect(subject.call(env)).to be_nil
165
123
  end
166
124
  end
167
125
 
168
- context 'no default pool' do
169
- let(:vagrantfile) do
170
- <<-EOF
171
- Vagrant.configure('2') do |config|
172
- config.vm.define :test
173
- end
174
- EOF
126
+ context 'with two domain disks' do
127
+ let(:domain_xml_file) { 'two_disk_settings.xml' }
128
+ let(:domain_volume_2) { double('domain_volume 2') }
129
+
130
+ before do
131
+ expect(volumes).to receive(:all).with(name: 'vagrant-test_default.img').and_return([domain_volume])
132
+ expect(volumes).to receive(:all).with(name: 'vagrant-test_default_1.img').and_return([domain_volume_2])
133
+ expect(domain_volume_2).to receive(:pool_name).and_return('default')
134
+
135
+ env[:domain_volumes].push({
136
+ :device=>'vdb',
137
+ :bus=>'virtio',
138
+ :cache=>'default',
139
+ :absolute_path=>'/var/lib/libvirt/images/vagrant-test_default_1.img',
140
+ :path=>"/test/box_1.img",
141
+ :name=>"test_vagrant_box_image_1.1.1_1.img",
142
+ :virtual_size=> ByteNumber.new(5),
143
+ :pool=>'default',
144
+ })
175
145
  end
176
146
 
177
- it 'should raise an exception' do
178
- expect(libvirt_client).to receive(:lookup_storage_pool_by_name).and_return(nil)
147
+ it 'should list multiple device entries' do
148
+ expect(ui).to receive(:info).with(/ -- Image\(vda\):.*/)
149
+ expect(ui).to receive(:info).with(/ -- Image\(vdb\):.*/)
150
+ expect(servers).to receive(:create).with(xml: domain_xml).and_return(machine)
179
151
 
180
- expect{ subject.call(env) }.to raise_error(VagrantPlugins::ProviderLibvirt::Errors::NoStoragePool)
152
+ expect(subject.call(env)).to be_nil
181
153
  end
182
154
  end
183
155
  end
@@ -187,57 +159,51 @@ describe VagrantPlugins::ProviderLibvirt::Action::CreateDomain do
187
159
  allow(machine.provider_config).to receive(:qemu_use_session).and_return(true)
188
160
  end
189
161
 
190
- context 'default pool' do
191
- it 'should execute correctly' do
192
- expect(servers).to receive(:create).and_return(machine)
162
+ it 'should execute correctly' do
163
+ expect(servers).to receive(:create).and_return(machine)
193
164
 
194
- expect(subject.call(env)).to be_nil
165
+ expect(subject.call(env)).to be_nil
166
+ end
167
+
168
+ context 'additional disks' do
169
+ let(:vagrantfile_providerconfig) do
170
+ <<-EOF
171
+ libvirt.qemu_use_session = true
172
+ EOF
195
173
  end
196
174
 
197
- context 'with no box' do
198
- let(:storage_pool_xml_file) { 'default_user_storage_pool.xml' }
199
- let(:vagrantfile) do
200
- <<-EOF
201
- Vagrant.configure('2') do |config|
202
- config.vm.define :test
203
- config.vm.provider :libvirt do |libvirt|
204
- #{vagrantfile_providerconfig}
205
- end
206
- end
207
- EOF
208
- end
175
+ let(:disks) do
176
+ [
177
+ :device => 'vdb',
178
+ :cache => 'default',
179
+ :bus => 'virtio',
180
+ :type => 'qcow2',
181
+ :absolute_path => '/var/lib/libvirt/images/vagrant-test_default-vdb.qcow2',
182
+ :virtual_size => ByteNumber.new(20*1024*1024*1024),
183
+ :pool => 'default',
184
+ ]
185
+ end
209
186
 
210
- it 'should query for the storage pool path' do
211
- expect(libvirt_client).to receive(:lookup_storage_pool_by_name).and_return(libvirt_storage_pool)
212
- expect(libvirt_storage_pool).to receive(:xml_desc).and_return(storage_pool_xml)
213
- expect(servers).to receive(:create).and_return(machine)
187
+ before do
188
+ expect(Process).to receive(:uid).and_return(9999).at_least(:once)
189
+ expect(Process).to receive(:gid).and_return(9999).at_least(:once)
214
190
 
215
- expect(subject.call(env)).to be_nil
216
- end
191
+ env[:disks] = disks
217
192
  end
218
193
 
219
- context 'additional disks' do
220
- let(:vagrantfile_providerconfig) do
221
- <<-EOF
222
- libvirt.qemu_use_session = true
223
- libvirt.storage :file, :size => '20G'
224
- EOF
225
- end
226
-
227
- context 'volume create succeeded' do
228
- it 'should complete' do
229
- expect(volumes).to receive(:create).with(
230
- hash_including(
231
- :path => "/var/lib/libvirt/images/vagrant-test_default-vdb.qcow2",
232
- :owner => 9999,
233
- :group => 9999,
234
- :pool_name => "default",
235
- )
194
+ context 'volume create succeeded' do
195
+ it 'should complete' do
196
+ expect(volumes).to receive(:create).with(
197
+ hash_including(
198
+ :path => "/var/lib/libvirt/images/vagrant-test_default-vdb.qcow2",
199
+ :owner => 9999,
200
+ :group => 9999,
201
+ :pool_name => "default",
236
202
  )
237
- expect(servers).to receive(:create).and_return(machine)
203
+ )
204
+ expect(servers).to receive(:create).and_return(machine)
238
205
 
239
- expect(subject.call(env)).to be_nil
240
- end
206
+ expect(subject.call(env)).to be_nil
241
207
  end
242
208
  end
243
209
  end
@@ -26,9 +26,6 @@ describe VagrantPlugins::ProviderLibvirt::Action::CreateDomainVolume do
26
26
 
27
27
  describe '#call' do
28
28
  before do
29
- allow_any_instance_of(VagrantPlugins::ProviderLibvirt::Driver)
30
- .to receive(:connection).and_return(connection)
31
- allow(connection).to receive(:client).and_return(libvirt_client)
32
29
  allow(connection).to receive(:volumes).and_return(volumes)
33
30
  allow(volumes).to receive(:all).and_return(all)
34
31
  allow(all).to receive(:first).and_return(box_volume)
@@ -19,10 +19,14 @@ describe VagrantPlugins::ProviderLibvirt::Action::DestroyDomain do
19
19
 
20
20
  let(:domain_xml) { File.read(File.join(File.dirname(__FILE__), File.basename(__FILE__, '.rb'), domain_xml_file)) }
21
21
 
22
+ let(:destroy_method) { double('destroy_method') }
23
+
22
24
  before do
23
25
  allow(machine.provider).to receive('driver').and_return(driver)
24
26
  allow(driver).to receive(:connection).and_return(connection)
25
27
  allow(logger).to receive(:info)
28
+ allow(domain).to receive(:method).with(:destroy).and_return(destroy_method)
29
+ allow(destroy_method).to receive(:parameters).and_return([[:opt, :options, :flags]])
26
30
  end
27
31
 
28
32
  describe '#call' do
@@ -49,7 +53,7 @@ describe VagrantPlugins::ProviderLibvirt::Action::DestroyDomain do
49
53
 
50
54
  context 'when box only has one root disk' do
51
55
  it 'calls fog to destroy volumes' do
52
- expect(domain).to receive(:destroy).with(destroy_volumes: true)
56
+ expect(domain).to receive(:destroy).with(destroy_volumes: true, flags: 0)
53
57
  expect(subject.call(env)).to be_nil
54
58
  end
55
59
 
@@ -69,7 +73,7 @@ describe VagrantPlugins::ProviderLibvirt::Action::DestroyDomain do
69
73
  end
70
74
 
71
75
  it 'destroys disks individually' do
72
- expect(domain).to receive(:destroy).with(destroy_volumes: false)
76
+ expect(domain).to receive(:destroy).with(destroy_volumes: false, flags: 0)
73
77
  expect(extra_disk).to receive(:destroy) # extra disk remove
74
78
  expect(root_disk).to receive(:destroy) # root disk remove
75
79
  expect(subject.call(env)).to be_nil
@@ -81,7 +85,7 @@ describe VagrantPlugins::ProviderLibvirt::Action::DestroyDomain do
81
85
  let(:domain_xml_file) { 'box_multiple_disks.xml' }
82
86
 
83
87
  it 'calls fog to destroy volumes' do
84
- expect(domain).to receive(:destroy).with(destroy_volumes: true)
88
+ expect(domain).to receive(:destroy).with(destroy_volumes: true, flags: 0)
85
89
  expect(subject.call(env)).to be_nil
86
90
  end
87
91
 
@@ -111,7 +115,7 @@ describe VagrantPlugins::ProviderLibvirt::Action::DestroyDomain do
111
115
  expect(disk).to receive(:name).and_return(name).at_least(:once)
112
116
  expect(disk).to receive(:destroy)
113
117
  end
114
- expect(domain).to receive(:destroy).with(destroy_volumes: false)
118
+ expect(domain).to receive(:destroy).with(destroy_volumes: false, flags: 0)
115
119
  expect(subject.call(env)).to be_nil
116
120
  end
117
121
 
@@ -133,7 +137,7 @@ describe VagrantPlugins::ProviderLibvirt::Action::DestroyDomain do
133
137
  next if disk == domain_disks.last.first
134
138
  expect(disk).to receive(:destroy)
135
139
  end
136
- expect(domain).to receive(:destroy).with(destroy_volumes: false)
140
+ expect(domain).to receive(:destroy).with(destroy_volumes: false, flags: 0)
137
141
  expect(subject.call(env)).to be_nil
138
142
  end
139
143
 
@@ -141,7 +145,7 @@ describe VagrantPlugins::ProviderLibvirt::Action::DestroyDomain do
141
145
  let(:domain_xml_file) { 'box_multiple_disks_and_additional_and_custom_disks_no_aliases.xml' }
142
146
 
143
147
  it 'only destroys expected disks' do
144
- expect(ui).to receive(:warn).with(/Destroying machine that was originally created without device aliases.*/)
148
+ expect(ui).to receive(:warn).with(/Machine that was originally created without device aliases.*/)
145
149
  expect(ui).to receive(:warn).with(/Unexpected number of volumes detected/)
146
150
  expect(ui).to receive(:warn).with(/box metadata not available to get volume list during destroy, assuming inferred list/)
147
151
  domain_disks.each do |disk, name|
@@ -150,7 +154,7 @@ describe VagrantPlugins::ProviderLibvirt::Action::DestroyDomain do
150
154
  next if domain_disks.last.first == disk
151
155
  expect(disk).to receive(:destroy)
152
156
  end
153
- expect(domain).to receive(:destroy).with(destroy_volumes: false)
157
+ expect(domain).to receive(:destroy).with(destroy_volumes: false, flags: 0)
154
158
  expect(subject.call(env)).to be_nil
155
159
  end
156
160
 
@@ -168,7 +172,7 @@ describe VagrantPlugins::ProviderLibvirt::Action::DestroyDomain do
168
172
  end
169
173
 
170
174
  it 'only destroys expected disks' do
171
- expect(ui).to receive(:warn).with(/Destroying machine that was originally created without device aliases.*/)
175
+ expect(ui).to receive(:warn).with(/Machine that was originally created without device aliases.*/)
172
176
  expect(ui).to receive(:warn).with(/Unexpected number of volumes detected/)
173
177
  domain_disks.each do |disk, name|
174
178
  expect(disk).to receive(:name).and_return(name).at_least(:once)
@@ -176,7 +180,7 @@ describe VagrantPlugins::ProviderLibvirt::Action::DestroyDomain do
176
180
  next if domain_disks.last.first == disk
177
181
  expect(disk).to receive(:destroy)
178
182
  end
179
- expect(domain).to receive(:destroy).with(destroy_volumes: false)
183
+ expect(domain).to receive(:destroy).with(destroy_volumes: false, flags: 0)
180
184
  expect(subject.call(env)).to be_nil
181
185
  end
182
186
  end
@@ -185,6 +189,35 @@ describe VagrantPlugins::ProviderLibvirt::Action::DestroyDomain do
185
189
  end
186
190
  end
187
191
 
192
+ context 'when has nvram' do
193
+ let(:vagrantfile) do
194
+ <<-EOF
195
+ Vagrant.configure('2') do |config|
196
+ config.vm.define :test
197
+ config.vm.provider :libvirt do |libvirt|
198
+ libvirt.nvram = "test"
199
+ end
200
+ end
201
+ EOF
202
+ end
203
+
204
+ it 'sets destroy flags to keep nvram' do
205
+ expect(domain).to receive(:destroy).with(destroy_volumes: true, flags: VagrantPlugins::ProviderLibvirt::Util::DomainFlags::VIR_DOMAIN_UNDEFINE_KEEP_NVRAM)
206
+ expect(subject.call(env)).to be_nil
207
+ end
208
+
209
+ context 'when fog does not support destroy with flags' do
210
+ before do
211
+ expect(destroy_method).to receive(:parameters).and_return([[:opt, :options]])
212
+ end
213
+
214
+ it 'skips setting additional destroy flags' do
215
+ expect(domain).to receive(:destroy).with(destroy_volumes: true)
216
+ expect(subject.call(env)).to be_nil
217
+ end
218
+ end
219
+ end
220
+
188
221
  context 'when has CDROMs attached' do
189
222
  let(:vagrantfile_providerconfig) do
190
223
  <<-EOF
@@ -197,7 +230,7 @@ describe VagrantPlugins::ProviderLibvirt::Action::DestroyDomain do
197
230
  expect(domain).to receive(:volumes).and_return([root_disk, nil])
198
231
  expect(libvirt_domain).to receive(:xml_desc).and_return(domain_xml)
199
232
 
200
- expect(domain).to_not receive(:destroy).with(destroy_volumes: true)
233
+ expect(domain).to_not receive(:destroy).with(destroy_volumes: true, flags: 0)
201
234
  expect(root_disk).to receive(:destroy) # root disk remove
202
235
  expect(subject.call(env)).to be_nil
203
236
  end