vagrant-libvirt 0.5.0 → 0.6.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.
- checksums.yaml +4 -4
- data/README.md +134 -23
- data/lib/vagrant-libvirt/action/clean_machine_folder.rb +4 -0
- data/lib/vagrant-libvirt/action/create_domain.rb +11 -3
- data/lib/vagrant-libvirt/action/create_domain_volume.rb +7 -2
- data/lib/vagrant-libvirt/action/create_network_interfaces.rb +8 -2
- data/lib/vagrant-libvirt/action/create_networks.rb +12 -8
- data/lib/vagrant-libvirt/action/destroy_domain.rb +2 -0
- data/lib/vagrant-libvirt/action/destroy_networks.rb +2 -0
- data/lib/vagrant-libvirt/action/forward_ports.rb +7 -5
- data/lib/vagrant-libvirt/action/halt_domain.rb +4 -34
- data/lib/vagrant-libvirt/action/handle_box_image.rb +18 -13
- data/lib/vagrant-libvirt/action/handle_storage_pool.rb +7 -1
- data/lib/vagrant-libvirt/action/is_created.rb +2 -0
- data/lib/vagrant-libvirt/action/is_running.rb +2 -0
- data/lib/vagrant-libvirt/action/is_suspended.rb +2 -0
- data/lib/vagrant-libvirt/action/message_already_created.rb +2 -0
- data/lib/vagrant-libvirt/action/message_not_created.rb +2 -0
- data/lib/vagrant-libvirt/action/message_not_running.rb +2 -0
- data/lib/vagrant-libvirt/action/message_not_suspended.rb +2 -0
- data/lib/vagrant-libvirt/action/message_will_not_destroy.rb +2 -0
- data/lib/vagrant-libvirt/action/package_domain.rb +133 -68
- data/lib/vagrant-libvirt/action/prepare_nfs_settings.rb +2 -0
- data/lib/vagrant-libvirt/action/prepare_nfs_valid_ids.rb +2 -0
- data/lib/vagrant-libvirt/action/prune_nfs_exports.rb +2 -0
- data/lib/vagrant-libvirt/action/read_mac_addresses.rb +2 -0
- data/lib/vagrant-libvirt/action/remove_libvirt_image.rb +2 -0
- data/lib/vagrant-libvirt/action/remove_stale_volume.rb +2 -0
- data/lib/vagrant-libvirt/action/resume_domain.rb +2 -0
- data/lib/vagrant-libvirt/action/set_boot_order.rb +8 -2
- data/lib/vagrant-libvirt/action/set_name_of_domain.rb +3 -1
- data/lib/vagrant-libvirt/action/share_folders.rb +2 -0
- data/lib/vagrant-libvirt/action/shutdown_domain.rb +49 -0
- data/lib/vagrant-libvirt/action/start_domain.rb +26 -17
- data/lib/vagrant-libvirt/action/suspend_domain.rb +2 -0
- data/lib/vagrant-libvirt/action/wait_till_up.rb +2 -0
- data/lib/vagrant-libvirt/action.rb +34 -4
- data/lib/vagrant-libvirt/cap/mount_9p.rb +2 -0
- data/lib/vagrant-libvirt/cap/mount_virtiofs.rb +2 -0
- data/lib/vagrant-libvirt/cap/nic_mac_addresses.rb +2 -0
- data/lib/vagrant-libvirt/cap/public_address.rb +2 -0
- data/lib/vagrant-libvirt/cap/synced_folder_9p.rb +5 -2
- data/lib/vagrant-libvirt/cap/synced_folder_virtiofs.rb +5 -2
- data/lib/vagrant-libvirt/config.rb +58 -24
- data/lib/vagrant-libvirt/driver.rb +67 -12
- data/lib/vagrant-libvirt/errors.rb +2 -0
- data/lib/vagrant-libvirt/plugin.rb +2 -0
- data/lib/vagrant-libvirt/provider.rb +2 -0
- data/lib/vagrant-libvirt/templates/domain.xml.erb +4 -2
- data/lib/vagrant-libvirt/templates/public_interface.xml.erb +1 -0
- data/lib/vagrant-libvirt/util/byte_number.rb +71 -0
- data/lib/vagrant-libvirt/util/collection.rb +2 -0
- data/lib/vagrant-libvirt/util/erb_template.rb +2 -0
- data/lib/vagrant-libvirt/util/error_codes.rb +2 -0
- data/lib/vagrant-libvirt/util/network_util.rb +3 -0
- data/lib/vagrant-libvirt/util/nfs.rb +2 -0
- data/lib/vagrant-libvirt/util/storage_util.rb +1 -0
- data/lib/vagrant-libvirt/util/timer.rb +2 -0
- data/lib/vagrant-libvirt/util/ui.rb +1 -0
- data/lib/vagrant-libvirt/util.rb +2 -0
- data/lib/vagrant-libvirt/version +1 -1
- data/lib/vagrant-libvirt/version.rb +2 -0
- data/lib/vagrant-libvirt.rb +2 -0
- data/locales/en.yml +2 -0
- data/spec/spec_helper.rb +2 -0
- data/spec/support/binding_proc.rb +2 -0
- data/spec/support/environment_helper.rb +2 -0
- data/spec/support/libvirt_context.rb +2 -0
- data/spec/support/matchers/have_file_content.rb +2 -0
- data/spec/support/sharedcontext.rb +3 -0
- data/spec/support/temporary_dir.rb +12 -0
- data/spec/unit/action/clean_machine_folder_spec.rb +16 -4
- data/spec/unit/action/create_domain_spec/additional_disks_domain.xml +61 -0
- data/spec/unit/action/create_domain_spec/default_domain.xml +55 -0
- data/spec/unit/action/create_domain_spec.rb +68 -32
- data/spec/unit/action/create_domain_volume_spec/one_disk_in_storage.xml +1 -1
- data/spec/unit/action/create_domain_volume_spec/three_disks_in_storage_disk_0.xml +1 -1
- data/spec/unit/action/create_domain_volume_spec/three_disks_in_storage_disk_1.xml +1 -1
- data/spec/unit/action/create_domain_volume_spec/three_disks_in_storage_disk_2.xml +1 -1
- data/spec/unit/action/create_domain_volume_spec.rb +10 -4
- data/spec/unit/action/destroy_domain_spec.rb +8 -2
- data/spec/unit/action/forward_ports_spec.rb +2 -0
- data/spec/unit/action/halt_domain_spec.rb +30 -57
- data/spec/unit/action/handle_box_image_spec.rb +104 -24
- data/spec/unit/action/package_domain_spec.rb +304 -0
- data/spec/unit/action/set_name_of_domain_spec.rb +2 -0
- data/spec/unit/action/shutdown_domain_spec.rb +131 -0
- data/spec/unit/action/start_domain_spec/existing.xml +62 -0
- data/spec/unit/action/start_domain_spec.rb +18 -28
- data/spec/unit/action/wait_till_up_spec.rb +2 -0
- data/spec/unit/action_spec.rb +96 -0
- data/spec/unit/config_spec.rb +56 -3
- data/spec/unit/driver_spec.rb +155 -0
- data/spec/unit/templates/domain_all_settings.xml +4 -0
- data/spec/unit/templates/domain_spec.rb +2 -0
- data/spec/unit/util/byte_number_spec.rb +28 -0
- metadata +59 -38
@@ -1,8 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'spec_helper'
|
4
|
+
require 'json'
|
2
5
|
require 'support/sharedcontext'
|
3
6
|
require 'support/libvirt_context'
|
4
7
|
|
5
8
|
require 'vagrant-libvirt/action/destroy_domain'
|
9
|
+
require 'vagrant-libvirt/util/byte_number'
|
10
|
+
|
6
11
|
|
7
12
|
describe VagrantPlugins::ProviderLibvirt::Action::HandleBoxImage do
|
8
13
|
subject { described_class.new(app, env) }
|
@@ -15,6 +20,41 @@ describe VagrantPlugins::ProviderLibvirt::Action::HandleBoxImage do
|
|
15
20
|
let(:all) { double('all') }
|
16
21
|
let(:box_volume) { double('box_volume') }
|
17
22
|
let(:fog_volume) { double('fog_volume') }
|
23
|
+
let(:config) { double('config') }
|
24
|
+
|
25
|
+
qemu_json_return_5G = JSON.dump({
|
26
|
+
"virtual-size": 5368709120,
|
27
|
+
"filename": "/test/box.img",
|
28
|
+
"cluster-size": 65536,
|
29
|
+
"format": "qcow2",
|
30
|
+
"actual-size": 655360,
|
31
|
+
"dirty-flag": false
|
32
|
+
})
|
33
|
+
byte_number_5G = ByteNumber.new(5368709120)
|
34
|
+
|
35
|
+
|
36
|
+
qemu_json_return_10G = JSON.dump({
|
37
|
+
"virtual-size": 10737423360,
|
38
|
+
"filename": "/test/disk.qcow2",
|
39
|
+
"cluster-size": 65536,
|
40
|
+
"format": "qcow2",
|
41
|
+
"actual-size": 655360,
|
42
|
+
"dirty-flag": false
|
43
|
+
})
|
44
|
+
byte_number_10G = ByteNumber.new(10737423360)
|
45
|
+
|
46
|
+
qemu_json_return_20G = JSON.dump({
|
47
|
+
"virtual-size": 21474836480,
|
48
|
+
"filename": "/test/box_2.img",
|
49
|
+
"cluster-size": 65536,
|
50
|
+
"format": "qcow2",
|
51
|
+
"actual-size": 1508708352,
|
52
|
+
"dirty-flag": false
|
53
|
+
})
|
54
|
+
byte_number_20G = ByteNumber.new(21474836480)
|
55
|
+
|
56
|
+
|
57
|
+
|
18
58
|
|
19
59
|
describe '#call' do
|
20
60
|
before do
|
@@ -39,7 +79,7 @@ describe VagrantPlugins::ProviderLibvirt::Action::HandleBoxImage do
|
|
39
79
|
]
|
40
80
|
}
|
41
81
|
allow(env[:machine]).to receive_message_chain("box.directory.join") do |arg|
|
42
|
-
'/test/'
|
82
|
+
'/test/' + arg.to_s
|
43
83
|
end
|
44
84
|
end
|
45
85
|
|
@@ -51,13 +91,53 @@ describe VagrantPlugins::ProviderLibvirt::Action::HandleBoxImage do
|
|
51
91
|
{
|
52
92
|
:path=>"/test/box.img",
|
53
93
|
:name=>"test_vagrant_box_image_1.1.1_box.img",
|
54
|
-
:virtual_size=>
|
94
|
+
:virtual_size=>byte_number_5G,
|
55
95
|
:format=>"qcow2"
|
56
96
|
}
|
57
97
|
]
|
58
98
|
)
|
59
99
|
end
|
60
100
|
|
101
|
+
context 'When config.machine_virtual_size is set and smaller than box_virtual_size' do
|
102
|
+
before do
|
103
|
+
allow(env[:machine]).to receive_message_chain("provider_config.machine_virtual_size").and_return(1)
|
104
|
+
end
|
105
|
+
it 'should warning must be raise' do
|
106
|
+
expect(ui).to receive(:warn).with("Ignoring requested virtual disk size of '1' as it is below\nthe minimum box image size of '5'.")
|
107
|
+
expect(subject.call(env)).to be_nil
|
108
|
+
expect(env[:box_volumes]).to eq(
|
109
|
+
[
|
110
|
+
{
|
111
|
+
:path=>"/test/box.img",
|
112
|
+
:name=>"test_vagrant_box_image_1.1.1_box.img",
|
113
|
+
:virtual_size=>byte_number_5G,
|
114
|
+
:format=>"qcow2"
|
115
|
+
}
|
116
|
+
]
|
117
|
+
)
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
context 'When config.machine_virtual_size is set and higher than box_virtual_size' do
|
122
|
+
before do
|
123
|
+
allow(env[:machine]).to receive_message_chain("provider_config.machine_virtual_size").and_return(20)
|
124
|
+
end
|
125
|
+
it 'should be use' do
|
126
|
+
expect(ui).to receive(:info).with("Created volume larger than box defaults, will require manual resizing of\nfilesystems to utilize.")
|
127
|
+
expect(subject.call(env)).to be_nil
|
128
|
+
expect(env[:box_volumes]).to eq(
|
129
|
+
[
|
130
|
+
{
|
131
|
+
:path=>"/test/box.img",
|
132
|
+
:name=>"test_vagrant_box_image_1.1.1_box.img",
|
133
|
+
:virtual_size=>byte_number_20G,
|
134
|
+
:format=>"qcow2"
|
135
|
+
}
|
136
|
+
]
|
137
|
+
)
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
61
141
|
context 'when disk image not in storage pool' do
|
62
142
|
before do
|
63
143
|
allow(File).to receive(:exist?).and_return(true)
|
@@ -74,7 +154,7 @@ describe VagrantPlugins::ProviderLibvirt::Action::HandleBoxImage do
|
|
74
154
|
hash_including(
|
75
155
|
:name => "test_vagrant_box_image_1.1.1_box.img",
|
76
156
|
:allocation => "5120M",
|
77
|
-
:capacity => "
|
157
|
+
:capacity => "5368709120B",
|
78
158
|
)
|
79
159
|
)
|
80
160
|
expect(subject).to receive(:upload_image)
|
@@ -119,17 +199,17 @@ describe VagrantPlugins::ProviderLibvirt::Action::HandleBoxImage do
|
|
119
199
|
],
|
120
200
|
]}
|
121
201
|
allow(env[:machine]).to receive_message_chain("box.directory.join") do |arg|
|
122
|
-
'/test/'
|
202
|
+
'/test/' + arg.to_s
|
123
203
|
end
|
124
204
|
allow(status).to receive(:success?).and_return(true)
|
125
|
-
allow(Open3).to receive(:capture3).with('qemu-img', 'info', '/test/box.img').and_return([
|
126
|
-
|
205
|
+
allow(Open3).to receive(:capture3).with('qemu-img', 'info', '--output=json', '/test/box.img').and_return([
|
206
|
+
qemu_json_return_5G, "", status
|
127
207
|
])
|
128
|
-
allow(Open3).to receive(:capture3).with('qemu-img', 'info', '/test/disk.qcow2').and_return([
|
129
|
-
|
208
|
+
allow(Open3).to receive(:capture3).with('qemu-img', 'info', '--output=json', '/test/disk.qcow2').and_return([
|
209
|
+
qemu_json_return_10G, "", status
|
130
210
|
])
|
131
|
-
allow(Open3).to receive(:capture3).with('qemu-img', 'info', '/test/box_2.img').and_return([
|
132
|
-
|
211
|
+
allow(Open3).to receive(:capture3).with('qemu-img', 'info', '--output=json', '/test/box_2.img').and_return([
|
212
|
+
qemu_json_return_20G, "", status
|
133
213
|
])
|
134
214
|
end
|
135
215
|
|
@@ -141,19 +221,19 @@ describe VagrantPlugins::ProviderLibvirt::Action::HandleBoxImage do
|
|
141
221
|
{
|
142
222
|
:path=>"/test/box.img",
|
143
223
|
:name=>"test_vagrant_box_image_1.1.1_send_box_name.img",
|
144
|
-
:virtual_size=>
|
224
|
+
:virtual_size=>byte_number_5G,
|
145
225
|
:format=>"qcow2"
|
146
226
|
},
|
147
227
|
{
|
148
228
|
:path=>"/test/disk.qcow2",
|
149
229
|
:name=>"test_vagrant_box_image_1.1.1_disk.img",
|
150
|
-
:virtual_size=>
|
230
|
+
:virtual_size=>byte_number_10G,
|
151
231
|
:format=>"qcow2"
|
152
232
|
},
|
153
233
|
{
|
154
234
|
:path=>"/test/box_2.img",
|
155
235
|
:name=>"test_vagrant_box_image_1.1.1_box_2.img",
|
156
|
-
:virtual_size=>
|
236
|
+
:virtual_size=>byte_number_20G,
|
157
237
|
:format=>"qcow2"
|
158
238
|
}
|
159
239
|
]
|
@@ -176,7 +256,7 @@ describe VagrantPlugins::ProviderLibvirt::Action::HandleBoxImage do
|
|
176
256
|
hash_including(
|
177
257
|
:name => "test_vagrant_box_image_1.1.1_send_box_name.img",
|
178
258
|
:allocation => "5120M",
|
179
|
-
:capacity => "
|
259
|
+
:capacity => "5368709120B",
|
180
260
|
)
|
181
261
|
)
|
182
262
|
expect(subject).to receive(:upload_image)
|
@@ -186,7 +266,7 @@ describe VagrantPlugins::ProviderLibvirt::Action::HandleBoxImage do
|
|
186
266
|
hash_including(
|
187
267
|
:name => "test_vagrant_box_image_1.1.1_disk.img",
|
188
268
|
:allocation => "10240M",
|
189
|
-
:capacity => "
|
269
|
+
:capacity => "10737423360B",
|
190
270
|
)
|
191
271
|
)
|
192
272
|
expect(subject).to receive(:upload_image)
|
@@ -196,7 +276,7 @@ describe VagrantPlugins::ProviderLibvirt::Action::HandleBoxImage do
|
|
196
276
|
hash_including(
|
197
277
|
:name => "test_vagrant_box_image_1.1.1_box_2.img",
|
198
278
|
:allocation => "20480M",
|
199
|
-
:capacity => "
|
279
|
+
:capacity => "21474836480B",
|
200
280
|
)
|
201
281
|
)
|
202
282
|
expect(subject).to receive(:upload_image)
|
@@ -256,7 +336,7 @@ describe VagrantPlugins::ProviderLibvirt::Action::HandleBoxImage do
|
|
256
336
|
]
|
257
337
|
}
|
258
338
|
allow(env[:machine]).to receive_message_chain("box.directory.join") do |arg|
|
259
|
-
'/test/'
|
339
|
+
'/test/' + arg.to_s
|
260
340
|
end
|
261
341
|
end
|
262
342
|
|
@@ -276,17 +356,17 @@ describe VagrantPlugins::ProviderLibvirt::Action::HandleBoxImage do
|
|
276
356
|
allow(env[:machine]).to receive_message_chain("box.version") { '1.1.1' }
|
277
357
|
allow(env[:machine]).to receive_message_chain("box.metadata") { box_metadata }
|
278
358
|
allow(env[:machine]).to receive_message_chain("box.directory.join") do |arg|
|
279
|
-
'/test/'
|
359
|
+
'/test/' + arg.to_s
|
280
360
|
end
|
281
361
|
allow(status).to receive(:success?).and_return(true)
|
282
|
-
allow(Open3).to receive(:capture3).with('qemu-img', 'info', '/test/box.img').and_return([
|
283
|
-
|
362
|
+
allow(Open3).to receive(:capture3).with('qemu-img', 'info', "--output=json", '/test/box.img').and_return([
|
363
|
+
qemu_json_return_5G, "", status
|
284
364
|
])
|
285
|
-
allow(Open3).to receive(:capture3).with('qemu-img', 'info', '/test/disk.qcow2').and_return([
|
286
|
-
|
365
|
+
allow(Open3).to receive(:capture3).with('qemu-img', 'info', "--output=json", '/test/disk.qcow2').and_return([
|
366
|
+
qemu_json_return_10G, "", status
|
287
367
|
])
|
288
|
-
allow(Open3).to receive(:capture3).with('qemu-img', 'info', '/test/box_2.img').and_return([
|
289
|
-
|
368
|
+
allow(Open3).to receive(:capture3).with('qemu-img', 'info', "--output=json", '/test/box_2.img').and_return([
|
369
|
+
qemu_json_return_20G, "", status
|
290
370
|
])
|
291
371
|
end
|
292
372
|
|
@@ -0,0 +1,304 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
require 'support/sharedcontext'
|
5
|
+
|
6
|
+
require 'vagrant-libvirt/action/clean_machine_folder'
|
7
|
+
|
8
|
+
describe VagrantPlugins::ProviderLibvirt::Action::PackageDomain do
|
9
|
+
subject { described_class.new(app, env) }
|
10
|
+
|
11
|
+
include_context 'unit'
|
12
|
+
include_context 'libvirt'
|
13
|
+
include_context 'temporary_dir'
|
14
|
+
|
15
|
+
let(:libvirt_client) { double('libvirt_client') }
|
16
|
+
let(:libvirt_domain) { double('libvirt_domain') }
|
17
|
+
let(:servers) { double('servers') }
|
18
|
+
let(:volumes) { double('volumes') }
|
19
|
+
let(:metadata_file) { double('file') }
|
20
|
+
let(:vagrantfile_file) { double('file') }
|
21
|
+
|
22
|
+
describe '#call' do
|
23
|
+
before do
|
24
|
+
allow_any_instance_of(VagrantPlugins::ProviderLibvirt::Driver)
|
25
|
+
.to receive(:connection).and_return(connection)
|
26
|
+
allow(connection).to receive(:client).and_return(libvirt_client)
|
27
|
+
allow(libvirt_client).to receive(:lookup_domain_by_uuid).and_return(libvirt_domain)
|
28
|
+
|
29
|
+
allow(connection).to receive(:servers).and_return(servers)
|
30
|
+
allow(servers).to receive(:get).and_return(domain)
|
31
|
+
|
32
|
+
allow(connection).to receive(:volumes).and_return(volumes)
|
33
|
+
|
34
|
+
allow(logger).to receive(:info)
|
35
|
+
|
36
|
+
env["package.directory"] = temp_dir
|
37
|
+
end
|
38
|
+
|
39
|
+
context 'with defaults' do
|
40
|
+
let(:root_disk) { double('libvirt_domain_disk') }
|
41
|
+
before do
|
42
|
+
allow(root_disk).to receive(:name).and_return('default_domain.img')
|
43
|
+
allow(domain).to receive(:volumes).and_return([root_disk])
|
44
|
+
allow(libvirt_domain).to receive(:name).and_return('default_domain')
|
45
|
+
allow(subject).to receive(:download_image).and_return(true)
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'should succeed' do
|
49
|
+
expect(ui).to receive(:info).with('Packaging domain...')
|
50
|
+
expect(ui).to receive(:info).with(/Downloading default_domain.img to .*\/box.img/)
|
51
|
+
expect(ui).to receive(:info).with('Image has backing image, copying image and rebasing ...')
|
52
|
+
expect(subject).to receive(:`).with(/qemu-img info .*\/box.img | grep 'backing file:' | cut -d ':' -f2/).and_return("some image")
|
53
|
+
expect(subject).to receive(:`).with(/qemu-img rebase -p -b "" .*\/box.img/)
|
54
|
+
expect(subject).to receive(:`).with(/virt-sysprep --no-logfile --operations .* -a .*\/box.img .*/)
|
55
|
+
expect(subject).to receive(:`).with(/virt-sparsify --in-place .*\/box.img/)
|
56
|
+
expect(subject).to receive(:`).with(/qemu-img info --output=json .*\/box.img/).and_return(
|
57
|
+
{ 'virtual-size': 5*1024*1024*1024 }.to_json
|
58
|
+
)
|
59
|
+
expect(File).to receive(:write).with(
|
60
|
+
/.*\/metadata.json/,
|
61
|
+
<<-EOF.unindent
|
62
|
+
{
|
63
|
+
"provider": "libvirt",
|
64
|
+
"format": "qcow2",
|
65
|
+
"virtual_size": 5
|
66
|
+
}
|
67
|
+
EOF
|
68
|
+
)
|
69
|
+
expect(File).to receive(:write).with(/.*\/Vagrantfile/, /.*/)
|
70
|
+
|
71
|
+
expect(subject.call(env)).to be_nil
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
context 'with nil volume' do
|
76
|
+
let(:root_disk) { double('libvirt_domain_disk') }
|
77
|
+
before do
|
78
|
+
allow(root_disk).to receive(:name).and_return('default_domain.img')
|
79
|
+
allow(domain).to receive(:volumes).and_return([nil, root_disk])
|
80
|
+
allow(libvirt_domain).to receive(:name).and_return('default_domain')
|
81
|
+
allow(subject).to receive(:download_image).and_return(true)
|
82
|
+
end
|
83
|
+
|
84
|
+
it 'should succeed' do
|
85
|
+
expect(ui).to receive(:info).with('Packaging domain...')
|
86
|
+
expect(ui).to receive(:info).with(/Downloading default_domain.img to .*\/box.img/)
|
87
|
+
expect(ui).to receive(:info).with('Image has backing image, copying image and rebasing ...')
|
88
|
+
expect(subject).to receive(:`).with(/qemu-img info .*\/box.img | grep 'backing file:' | cut -d ':' -f2/).and_return("some image")
|
89
|
+
expect(subject).to receive(:`).with(/qemu-img rebase -p -b "" .*\/box.img/)
|
90
|
+
expect(subject).to receive(:`).with(/virt-sysprep --no-logfile --operations .* -a .*\/box.img .*/)
|
91
|
+
expect(subject).to receive(:`).with(/virt-sparsify --in-place .*\/box.img/)
|
92
|
+
expect(subject).to receive(:`).with(/qemu-img info --output=json .*\/box.img/).and_return(
|
93
|
+
{ 'virtual-size': 5*1024*1024*1024 }.to_json
|
94
|
+
)
|
95
|
+
|
96
|
+
expect(subject.call(env)).to be_nil
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
context 'when detecting the format' do
|
101
|
+
let(:root_disk) { double('libvirt_domain_disk') }
|
102
|
+
let(:disk2) { double('libvirt_additional_disk') }
|
103
|
+
let(:fake_env) { Hash.new }
|
104
|
+
|
105
|
+
before do
|
106
|
+
allow(root_disk).to receive(:name).and_return('default_domain.img')
|
107
|
+
allow(disk2).to receive(:name).and_return('disk2.img')
|
108
|
+
allow(libvirt_domain).to receive(:name).and_return('default_domain')
|
109
|
+
end
|
110
|
+
|
111
|
+
context 'with two disks' do
|
112
|
+
before do
|
113
|
+
allow(domain).to receive(:volumes).and_return([root_disk, disk2])
|
114
|
+
end
|
115
|
+
|
116
|
+
it 'should emit a warning' do
|
117
|
+
expect(ui).to receive(:info).with('Packaging domain...')
|
118
|
+
expect(ui).to receive(:warn).with(/Detected more than one volume for machine.*\n.*/)
|
119
|
+
expect(subject).to receive(:package_v1)
|
120
|
+
|
121
|
+
expect(subject.call(env)).to be_nil
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
context 'with format set to v1' do
|
126
|
+
before do
|
127
|
+
allow(domain).to receive(:volumes).and_return([root_disk])
|
128
|
+
stub_const("ENV", fake_env)
|
129
|
+
fake_env['VAGRANT_LIBVIRT_BOX_FORMAT_VERSION'] = "v1"
|
130
|
+
end
|
131
|
+
|
132
|
+
it 'should call v1 packaging' do
|
133
|
+
expect(ui).to receive(:info).with('Packaging domain...')
|
134
|
+
expect(subject).to receive(:package_v1)
|
135
|
+
|
136
|
+
expect(subject.call(env)).to be_nil
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
context 'with format set to v2' do
|
141
|
+
before do
|
142
|
+
allow(domain).to receive(:volumes).and_return([root_disk])
|
143
|
+
stub_const("ENV", fake_env)
|
144
|
+
fake_env['VAGRANT_LIBVIRT_BOX_FORMAT_VERSION'] = "v2"
|
145
|
+
end
|
146
|
+
|
147
|
+
it 'should call v1 packaging' do
|
148
|
+
expect(ui).to receive(:info).with('Packaging domain...')
|
149
|
+
expect(subject).to receive(:package_v2)
|
150
|
+
|
151
|
+
expect(subject.call(env)).to be_nil
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
context 'with invalid format' do
|
156
|
+
before do
|
157
|
+
allow(domain).to receive(:volumes).and_return([root_disk])
|
158
|
+
stub_const("ENV", fake_env)
|
159
|
+
fake_env['VAGRANT_LIBVIRT_BOX_FORMAT_VERSION'] = "bad format"
|
160
|
+
end
|
161
|
+
|
162
|
+
it 'should emit a warning and default to v1' do
|
163
|
+
expect(ui).to receive(:info).with('Packaging domain...')
|
164
|
+
expect(ui).to receive(:warn).with(/Unrecognized value for.*defaulting to v1/)
|
165
|
+
expect(subject).to receive(:package_v1)
|
166
|
+
|
167
|
+
expect(subject.call(env)).to be_nil
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
context 'with v2 format' do
|
173
|
+
let(:disk1) { double('libvirt_domain_disk') }
|
174
|
+
let(:disk2) { double('libvirt_additional_disk') }
|
175
|
+
let(:fake_env) { Hash.new }
|
176
|
+
|
177
|
+
before do
|
178
|
+
allow(disk1).to receive(:name).and_return('default_domain.img')
|
179
|
+
allow(disk2).to receive(:name).and_return('disk2.img')
|
180
|
+
allow(libvirt_domain).to receive(:name).and_return('default_domain')
|
181
|
+
allow(subject).to receive(:download_image).and_return(true).twice()
|
182
|
+
|
183
|
+
stub_const("ENV", fake_env)
|
184
|
+
fake_env['VAGRANT_LIBVIRT_BOX_FORMAT_VERSION'] = "v2"
|
185
|
+
end
|
186
|
+
|
187
|
+
context 'with 2 disks' do
|
188
|
+
before do
|
189
|
+
allow(domain).to receive(:volumes).and_return([disk1, disk2])
|
190
|
+
end
|
191
|
+
|
192
|
+
it 'should succeed' do
|
193
|
+
expect(ui).to receive(:info).with('Packaging domain...')
|
194
|
+
expect(ui).to receive(:info).with(/Downloading default_domain.img to .*\/box_1.img/)
|
195
|
+
expect(ui).to receive(:info).with('Image has backing image, copying image and rebasing ...')
|
196
|
+
expect(subject).to receive(:`).with(/qemu-img info .*\/box_1.img | grep 'backing file:' | cut -d ':' -f2/).and_return("some image")
|
197
|
+
expect(subject).to receive(:`).with(/qemu-img rebase -p -b "" .*\/box_1.img/)
|
198
|
+
expect(subject).to receive(:`).with(/virt-sysprep --no-logfile --operations .* -a .*\/box_1.img .*/)
|
199
|
+
expect(subject).to receive(:`).with(/virt-sparsify --in-place .*\/box_1.img/)
|
200
|
+
expect(ui).to receive(:info).with(/Downloading disk2.img to .*\/box_2.img/)
|
201
|
+
expect(ui).to receive(:info).with('Image has backing image, copying image and rebasing ...')
|
202
|
+
expect(subject).to receive(:`).with(/qemu-img info .*\/box_2.img | grep 'backing file:' | cut -d ':' -f2/).and_return("some image")
|
203
|
+
expect(subject).to receive(:`).with(/qemu-img rebase -p -b "" .*\/box_2.img/)
|
204
|
+
expect(subject).to receive(:`).with(/virt-sparsify --in-place .*\/box_2.img/)
|
205
|
+
|
206
|
+
expect(File).to receive(:write).with(
|
207
|
+
/.*\/metadata.json/,
|
208
|
+
<<-EOF.unindent.rstrip()
|
209
|
+
{
|
210
|
+
"provider": "libvirt",
|
211
|
+
"format": "qcow2",
|
212
|
+
"disks": [
|
213
|
+
{
|
214
|
+
"path": "box_1.img"
|
215
|
+
},
|
216
|
+
{
|
217
|
+
"path": "box_2.img"
|
218
|
+
}
|
219
|
+
]
|
220
|
+
}
|
221
|
+
EOF
|
222
|
+
)
|
223
|
+
expect(File).to receive(:write).with(/.*\/Vagrantfile/, /.*/)
|
224
|
+
|
225
|
+
expect(subject.call(env)).to be_nil
|
226
|
+
end
|
227
|
+
end
|
228
|
+
|
229
|
+
context 'with 1 disk' do
|
230
|
+
before do
|
231
|
+
allow(domain).to receive(:volumes).and_return([disk1])
|
232
|
+
end
|
233
|
+
|
234
|
+
it 'should succeed' do
|
235
|
+
expect(ui).to receive(:info).with('Packaging domain...')
|
236
|
+
expect(ui).to receive(:info).with(/Downloading default_domain.img to .*\/box_1.img/)
|
237
|
+
expect(ui).to receive(:info).with('Image has backing image, copying image and rebasing ...')
|
238
|
+
expect(subject).to receive(:`).with(/qemu-img info .*\/box_1.img | grep 'backing file:' | cut -d ':' -f2/).and_return("some image")
|
239
|
+
expect(subject).to receive(:`).with(/qemu-img rebase -p -b "" .*\/box_1.img/)
|
240
|
+
expect(subject).to receive(:`).with(/virt-sysprep --no-logfile --operations .* -a .*\/box_1.img .*/)
|
241
|
+
expect(subject).to receive(:`).with(/virt-sparsify --in-place .*\/box_1.img/)
|
242
|
+
|
243
|
+
expect(File).to receive(:write).with(
|
244
|
+
/.*\/metadata.json/,
|
245
|
+
<<-EOF.unindent.rstrip()
|
246
|
+
{
|
247
|
+
"provider": "libvirt",
|
248
|
+
"format": "qcow2",
|
249
|
+
"disks": [
|
250
|
+
{
|
251
|
+
"path": "box_1.img"
|
252
|
+
}
|
253
|
+
]
|
254
|
+
}
|
255
|
+
EOF
|
256
|
+
)
|
257
|
+
expect(File).to receive(:write).with(/.*\/Vagrantfile/, /.*/)
|
258
|
+
|
259
|
+
expect(subject.call(env)).to be_nil
|
260
|
+
end
|
261
|
+
end
|
262
|
+
end
|
263
|
+
end
|
264
|
+
|
265
|
+
describe '#vagrantfile_content' do
|
266
|
+
context 'with defaults' do
|
267
|
+
it 'should output expected content' do
|
268
|
+
expect(subject.vagrantfile_content(env)).to eq(
|
269
|
+
<<-EOF.unindent
|
270
|
+
Vagrant.configure("2") do |config|
|
271
|
+
config.vm.provider :libvirt do |libvirt|
|
272
|
+
libvirt.driver = "kvm"
|
273
|
+
end
|
274
|
+
|
275
|
+
end
|
276
|
+
EOF
|
277
|
+
)
|
278
|
+
end
|
279
|
+
end
|
280
|
+
|
281
|
+
context 'with custom user vagrantfile' do
|
282
|
+
before do
|
283
|
+
env["package.vagrantfile"] = "_Vagrantfile"
|
284
|
+
end
|
285
|
+
it 'should output Vagrantfile containing reference' do
|
286
|
+
expect(subject.vagrantfile_content(env)).to eq(
|
287
|
+
<<-EOF.unindent
|
288
|
+
Vagrant.configure("2") do |config|
|
289
|
+
config.vm.provider :libvirt do |libvirt|
|
290
|
+
libvirt.driver = "kvm"
|
291
|
+
end
|
292
|
+
|
293
|
+
# Load include vagrant file if it exists after the auto-generated
|
294
|
+
# so it can override any of the settings
|
295
|
+
include_vagrantfile = File.expand_path("../include/_Vagrantfile", __FILE__)
|
296
|
+
load include_vagrantfile if File.exist?(include_vagrantfile)
|
297
|
+
|
298
|
+
end
|
299
|
+
EOF
|
300
|
+
)
|
301
|
+
end
|
302
|
+
end
|
303
|
+
end
|
304
|
+
end
|
@@ -0,0 +1,131 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'support/sharedcontext'
|
3
|
+
require 'support/libvirt_context'
|
4
|
+
require 'vagrant-libvirt/action/shutdown_domain'
|
5
|
+
|
6
|
+
describe VagrantPlugins::ProviderLibvirt::Action::ShutdownDomain do
|
7
|
+
subject { described_class.new(app, env, target_state, current_state) }
|
8
|
+
|
9
|
+
include_context 'unit'
|
10
|
+
include_context 'libvirt'
|
11
|
+
|
12
|
+
let(:driver) { double('driver') }
|
13
|
+
let(:libvirt_domain) { double('libvirt_domain') }
|
14
|
+
let(:servers) { double('servers') }
|
15
|
+
let(:current_state) { :running }
|
16
|
+
let(:target_state) { :shutoff }
|
17
|
+
|
18
|
+
before do
|
19
|
+
allow(machine.provider).to receive('driver').and_return(driver)
|
20
|
+
allow(driver).to receive(:created?).and_return(true)
|
21
|
+
allow(driver).to receive(:connection).and_return(connection)
|
22
|
+
end
|
23
|
+
|
24
|
+
describe '#call' do
|
25
|
+
before do
|
26
|
+
allow(connection).to receive(:servers).and_return(servers)
|
27
|
+
allow(servers).to receive(:get).and_return(domain)
|
28
|
+
allow(ui).to receive(:info).with('Attempting direct shutdown of domain...')
|
29
|
+
end
|
30
|
+
|
31
|
+
context "when state is shutoff" do
|
32
|
+
before do
|
33
|
+
allow(driver).to receive(:state).and_return(:shutoff)
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should not shutdown" do
|
37
|
+
expect(domain).not_to receive(:shutoff)
|
38
|
+
subject.call(env)
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should not print shutdown message" do
|
42
|
+
expect(ui).not_to receive(:info)
|
43
|
+
subject.call(env)
|
44
|
+
end
|
45
|
+
|
46
|
+
it "should provide a true result" do
|
47
|
+
subject.call(env)
|
48
|
+
expect(env[:result]).to be_truthy
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
context "when state is running" do
|
53
|
+
before do
|
54
|
+
allow(driver).to receive(:state).and_return(:running)
|
55
|
+
end
|
56
|
+
|
57
|
+
it "should shutdown" do
|
58
|
+
expect(domain).to receive(:wait_for)
|
59
|
+
expect(domain).to receive(:shutdown)
|
60
|
+
subject.call(env)
|
61
|
+
end
|
62
|
+
|
63
|
+
it "should print shutdown message" do
|
64
|
+
expect(domain).to receive(:wait_for)
|
65
|
+
expect(domain).to receive(:shutdown)
|
66
|
+
expect(ui).to receive(:info).with('Attempting direct shutdown of domain...')
|
67
|
+
subject.call(env)
|
68
|
+
end
|
69
|
+
|
70
|
+
context "when final state is not shutoff" do
|
71
|
+
before do
|
72
|
+
expect(driver).to receive(:state).and_return(:running).exactly(3).times
|
73
|
+
expect(domain).to receive(:wait_for)
|
74
|
+
expect(domain).to receive(:shutdown)
|
75
|
+
end
|
76
|
+
|
77
|
+
it "should provide a false result" do
|
78
|
+
subject.call(env)
|
79
|
+
expect(env[:result]).to be_falsey
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
context "when final state is shutoff" do
|
84
|
+
before do
|
85
|
+
expect(driver).to receive(:state).and_return(:running).exactly(2).times
|
86
|
+
expect(driver).to receive(:state).and_return(:shutoff).exactly(1).times
|
87
|
+
expect(domain).to receive(:wait_for)
|
88
|
+
expect(domain).to receive(:shutdown)
|
89
|
+
end
|
90
|
+
|
91
|
+
it "should provide a true result" do
|
92
|
+
subject.call(env)
|
93
|
+
expect(env[:result]).to be_truthy
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
context "when timeout exceeded" do
|
98
|
+
before do
|
99
|
+
expect(machine).to receive_message_chain('config.vm.graceful_halt_timeout').and_return(1)
|
100
|
+
expect(app).to receive(:call) { sleep 1.5 }
|
101
|
+
expect(driver).to receive(:state).and_return(:running).exactly(1).times
|
102
|
+
expect(domain).to_not receive(:wait_for)
|
103
|
+
expect(domain).to_not receive(:shutdown)
|
104
|
+
end
|
105
|
+
|
106
|
+
it "should provide a false result" do
|
107
|
+
subject.call(env)
|
108
|
+
expect(env[:result]).to be_falsey
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
context "when timeout not exceeded" do
|
113
|
+
before do
|
114
|
+
expect(machine).to receive_message_chain('config.vm.graceful_halt_timeout').and_return(2)
|
115
|
+
expect(app).to receive(:call) { sleep 1 }
|
116
|
+
expect(driver).to receive(:state).and_return(:running).exactly(3).times
|
117
|
+
expect(domain).to receive(:wait_for) do |time|
|
118
|
+
expect(time).to be < 1
|
119
|
+
expect(time).to be > 0
|
120
|
+
end
|
121
|
+
expect(domain).to receive(:shutdown)
|
122
|
+
end
|
123
|
+
|
124
|
+
it "should wait for the reduced time" do
|
125
|
+
subject.call(env)
|
126
|
+
expect(env[:result]).to be_falsey
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|