Provide support for packaging into v2 format (#1360)

Support packaging multi disk machines however default to v1 format
unless v2 format is explicitly enabled. Output a warning to alert users
of the possible change in behaviour in the future.

Allows selecting the format to use via the environment, where use of v1
format with a multi disk machine will ignore the other disks.
This commit is contained in:
Darragh Bailey
2021-10-08 11:05:10 +01:00
committed by GitHub
parent 81b6fb715a
commit 56282b965c
2 changed files with 281 additions and 30 deletions

View File

@@ -16,6 +16,8 @@ describe VagrantPlugins::ProviderLibvirt::Action::PackageDomain do
let(:libvirt_domain) { double('libvirt_domain') }
let(:servers) { double('servers') }
let(:volumes) { double('volumes') }
let(:metadata_file) { double('file') }
let(:vagrantfile_file) { double('file') }
describe '#call' do
before do
@@ -54,10 +56,19 @@ describe VagrantPlugins::ProviderLibvirt::Action::PackageDomain do
expect(subject).to receive(:`).with(/qemu-img info --output=json .*\/box.img/).and_return(
{ 'virtual-size': 5*1024*1024*1024 }.to_json
)
expect(File).to receive(:write).with(
/.*\/metadata.json/,
<<-EOF.unindent
{
"provider": "libvirt",
"format": "qcow2",
"virtual_size": 5
}
EOF
)
expect(File).to receive(:write).with(/.*\/Vagrantfile/, /.*/)
expect(subject.call(env)).to be_nil
expect(File.exist?(File.join(temp_dir, 'metadata.json'))).to eq(true)
expect(File.exist?(File.join(temp_dir, 'Vagrantfile'))).to eq(true)
end
end
@@ -85,6 +96,170 @@ describe VagrantPlugins::ProviderLibvirt::Action::PackageDomain do
expect(subject.call(env)).to be_nil
end
end
context 'when detecting the format' do
let(:root_disk) { double('libvirt_domain_disk') }
let(:disk2) { double('libvirt_additional_disk') }
let(:fake_env) { Hash.new }
before do
allow(root_disk).to receive(:name).and_return('default_domain.img')
allow(disk2).to receive(:name).and_return('disk2.img')
allow(libvirt_domain).to receive(:name).and_return('default_domain')
end
context 'with two disks' do
before do
allow(domain).to receive(:volumes).and_return([root_disk, disk2])
end
it 'should emit a warning' do
expect(ui).to receive(:info).with('Packaging domain...')
expect(ui).to receive(:warn).with(/Detected more than one volume for machine.*\n.*/)
expect(subject).to receive(:package_v1)
expect(subject.call(env)).to be_nil
end
end
context 'with format set to v1' do
before do
allow(domain).to receive(:volumes).and_return([root_disk])
stub_const("ENV", fake_env)
fake_env['VAGRANT_LIBVIRT_BOX_FORMAT_VERSION'] = "v1"
end
it 'should call v1 packaging' do
expect(ui).to receive(:info).with('Packaging domain...')
expect(subject).to receive(:package_v1)
expect(subject.call(env)).to be_nil
end
end
context 'with format set to v2' do
before do
allow(domain).to receive(:volumes).and_return([root_disk])
stub_const("ENV", fake_env)
fake_env['VAGRANT_LIBVIRT_BOX_FORMAT_VERSION'] = "v2"
end
it 'should call v1 packaging' do
expect(ui).to receive(:info).with('Packaging domain...')
expect(subject).to receive(:package_v2)
expect(subject.call(env)).to be_nil
end
end
context 'with invalid format' do
before do
allow(domain).to receive(:volumes).and_return([root_disk])
stub_const("ENV", fake_env)
fake_env['VAGRANT_LIBVIRT_BOX_FORMAT_VERSION'] = "bad format"
end
it 'should emit a warning and default to v1' do
expect(ui).to receive(:info).with('Packaging domain...')
expect(ui).to receive(:warn).with(/Unrecognized value for.*defaulting to v1/)
expect(subject).to receive(:package_v1)
expect(subject.call(env)).to be_nil
end
end
end
context 'with v2 format' do
let(:disk1) { double('libvirt_domain_disk') }
let(:disk2) { double('libvirt_additional_disk') }
let(:fake_env) { Hash.new }
before do
allow(disk1).to receive(:name).and_return('default_domain.img')
allow(disk2).to receive(:name).and_return('disk2.img')
allow(libvirt_domain).to receive(:name).and_return('default_domain')
allow(subject).to receive(:download_image).and_return(true).twice()
stub_const("ENV", fake_env)
fake_env['VAGRANT_LIBVIRT_BOX_FORMAT_VERSION'] = "v2"
end
context 'with 2 disks' do
before do
allow(domain).to receive(:volumes).and_return([disk1, disk2])
end
it 'should succeed' do
expect(ui).to receive(:info).with('Packaging domain...')
expect(ui).to receive(:info).with(/Downloading default_domain.img to .*\/box_1.img/)
expect(ui).to receive(:info).with('Image has backing image, copying image and rebasing ...')
expect(subject).to receive(:`).with(/qemu-img info .*\/box_1.img | grep 'backing file:' | cut -d ':' -f2/).and_return("some image")
expect(subject).to receive(:`).with(/qemu-img rebase -p -b "" .*\/box_1.img/)
expect(subject).to receive(:`).with(/virt-sysprep --no-logfile --operations .* -a .*\/box_1.img .*/)
expect(subject).to receive(:`).with(/virt-sparsify --in-place .*\/box_1.img/)
expect(ui).to receive(:info).with(/Downloading disk2.img to .*\/box_2.img/)
expect(ui).to receive(:info).with('Image has backing image, copying image and rebasing ...')
expect(subject).to receive(:`).with(/qemu-img info .*\/box_2.img | grep 'backing file:' | cut -d ':' -f2/).and_return("some image")
expect(subject).to receive(:`).with(/qemu-img rebase -p -b "" .*\/box_2.img/)
expect(subject).to receive(:`).with(/virt-sparsify --in-place .*\/box_2.img/)
expect(File).to receive(:write).with(
/.*\/metadata.json/,
<<-EOF.unindent.rstrip()
{
"provider": "libvirt",
"format": "qcow2",
"disks": [
{
"path": "box_1.img"
},
{
"path": "box_2.img"
}
]
}
EOF
)
expect(File).to receive(:write).with(/.*\/Vagrantfile/, /.*/)
expect(subject.call(env)).to be_nil
end
end
context 'with 1 disk' do
before do
allow(domain).to receive(:volumes).and_return([disk1])
end
it 'should succeed' do
expect(ui).to receive(:info).with('Packaging domain...')
expect(ui).to receive(:info).with(/Downloading default_domain.img to .*\/box_1.img/)
expect(ui).to receive(:info).with('Image has backing image, copying image and rebasing ...')
expect(subject).to receive(:`).with(/qemu-img info .*\/box_1.img | grep 'backing file:' | cut -d ':' -f2/).and_return("some image")
expect(subject).to receive(:`).with(/qemu-img rebase -p -b "" .*\/box_1.img/)
expect(subject).to receive(:`).with(/virt-sysprep --no-logfile --operations .* -a .*\/box_1.img .*/)
expect(subject).to receive(:`).with(/virt-sparsify --in-place .*\/box_1.img/)
expect(File).to receive(:write).with(
/.*\/metadata.json/,
<<-EOF.unindent.rstrip()
{
"provider": "libvirt",
"format": "qcow2",
"disks": [
{
"path": "box_1.img"
}
]
}
EOF
)
expect(File).to receive(:write).with(/.*\/Vagrantfile/, /.*/)
expect(subject.call(env)).to be_nil
end
end
end
end
describe '#vagrantfile_content' do