vagrant-libvirt 0.4.0 → 0.5.3

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 (52) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +251 -33
  3. data/lib/vagrant-libvirt/action.rb +7 -1
  4. data/lib/vagrant-libvirt/action/clean_machine_folder.rb +30 -0
  5. data/lib/vagrant-libvirt/action/create_domain.rb +28 -11
  6. data/lib/vagrant-libvirt/action/create_domain_volume.rb +57 -55
  7. data/lib/vagrant-libvirt/action/create_network_interfaces.rb +0 -3
  8. data/lib/vagrant-libvirt/action/create_networks.rb +11 -4
  9. data/lib/vagrant-libvirt/action/destroy_domain.rb +1 -1
  10. data/lib/vagrant-libvirt/action/forward_ports.rb +36 -37
  11. data/lib/vagrant-libvirt/action/halt_domain.rb +25 -9
  12. data/lib/vagrant-libvirt/action/handle_box_image.rb +170 -77
  13. data/lib/vagrant-libvirt/action/is_running.rb +1 -3
  14. data/lib/vagrant-libvirt/action/is_suspended.rb +4 -4
  15. data/lib/vagrant-libvirt/action/set_boot_order.rb +6 -2
  16. data/lib/vagrant-libvirt/action/wait_till_up.rb +1 -25
  17. data/lib/vagrant-libvirt/cap/{mount_p9.rb → mount_9p.rb} +2 -2
  18. data/lib/vagrant-libvirt/cap/mount_virtiofs.rb +37 -0
  19. data/lib/vagrant-libvirt/cap/{synced_folder.rb → synced_folder_9p.rb} +4 -5
  20. data/lib/vagrant-libvirt/cap/synced_folder_virtiofs.rb +109 -0
  21. data/lib/vagrant-libvirt/config.rb +34 -2
  22. data/lib/vagrant-libvirt/driver.rb +3 -1
  23. data/lib/vagrant-libvirt/errors.rb +24 -1
  24. data/lib/vagrant-libvirt/plugin.rb +14 -5
  25. data/lib/vagrant-libvirt/templates/domain.xml.erb +7 -6
  26. data/lib/vagrant-libvirt/templates/private_network.xml.erb +1 -1
  27. data/lib/vagrant-libvirt/util/byte_number.rb +71 -0
  28. data/lib/vagrant-libvirt/util/network_util.rb +21 -3
  29. data/lib/vagrant-libvirt/version +1 -1
  30. data/locales/en.yml +12 -0
  31. data/spec/spec_helper.rb +9 -1
  32. data/spec/support/binding_proc.rb +24 -0
  33. data/spec/support/matchers/have_file_content.rb +63 -0
  34. data/spec/unit/action/clean_machine_folder_spec.rb +58 -0
  35. data/spec/unit/action/create_domain_spec.rb +15 -5
  36. data/spec/unit/action/create_domain_spec/additional_disks_domain.xml +54 -0
  37. data/spec/unit/action/create_domain_spec/default_domain.xml +49 -0
  38. data/spec/unit/action/create_domain_volume_spec.rb +104 -0
  39. data/spec/unit/action/create_domain_volume_spec/one_disk_in_storage.xml +21 -0
  40. data/spec/unit/action/create_domain_volume_spec/three_disks_in_storage_disk_0.xml +21 -0
  41. data/spec/unit/action/create_domain_volume_spec/three_disks_in_storage_disk_1.xml +21 -0
  42. data/spec/unit/action/create_domain_volume_spec/three_disks_in_storage_disk_2.xml +21 -0
  43. data/spec/unit/action/destroy_domain_spec.rb +1 -1
  44. data/spec/unit/action/forward_ports_spec.rb +202 -0
  45. data/spec/unit/action/halt_domain_spec.rb +90 -0
  46. data/spec/unit/action/handle_box_image_spec.rb +441 -0
  47. data/spec/unit/action/wait_till_up_spec.rb +11 -15
  48. data/spec/unit/config_spec.rb +12 -9
  49. data/spec/unit/templates/domain_all_settings.xml +8 -0
  50. data/spec/unit/templates/domain_spec.rb +20 -1
  51. data/spec/unit/util/byte_number_spec.rb +26 -0
  52. metadata +52 -18
@@ -0,0 +1,90 @@
1
+ require 'spec_helper'
2
+ require 'support/sharedcontext'
3
+ require 'support/libvirt_context'
4
+ require 'vagrant-libvirt/action/destroy_domain'
5
+
6
+ describe VagrantPlugins::ProviderLibvirt::Action::HaltDomain do
7
+ subject { described_class.new(app, env) }
8
+
9
+ include_context 'unit'
10
+ include_context 'libvirt'
11
+
12
+ let(:libvirt_domain) { double('libvirt_domain') }
13
+ let(:servers) { double('servers') }
14
+
15
+ describe '#call' do
16
+ before do
17
+ allow_any_instance_of(VagrantPlugins::ProviderLibvirt::Driver)
18
+ .to receive(:connection).and_return(connection)
19
+ allow(connection).to receive(:servers).and_return(servers)
20
+ allow(servers).to receive(:get).and_return(domain)
21
+ # always see this at the start of #call
22
+ expect(ui).to receive(:info).with('Halting domain...')
23
+ end
24
+
25
+ context 'with graceful timeout' do
26
+ it "should shutdown" do
27
+ expect(guest).to receive(:capability).with(:halt).and_return(true)
28
+ expect(domain).to receive(:wait_for).with(60).and_return(false)
29
+ expect(subject.call(env)).to be_nil
30
+ end
31
+
32
+ context 'when halt fails' do
33
+ before do
34
+ expect(logger).to receive(:info).with('Trying Libvirt graceful shutdown.')
35
+ expect(guest).to receive(:capability).with(:halt).and_raise(IOError)
36
+ expect(domain).to receive(:state).and_return('running')
37
+ end
38
+
39
+ it "should call shutdown" do
40
+ expect(domain).to receive(:shutdown)
41
+ expect(domain).to receive(:wait_for).with(60).and_return(false)
42
+ expect(subject.call(env)).to be_nil
43
+ end
44
+
45
+ context 'when shutdown fails' do
46
+ it "should call power off" do
47
+ expect(logger).to receive(:error).with('Failed to shutdown cleanly. Calling force poweroff.')
48
+ expect(domain).to receive(:shutdown).and_raise(IOError)
49
+ expect(domain).to receive(:poweroff)
50
+ expect(subject.call(env)).to be_nil
51
+ end
52
+ end
53
+
54
+ context 'when shutdown exceeds the timeout' do
55
+ it "should call poweroff" do
56
+ expect(logger).to receive(:info).with('VM is still running. Calling force poweroff.')
57
+ expect(domain).to receive(:shutdown).and_raise(Timeout::Error)
58
+ expect(domain).to receive(:poweroff)
59
+ expect(subject.call(env)).to be_nil
60
+ end
61
+ end
62
+ end
63
+
64
+ context 'when halt exceeds the timeout' do
65
+ before do
66
+ expect(logger).to_not receive(:info).with('Trying Libvirt graceful shutdown.')
67
+ expect(guest).to receive(:capability).with(:halt).and_raise(Timeout::Error)
68
+ end
69
+
70
+ it "should call poweroff" do
71
+ expect(logger).to receive(:info).with('VM is still running. Calling force poweroff.')
72
+ expect(domain).to receive(:poweroff)
73
+ expect(subject.call(env)).to be_nil
74
+ end
75
+ end
76
+ end
77
+
78
+ context 'with force halt enabled' do
79
+ before do
80
+ allow(env).to receive(:[]).and_call_original
81
+ expect(env).to receive(:[]).with(:force_halt).and_return(true)
82
+ end
83
+
84
+ it "should just call poweroff" do
85
+ expect(domain).to receive(:poweroff)
86
+ expect(subject.call(env)).to be_nil
87
+ end
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,441 @@
1
+ require 'spec_helper'
2
+ require 'json'
3
+ require 'support/sharedcontext'
4
+ require 'support/libvirt_context'
5
+
6
+ require 'vagrant-libvirt/action/destroy_domain'
7
+ require 'vagrant-libvirt/util/byte_number'
8
+
9
+
10
+ describe VagrantPlugins::ProviderLibvirt::Action::HandleBoxImage do
11
+ subject { described_class.new(app, env) }
12
+
13
+ include_context 'unit'
14
+ include_context 'libvirt'
15
+
16
+ let(:libvirt_client) { double('libvirt_client') }
17
+ let(:volumes) { double('volumes') }
18
+ let(:all) { double('all') }
19
+ let(:box_volume) { double('box_volume') }
20
+ let(:fog_volume) { double('fog_volume') }
21
+ let(:config) { double('config') }
22
+
23
+ qemu_json_return_5G = JSON.dump({
24
+ "virtual-size": 5368709120,
25
+ "filename": "/test/box.img",
26
+ "cluster-size": 65536,
27
+ "format": "qcow2",
28
+ "actual-size": 655360,
29
+ "dirty-flag": false
30
+ })
31
+ byte_number_5G = ByteNumber.new(5368709120)
32
+
33
+
34
+ qemu_json_return_10G = JSON.dump({
35
+ "virtual-size": 10737423360,
36
+ "filename": "/test/disk.qcow2",
37
+ "cluster-size": 65536,
38
+ "format": "qcow2",
39
+ "actual-size": 655360,
40
+ "dirty-flag": false
41
+ })
42
+ byte_number_10G = ByteNumber.new(10737423360)
43
+
44
+ qemu_json_return_20G = JSON.dump({
45
+ "virtual-size": 21474836480,
46
+ "filename": "/test/box_2.img",
47
+ "cluster-size": 65536,
48
+ "format": "qcow2",
49
+ "actual-size": 1508708352,
50
+ "dirty-flag": false
51
+ })
52
+ byte_number_20G = ByteNumber.new(21474836480)
53
+
54
+
55
+
56
+
57
+ describe '#call' do
58
+ before do
59
+ allow_any_instance_of(VagrantPlugins::ProviderLibvirt::Driver)
60
+ .to receive(:connection).and_return(connection)
61
+ allow(connection).to receive(:client).and_return(libvirt_client)
62
+ allow(connection).to receive(:volumes).and_return(volumes)
63
+ allow(volumes).to receive(:all).and_return(all)
64
+ allow(env[:ui]).to receive(:clear_line)
65
+
66
+ end
67
+
68
+ context 'when one disk in metadata.json' do
69
+ before do
70
+ allow(all).to receive(:first).and_return(box_volume)
71
+ allow(box_volume).to receive(:id).and_return(1)
72
+ allow(env[:machine]).to receive_message_chain("box.name") { 'test' }
73
+ allow(env[:machine]).to receive_message_chain("box.version") { '1.1.1' }
74
+ allow(env[:machine]).to receive_message_chain("box.metadata") { Hash[
75
+ 'virtual_size'=> 5,
76
+ 'format' => 'qcow2'
77
+ ]
78
+ }
79
+ allow(env[:machine]).to receive_message_chain("box.directory.join") do |arg|
80
+ '/test/'.concat(arg.to_s)
81
+ end
82
+ end
83
+
84
+ it 'should have one disk in machine env' do
85
+ expect(subject.call(env)).to be_nil
86
+ expect(env[:box_volume_number]).to eq(1)
87
+ expect(env[:box_volumes]).to eq(
88
+ [
89
+ {
90
+ :path=>"/test/box.img",
91
+ :name=>"test_vagrant_box_image_1.1.1_box.img",
92
+ :virtual_size=>byte_number_5G,
93
+ :format=>"qcow2"
94
+ }
95
+ ]
96
+ )
97
+ end
98
+
99
+ context 'When config.machine_virtual_size is set and smaller than box_virtual_size' do
100
+ before do
101
+ allow(env[:machine]).to receive_message_chain("provider_config.machine_virtual_size").and_return(1)
102
+ end
103
+ it 'should warning must be raise' do
104
+ expect(ui).to receive(:warn).with("Ignoring requested virtual disk size of '1' as it is below\nthe minimum box image size of '5'.")
105
+ expect(subject.call(env)).to be_nil
106
+ expect(env[:box_volumes]).to eq(
107
+ [
108
+ {
109
+ :path=>"/test/box.img",
110
+ :name=>"test_vagrant_box_image_1.1.1_box.img",
111
+ :virtual_size=>byte_number_5G,
112
+ :format=>"qcow2"
113
+ }
114
+ ]
115
+ )
116
+ end
117
+ end
118
+
119
+ context 'When config.machine_virtual_size is set and higher than box_virtual_size' do
120
+ before do
121
+ allow(env[:machine]).to receive_message_chain("provider_config.machine_virtual_size").and_return(20)
122
+ end
123
+ it 'should be use' do
124
+ expect(ui).to receive(:info).with("Created volume larger than box defaults, will require manual resizing of\nfilesystems to utilize.")
125
+ expect(subject.call(env)).to be_nil
126
+ expect(env[:box_volumes]).to eq(
127
+ [
128
+ {
129
+ :path=>"/test/box.img",
130
+ :name=>"test_vagrant_box_image_1.1.1_box.img",
131
+ :virtual_size=>byte_number_20G,
132
+ :format=>"qcow2"
133
+ }
134
+ ]
135
+ )
136
+ end
137
+ end
138
+
139
+ context 'when disk image not in storage pool' do
140
+ before do
141
+ allow(File).to receive(:exist?).and_return(true)
142
+ allow(File).to receive(:size).and_return(5*1024*1024*1024)
143
+ allow(all).to receive(:first).and_return(nil)
144
+ allow(subject).to receive(:upload_image).and_return(true)
145
+ allow(volumes).to receive(:create).and_return(fog_volume)
146
+ end
147
+
148
+ it 'should upload disk' do
149
+ expect(ui).to receive(:info).with('Uploading base box image as volume into Libvirt storage...')
150
+ expect(logger).to receive(:info).with('Creating volume test_vagrant_box_image_1.1.1_box.img in storage pool default.')
151
+ expect(volumes).to receive(:create).with(
152
+ hash_including(
153
+ :name => "test_vagrant_box_image_1.1.1_box.img",
154
+ :allocation => "5120M",
155
+ :capacity => "5368709120B",
156
+ )
157
+ )
158
+ expect(subject).to receive(:upload_image)
159
+ expect(subject.call(env)).to be_nil
160
+ end
161
+ end
162
+
163
+ context 'when disk image already in storage pool' do
164
+ before do
165
+ allow(all).to receive(:first).and_return(box_volume)
166
+ allow(box_volume).to receive(:id).and_return(1)
167
+ end
168
+
169
+ it 'should skip disk upload' do
170
+ expect(volumes).not_to receive(:create)
171
+ expect(subject).not_to receive(:upload_image)
172
+ expect(subject.call(env)).to be_nil
173
+ end
174
+ end
175
+ end
176
+
177
+ context 'when three disks in metadata.json' do
178
+ let(:status) { double }
179
+
180
+ before do
181
+ allow(all).to receive(:first).and_return(box_volume)
182
+ allow(box_volume).to receive(:id).and_return(1)
183
+ allow(env[:machine]).to receive_message_chain("box.name") { 'test' }
184
+ allow(env[:machine]).to receive_message_chain("box.version") { '1.1.1' }
185
+ allow(env[:machine]).to receive_message_chain("box.metadata") { Hash[
186
+ 'disks' => [
187
+ {
188
+ 'path' => 'box.img',
189
+ 'name' => 'send_box_name',
190
+ },
191
+ {
192
+ 'path' => 'disk.qcow2',
193
+ },
194
+ {
195
+ 'path' => 'box_2.img',
196
+ },
197
+ ],
198
+ ]}
199
+ allow(env[:machine]).to receive_message_chain("box.directory.join") do |arg|
200
+ '/test/'.concat(arg.to_s)
201
+ end
202
+ allow(status).to receive(:success?).and_return(true)
203
+ allow(Open3).to receive(:capture3).with('qemu-img', 'info', '--output=json', '/test/box.img').and_return([
204
+ qemu_json_return_5G, "", status
205
+ ])
206
+ allow(Open3).to receive(:capture3).with('qemu-img', 'info', '--output=json', '/test/disk.qcow2').and_return([
207
+ qemu_json_return_10G, "", status
208
+ ])
209
+ allow(Open3).to receive(:capture3).with('qemu-img', 'info', '--output=json', '/test/box_2.img').and_return([
210
+ qemu_json_return_20G, "", status
211
+ ])
212
+ end
213
+
214
+ it 'should have three disks in machine env' do
215
+ expect(subject.call(env)).to be_nil
216
+ expect(env[:box_volume_number]).to eq(3)
217
+ expect(env[:box_volumes]).to eq(
218
+ [
219
+ {
220
+ :path=>"/test/box.img",
221
+ :name=>"test_vagrant_box_image_1.1.1_send_box_name.img",
222
+ :virtual_size=>byte_number_5G,
223
+ :format=>"qcow2"
224
+ },
225
+ {
226
+ :path=>"/test/disk.qcow2",
227
+ :name=>"test_vagrant_box_image_1.1.1_disk.img",
228
+ :virtual_size=>byte_number_10G,
229
+ :format=>"qcow2"
230
+ },
231
+ {
232
+ :path=>"/test/box_2.img",
233
+ :name=>"test_vagrant_box_image_1.1.1_box_2.img",
234
+ :virtual_size=>byte_number_20G,
235
+ :format=>"qcow2"
236
+ }
237
+ ]
238
+ )
239
+ end
240
+
241
+ context 'when none of the disks in storage pool' do
242
+ before do
243
+ allow(File).to receive(:exist?).and_return(true)
244
+ allow(File).to receive(:size).and_return(5*1024*1024*1024, 10*1024*1024*1024, 20*1024*1024*1024)
245
+ allow(all).to receive(:first).and_return(nil)
246
+ allow(subject).to receive(:upload_image).and_return(true)
247
+ allow(volumes).to receive(:create).and_return(fog_volume)
248
+ end
249
+
250
+ it 'should upload all 3 disks' do
251
+ expect(ui).to receive(:info).with('Uploading base box image as volume into Libvirt storage...')
252
+ expect(logger).to receive(:info).with('Creating volume test_vagrant_box_image_1.1.1_send_box_name.img in storage pool default.')
253
+ expect(volumes).to receive(:create).with(
254
+ hash_including(
255
+ :name => "test_vagrant_box_image_1.1.1_send_box_name.img",
256
+ :allocation => "5120M",
257
+ :capacity => "5368709120B",
258
+ )
259
+ )
260
+ expect(subject).to receive(:upload_image)
261
+ expect(ui).to receive(:info).with('Uploading base box image as volume into Libvirt storage...')
262
+ expect(logger).to receive(:info).with('Creating volume test_vagrant_box_image_1.1.1_disk.img in storage pool default.')
263
+ expect(volumes).to receive(:create).with(
264
+ hash_including(
265
+ :name => "test_vagrant_box_image_1.1.1_disk.img",
266
+ :allocation => "10240M",
267
+ :capacity => "10737423360B",
268
+ )
269
+ )
270
+ expect(subject).to receive(:upload_image)
271
+ expect(ui).to receive(:info).with('Uploading base box image as volume into Libvirt storage...')
272
+ expect(logger).to receive(:info).with('Creating volume test_vagrant_box_image_1.1.1_box_2.img in storage pool default.')
273
+ expect(volumes).to receive(:create).with(
274
+ hash_including(
275
+ :name => "test_vagrant_box_image_1.1.1_box_2.img",
276
+ :allocation => "20480M",
277
+ :capacity => "21474836480B",
278
+ )
279
+ )
280
+ expect(subject).to receive(:upload_image)
281
+
282
+ expect(subject.call(env)).to be_nil
283
+ end
284
+ end
285
+
286
+ context 'when only disk 0 in storage pool' do
287
+ before do
288
+ allow(File).to receive(:exist?).and_return(true)
289
+ allow(File).to receive(:size).and_return(10*1024*1024*1024, 20*1024*1024*1024)
290
+ allow(all).to receive(:first).and_return(box_volume, nil, nil)
291
+ allow(box_volume).to receive(:id).and_return(1)
292
+ allow(subject).to receive(:upload_image).and_return(true)
293
+ allow(volumes).to receive(:create).and_return(fog_volume)
294
+ end
295
+
296
+ it 'upload disks 1 and 2 only' do
297
+ expect(ui).to receive(:info).with('Uploading base box image as volume into Libvirt storage...')
298
+ expect(logger).to receive(:info).with('Creating volume test_vagrant_box_image_1.1.1_disk.img in storage pool default.')
299
+ expect(volumes).to receive(:create).with(hash_including(:name => "test_vagrant_box_image_1.1.1_disk.img"))
300
+ expect(subject).to receive(:upload_image)
301
+ expect(ui).to receive(:info).with('Uploading base box image as volume into Libvirt storage...')
302
+ expect(logger).to receive(:info).with('Creating volume test_vagrant_box_image_1.1.1_box_2.img in storage pool default.')
303
+ expect(volumes).to receive(:create).with(hash_including(:name => "test_vagrant_box_image_1.1.1_box_2.img"))
304
+ expect(subject).to receive(:upload_image)
305
+
306
+ expect(subject.call(env)).to be_nil
307
+ end
308
+ end
309
+
310
+ context 'when has all disks on storage pool' do
311
+ before do
312
+ allow(all).to receive(:first).and_return(box_volume)
313
+ allow(box_volume).to receive(:id).and_return(1)
314
+ end
315
+
316
+ it 'should skip disk upload' do
317
+ expect(ui).not_to receive(:info).with('Uploading base box image as volume into Libvirt storage...')
318
+ expect(volumes).not_to receive(:create)
319
+ expect(subject).not_to receive(:upload_image)
320
+ expect(subject.call(env)).to be_nil
321
+ end
322
+ end
323
+ end
324
+
325
+ context 'when wrong box format in metadata.json' do
326
+ before do
327
+ allow(all).to receive(:first).and_return(box_volume)
328
+ allow(box_volume).to receive(:id).and_return(1)
329
+ allow(env[:machine]).to receive_message_chain("box.name") { 'test' }
330
+ allow(env[:machine]).to receive_message_chain("box.version") { '1.1.1' }
331
+ allow(env[:machine]).to receive_message_chain("box.metadata") { Hash[
332
+ 'virtual_size'=> 5,
333
+ 'format' => 'wrongFormat'
334
+ ]
335
+ }
336
+ allow(env[:machine]).to receive_message_chain("box.directory.join") do |arg|
337
+ '/test/'.concat(arg.to_s)
338
+ end
339
+ end
340
+
341
+ it 'should raise WrongBoxFormatSet exception' do
342
+ expect{ subject.call(env) }.to raise_error(VagrantPlugins::ProviderLibvirt::Errors::WrongBoxFormatSet)
343
+ end
344
+
345
+ end
346
+
347
+ context 'when invalid format in metadata.json' do
348
+ let(:status) { double }
349
+
350
+ before do
351
+ allow(all).to receive(:first).and_return(box_volume)
352
+ allow(box_volume).to receive(:id).and_return(1)
353
+ allow(env[:machine]).to receive_message_chain("box.name") { 'test' }
354
+ allow(env[:machine]).to receive_message_chain("box.version") { '1.1.1' }
355
+ allow(env[:machine]).to receive_message_chain("box.metadata") { box_metadata }
356
+ allow(env[:machine]).to receive_message_chain("box.directory.join") do |arg|
357
+ '/test/'.concat(arg.to_s)
358
+ end
359
+ allow(status).to receive(:success?).and_return(true)
360
+ allow(Open3).to receive(:capture3).with('qemu-img', 'info', "--output=json", '/test/box.img').and_return([
361
+ qemu_json_return_5G, "", status
362
+ ])
363
+ allow(Open3).to receive(:capture3).with('qemu-img', 'info', "--output=json", '/test/disk.qcow2').and_return([
364
+ qemu_json_return_10G, "", status
365
+ ])
366
+ allow(Open3).to receive(:capture3).with('qemu-img', 'info', "--output=json", '/test/box_2.img').and_return([
367
+ qemu_json_return_20G, "", status
368
+ ])
369
+ end
370
+
371
+ context 'with one disk having wrong disk format' do
372
+ let(:box_metadata) {
373
+ Hash[
374
+ 'disks' => [
375
+ {
376
+ 'path' => 'box.img',
377
+ 'name' =>'send_box_name.img',
378
+ 'format' => 'wrongFormat'
379
+ },
380
+ {
381
+ 'path' => 'disk.qcow2',
382
+ },
383
+ {
384
+ 'path' => 'box_2.img',
385
+ },
386
+ ],
387
+ ]
388
+ }
389
+
390
+ it 'should be ignored' do
391
+ expect(subject.call(env)).to be_nil
392
+ end
393
+ end
394
+
395
+ context 'with one disk missing path' do
396
+ let(:box_metadata) {
397
+ Hash[
398
+ 'disks' => [
399
+ {
400
+ 'path' => 'box.img',
401
+ },
402
+ {
403
+ 'name' => 'send_box_name',
404
+ },
405
+ {
406
+ 'path' => 'box_2.img',
407
+ },
408
+ ],
409
+ ]
410
+ }
411
+
412
+ it 'should raise an exception' do
413
+ expect{ subject.call(env) }.to raise_error(VagrantPlugins::ProviderLibvirt::Errors::BoxFormatMissingAttribute, /: 'disks\[1\]\['path'\]'/)
414
+ end
415
+ end
416
+
417
+ context 'with one disk name duplicating a path of another' do
418
+ let(:box_metadata) {
419
+ Hash[
420
+ 'disks' => [
421
+ {
422
+ 'path' => 'box.img',
423
+ 'name' => 'box_2',
424
+ },
425
+ {
426
+ 'path' => 'disk.qcow2',
427
+ },
428
+ {
429
+ 'path' => 'box_2.img',
430
+ },
431
+ ],
432
+ ]
433
+ }
434
+
435
+ it 'should raise an exception' do
436
+ expect{ subject.call(env) }.to raise_error(VagrantPlugins::ProviderLibvirt::Errors::BoxFormatDuplicateVolume, /test_vagrant_box_image_1.1.1_box_2.img.*'disks\[2\]'.*'disks\[0\]'/)
437
+ end
438
+ end
439
+ end
440
+ end
441
+ end