mirror of
https://github.com/vagrant-libvirt/vagrant-libvirt.git
synced 2025-02-25 18:55:27 -06:00
Turn on frozen string support in all files by using a comment to avoid enabling across dependencies where it may not work. Fixes: #1177
444 lines
16 KiB
Ruby
444 lines
16 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
require 'spec_helper'
|
|
require 'json'
|
|
require 'support/sharedcontext'
|
|
require 'support/libvirt_context'
|
|
|
|
require 'vagrant-libvirt/action/destroy_domain'
|
|
require 'vagrant-libvirt/util/byte_number'
|
|
|
|
|
|
describe VagrantPlugins::ProviderLibvirt::Action::HandleBoxImage do
|
|
subject { described_class.new(app, env) }
|
|
|
|
include_context 'unit'
|
|
include_context 'libvirt'
|
|
|
|
let(:libvirt_client) { double('libvirt_client') }
|
|
let(:volumes) { double('volumes') }
|
|
let(:all) { double('all') }
|
|
let(:box_volume) { double('box_volume') }
|
|
let(:fog_volume) { double('fog_volume') }
|
|
let(:config) { double('config') }
|
|
|
|
qemu_json_return_5G = JSON.dump({
|
|
"virtual-size": 5368709120,
|
|
"filename": "/test/box.img",
|
|
"cluster-size": 65536,
|
|
"format": "qcow2",
|
|
"actual-size": 655360,
|
|
"dirty-flag": false
|
|
})
|
|
byte_number_5G = ByteNumber.new(5368709120)
|
|
|
|
|
|
qemu_json_return_10G = JSON.dump({
|
|
"virtual-size": 10737423360,
|
|
"filename": "/test/disk.qcow2",
|
|
"cluster-size": 65536,
|
|
"format": "qcow2",
|
|
"actual-size": 655360,
|
|
"dirty-flag": false
|
|
})
|
|
byte_number_10G = ByteNumber.new(10737423360)
|
|
|
|
qemu_json_return_20G = JSON.dump({
|
|
"virtual-size": 21474836480,
|
|
"filename": "/test/box_2.img",
|
|
"cluster-size": 65536,
|
|
"format": "qcow2",
|
|
"actual-size": 1508708352,
|
|
"dirty-flag": false
|
|
})
|
|
byte_number_20G = ByteNumber.new(21474836480)
|
|
|
|
|
|
|
|
|
|
describe '#call' do
|
|
before do
|
|
allow_any_instance_of(VagrantPlugins::ProviderLibvirt::Driver)
|
|
.to receive(:connection).and_return(connection)
|
|
allow(connection).to receive(:client).and_return(libvirt_client)
|
|
allow(connection).to receive(:volumes).and_return(volumes)
|
|
allow(volumes).to receive(:all).and_return(all)
|
|
allow(env[:ui]).to receive(:clear_line)
|
|
|
|
end
|
|
|
|
context 'when one disk in metadata.json' do
|
|
before do
|
|
allow(all).to receive(:first).and_return(box_volume)
|
|
allow(box_volume).to receive(:id).and_return(1)
|
|
allow(env[:machine]).to receive_message_chain("box.name") { 'test' }
|
|
allow(env[:machine]).to receive_message_chain("box.version") { '1.1.1' }
|
|
allow(env[:machine]).to receive_message_chain("box.metadata") { Hash[
|
|
'virtual_size'=> 5,
|
|
'format' => 'qcow2'
|
|
]
|
|
}
|
|
allow(env[:machine]).to receive_message_chain("box.directory.join") do |arg|
|
|
'/test/' + arg.to_s
|
|
end
|
|
end
|
|
|
|
it 'should have one disk in machine env' do
|
|
expect(subject.call(env)).to be_nil
|
|
expect(env[:box_volume_number]).to eq(1)
|
|
expect(env[:box_volumes]).to eq(
|
|
[
|
|
{
|
|
:path=>"/test/box.img",
|
|
:name=>"test_vagrant_box_image_1.1.1_box.img",
|
|
:virtual_size=>byte_number_5G,
|
|
:format=>"qcow2"
|
|
}
|
|
]
|
|
)
|
|
end
|
|
|
|
context 'When config.machine_virtual_size is set and smaller than box_virtual_size' do
|
|
before do
|
|
allow(env[:machine]).to receive_message_chain("provider_config.machine_virtual_size").and_return(1)
|
|
end
|
|
it 'should warning must be raise' do
|
|
expect(ui).to receive(:warn).with("Ignoring requested virtual disk size of '1' as it is below\nthe minimum box image size of '5'.")
|
|
expect(subject.call(env)).to be_nil
|
|
expect(env[:box_volumes]).to eq(
|
|
[
|
|
{
|
|
:path=>"/test/box.img",
|
|
:name=>"test_vagrant_box_image_1.1.1_box.img",
|
|
:virtual_size=>byte_number_5G,
|
|
:format=>"qcow2"
|
|
}
|
|
]
|
|
)
|
|
end
|
|
end
|
|
|
|
context 'When config.machine_virtual_size is set and higher than box_virtual_size' do
|
|
before do
|
|
allow(env[:machine]).to receive_message_chain("provider_config.machine_virtual_size").and_return(20)
|
|
end
|
|
it 'should be use' do
|
|
expect(ui).to receive(:info).with("Created volume larger than box defaults, will require manual resizing of\nfilesystems to utilize.")
|
|
expect(subject.call(env)).to be_nil
|
|
expect(env[:box_volumes]).to eq(
|
|
[
|
|
{
|
|
:path=>"/test/box.img",
|
|
:name=>"test_vagrant_box_image_1.1.1_box.img",
|
|
:virtual_size=>byte_number_20G,
|
|
:format=>"qcow2"
|
|
}
|
|
]
|
|
)
|
|
end
|
|
end
|
|
|
|
context 'when disk image not in storage pool' do
|
|
before do
|
|
allow(File).to receive(:exist?).and_return(true)
|
|
allow(File).to receive(:size).and_return(5*1024*1024*1024)
|
|
allow(all).to receive(:first).and_return(nil)
|
|
allow(subject).to receive(:upload_image).and_return(true)
|
|
allow(volumes).to receive(:create).and_return(fog_volume)
|
|
end
|
|
|
|
it 'should upload disk' do
|
|
expect(ui).to receive(:info).with('Uploading base box image as volume into Libvirt storage...')
|
|
expect(logger).to receive(:info).with('Creating volume test_vagrant_box_image_1.1.1_box.img in storage pool default.')
|
|
expect(volumes).to receive(:create).with(
|
|
hash_including(
|
|
:name => "test_vagrant_box_image_1.1.1_box.img",
|
|
:allocation => "5120M",
|
|
:capacity => "5368709120B",
|
|
)
|
|
)
|
|
expect(subject).to receive(:upload_image)
|
|
expect(subject.call(env)).to be_nil
|
|
end
|
|
end
|
|
|
|
context 'when disk image already in storage pool' do
|
|
before do
|
|
allow(all).to receive(:first).and_return(box_volume)
|
|
allow(box_volume).to receive(:id).and_return(1)
|
|
end
|
|
|
|
it 'should skip disk upload' do
|
|
expect(volumes).not_to receive(:create)
|
|
expect(subject).not_to receive(:upload_image)
|
|
expect(subject.call(env)).to be_nil
|
|
end
|
|
end
|
|
end
|
|
|
|
context 'when three disks in metadata.json' do
|
|
let(:status) { double }
|
|
|
|
before do
|
|
allow(all).to receive(:first).and_return(box_volume)
|
|
allow(box_volume).to receive(:id).and_return(1)
|
|
allow(env[:machine]).to receive_message_chain("box.name") { 'test' }
|
|
allow(env[:machine]).to receive_message_chain("box.version") { '1.1.1' }
|
|
allow(env[:machine]).to receive_message_chain("box.metadata") { Hash[
|
|
'disks' => [
|
|
{
|
|
'path' => 'box.img',
|
|
'name' => 'send_box_name',
|
|
},
|
|
{
|
|
'path' => 'disk.qcow2',
|
|
},
|
|
{
|
|
'path' => 'box_2.img',
|
|
},
|
|
],
|
|
]}
|
|
allow(env[:machine]).to receive_message_chain("box.directory.join") do |arg|
|
|
'/test/' + arg.to_s
|
|
end
|
|
allow(status).to receive(:success?).and_return(true)
|
|
allow(Open3).to receive(:capture3).with('qemu-img', 'info', '--output=json', '/test/box.img').and_return([
|
|
qemu_json_return_5G, "", status
|
|
])
|
|
allow(Open3).to receive(:capture3).with('qemu-img', 'info', '--output=json', '/test/disk.qcow2').and_return([
|
|
qemu_json_return_10G, "", status
|
|
])
|
|
allow(Open3).to receive(:capture3).with('qemu-img', 'info', '--output=json', '/test/box_2.img').and_return([
|
|
qemu_json_return_20G, "", status
|
|
])
|
|
end
|
|
|
|
it 'should have three disks in machine env' do
|
|
expect(subject.call(env)).to be_nil
|
|
expect(env[:box_volume_number]).to eq(3)
|
|
expect(env[:box_volumes]).to eq(
|
|
[
|
|
{
|
|
:path=>"/test/box.img",
|
|
:name=>"test_vagrant_box_image_1.1.1_send_box_name.img",
|
|
:virtual_size=>byte_number_5G,
|
|
:format=>"qcow2"
|
|
},
|
|
{
|
|
:path=>"/test/disk.qcow2",
|
|
:name=>"test_vagrant_box_image_1.1.1_disk.img",
|
|
:virtual_size=>byte_number_10G,
|
|
:format=>"qcow2"
|
|
},
|
|
{
|
|
:path=>"/test/box_2.img",
|
|
:name=>"test_vagrant_box_image_1.1.1_box_2.img",
|
|
:virtual_size=>byte_number_20G,
|
|
:format=>"qcow2"
|
|
}
|
|
]
|
|
)
|
|
end
|
|
|
|
context 'when none of the disks in storage pool' do
|
|
before do
|
|
allow(File).to receive(:exist?).and_return(true)
|
|
allow(File).to receive(:size).and_return(5*1024*1024*1024, 10*1024*1024*1024, 20*1024*1024*1024)
|
|
allow(all).to receive(:first).and_return(nil)
|
|
allow(subject).to receive(:upload_image).and_return(true)
|
|
allow(volumes).to receive(:create).and_return(fog_volume)
|
|
end
|
|
|
|
it 'should upload all 3 disks' do
|
|
expect(ui).to receive(:info).with('Uploading base box image as volume into Libvirt storage...')
|
|
expect(logger).to receive(:info).with('Creating volume test_vagrant_box_image_1.1.1_send_box_name.img in storage pool default.')
|
|
expect(volumes).to receive(:create).with(
|
|
hash_including(
|
|
:name => "test_vagrant_box_image_1.1.1_send_box_name.img",
|
|
:allocation => "5120M",
|
|
:capacity => "5368709120B",
|
|
)
|
|
)
|
|
expect(subject).to receive(:upload_image)
|
|
expect(ui).to receive(:info).with('Uploading base box image as volume into Libvirt storage...')
|
|
expect(logger).to receive(:info).with('Creating volume test_vagrant_box_image_1.1.1_disk.img in storage pool default.')
|
|
expect(volumes).to receive(:create).with(
|
|
hash_including(
|
|
:name => "test_vagrant_box_image_1.1.1_disk.img",
|
|
:allocation => "10240M",
|
|
:capacity => "10737423360B",
|
|
)
|
|
)
|
|
expect(subject).to receive(:upload_image)
|
|
expect(ui).to receive(:info).with('Uploading base box image as volume into Libvirt storage...')
|
|
expect(logger).to receive(:info).with('Creating volume test_vagrant_box_image_1.1.1_box_2.img in storage pool default.')
|
|
expect(volumes).to receive(:create).with(
|
|
hash_including(
|
|
:name => "test_vagrant_box_image_1.1.1_box_2.img",
|
|
:allocation => "20480M",
|
|
:capacity => "21474836480B",
|
|
)
|
|
)
|
|
expect(subject).to receive(:upload_image)
|
|
|
|
expect(subject.call(env)).to be_nil
|
|
end
|
|
end
|
|
|
|
context 'when only disk 0 in storage pool' do
|
|
before do
|
|
allow(File).to receive(:exist?).and_return(true)
|
|
allow(File).to receive(:size).and_return(10*1024*1024*1024, 20*1024*1024*1024)
|
|
allow(all).to receive(:first).and_return(box_volume, nil, nil)
|
|
allow(box_volume).to receive(:id).and_return(1)
|
|
allow(subject).to receive(:upload_image).and_return(true)
|
|
allow(volumes).to receive(:create).and_return(fog_volume)
|
|
end
|
|
|
|
it 'upload disks 1 and 2 only' do
|
|
expect(ui).to receive(:info).with('Uploading base box image as volume into Libvirt storage...')
|
|
expect(logger).to receive(:info).with('Creating volume test_vagrant_box_image_1.1.1_disk.img in storage pool default.')
|
|
expect(volumes).to receive(:create).with(hash_including(:name => "test_vagrant_box_image_1.1.1_disk.img"))
|
|
expect(subject).to receive(:upload_image)
|
|
expect(ui).to receive(:info).with('Uploading base box image as volume into Libvirt storage...')
|
|
expect(logger).to receive(:info).with('Creating volume test_vagrant_box_image_1.1.1_box_2.img in storage pool default.')
|
|
expect(volumes).to receive(:create).with(hash_including(:name => "test_vagrant_box_image_1.1.1_box_2.img"))
|
|
expect(subject).to receive(:upload_image)
|
|
|
|
expect(subject.call(env)).to be_nil
|
|
end
|
|
end
|
|
|
|
context 'when has all disks on storage pool' do
|
|
before do
|
|
allow(all).to receive(:first).and_return(box_volume)
|
|
allow(box_volume).to receive(:id).and_return(1)
|
|
end
|
|
|
|
it 'should skip disk upload' do
|
|
expect(ui).not_to receive(:info).with('Uploading base box image as volume into Libvirt storage...')
|
|
expect(volumes).not_to receive(:create)
|
|
expect(subject).not_to receive(:upload_image)
|
|
expect(subject.call(env)).to be_nil
|
|
end
|
|
end
|
|
end
|
|
|
|
context 'when wrong box format in metadata.json' do
|
|
before do
|
|
allow(all).to receive(:first).and_return(box_volume)
|
|
allow(box_volume).to receive(:id).and_return(1)
|
|
allow(env[:machine]).to receive_message_chain("box.name") { 'test' }
|
|
allow(env[:machine]).to receive_message_chain("box.version") { '1.1.1' }
|
|
allow(env[:machine]).to receive_message_chain("box.metadata") { Hash[
|
|
'virtual_size'=> 5,
|
|
'format' => 'wrongFormat'
|
|
]
|
|
}
|
|
allow(env[:machine]).to receive_message_chain("box.directory.join") do |arg|
|
|
'/test/' + arg.to_s
|
|
end
|
|
end
|
|
|
|
it 'should raise WrongBoxFormatSet exception' do
|
|
expect{ subject.call(env) }.to raise_error(VagrantPlugins::ProviderLibvirt::Errors::WrongBoxFormatSet)
|
|
end
|
|
|
|
end
|
|
|
|
context 'when invalid format in metadata.json' do
|
|
let(:status) { double }
|
|
|
|
before do
|
|
allow(all).to receive(:first).and_return(box_volume)
|
|
allow(box_volume).to receive(:id).and_return(1)
|
|
allow(env[:machine]).to receive_message_chain("box.name") { 'test' }
|
|
allow(env[:machine]).to receive_message_chain("box.version") { '1.1.1' }
|
|
allow(env[:machine]).to receive_message_chain("box.metadata") { box_metadata }
|
|
allow(env[:machine]).to receive_message_chain("box.directory.join") do |arg|
|
|
'/test/' + arg.to_s
|
|
end
|
|
allow(status).to receive(:success?).and_return(true)
|
|
allow(Open3).to receive(:capture3).with('qemu-img', 'info', "--output=json", '/test/box.img').and_return([
|
|
qemu_json_return_5G, "", status
|
|
])
|
|
allow(Open3).to receive(:capture3).with('qemu-img', 'info', "--output=json", '/test/disk.qcow2').and_return([
|
|
qemu_json_return_10G, "", status
|
|
])
|
|
allow(Open3).to receive(:capture3).with('qemu-img', 'info', "--output=json", '/test/box_2.img').and_return([
|
|
qemu_json_return_20G, "", status
|
|
])
|
|
end
|
|
|
|
context 'with one disk having wrong disk format' do
|
|
let(:box_metadata) {
|
|
Hash[
|
|
'disks' => [
|
|
{
|
|
'path' => 'box.img',
|
|
'name' =>'send_box_name.img',
|
|
'format' => 'wrongFormat'
|
|
},
|
|
{
|
|
'path' => 'disk.qcow2',
|
|
},
|
|
{
|
|
'path' => 'box_2.img',
|
|
},
|
|
],
|
|
]
|
|
}
|
|
|
|
it 'should be ignored' do
|
|
expect(subject.call(env)).to be_nil
|
|
end
|
|
end
|
|
|
|
context 'with one disk missing path' do
|
|
let(:box_metadata) {
|
|
Hash[
|
|
'disks' => [
|
|
{
|
|
'path' => 'box.img',
|
|
},
|
|
{
|
|
'name' => 'send_box_name',
|
|
},
|
|
{
|
|
'path' => 'box_2.img',
|
|
},
|
|
],
|
|
]
|
|
}
|
|
|
|
it 'should raise an exception' do
|
|
expect{ subject.call(env) }.to raise_error(VagrantPlugins::ProviderLibvirt::Errors::BoxFormatMissingAttribute, /: 'disks\[1\]\['path'\]'/)
|
|
end
|
|
end
|
|
|
|
context 'with one disk name duplicating a path of another' do
|
|
let(:box_metadata) {
|
|
Hash[
|
|
'disks' => [
|
|
{
|
|
'path' => 'box.img',
|
|
'name' => 'box_2',
|
|
},
|
|
{
|
|
'path' => 'disk.qcow2',
|
|
},
|
|
{
|
|
'path' => 'box_2.img',
|
|
},
|
|
],
|
|
]
|
|
}
|
|
|
|
it 'should raise an exception' do
|
|
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\]'/)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|