2021-06-30 13:27:03 +01:00
|
|
|
# frozen_string_literal: true
|
|
|
|
|
|
2020-11-15 23:28:43 +00:00
|
|
|
require 'spec_helper'
|
|
|
|
|
require 'support/sharedcontext'
|
|
|
|
|
require 'support/libvirt_context'
|
|
|
|
|
|
|
|
|
|
require 'vagrant-libvirt/errors'
|
|
|
|
|
require 'vagrant-libvirt/action/start_domain'
|
|
|
|
|
|
|
|
|
|
describe VagrantPlugins::ProviderLibvirt::Action::StartDomain do
|
|
|
|
|
subject { described_class.new(app, env) }
|
|
|
|
|
|
|
|
|
|
include_context 'unit'
|
|
|
|
|
include_context 'libvirt'
|
|
|
|
|
|
|
|
|
|
let(:servers) { double('servers') }
|
|
|
|
|
|
|
|
|
|
let(:domain_xml) { File.read(File.join(File.dirname(__FILE__), File.basename(__FILE__, '.rb'), test_file)) }
|
2020-12-05 15:24:42 +00:00
|
|
|
let(:updated_domain_xml) { File.read(File.join(File.dirname(__FILE__), File.basename(__FILE__, '.rb'), updated_test_file)) }
|
2020-11-15 23:28:43 +00:00
|
|
|
|
2022-05-06 20:30:55 +01:00
|
|
|
before do
|
|
|
|
|
allow(driver).to receive(:created?).and_return(true)
|
|
|
|
|
end
|
|
|
|
|
|
2020-11-15 23:28:43 +00:00
|
|
|
describe '#call' do
|
2021-09-11 22:00:33 +01:00
|
|
|
let(:test_file) { 'default.xml' }
|
|
|
|
|
|
2020-11-15 23:28:43 +00:00
|
|
|
before do
|
|
|
|
|
allow(connection).to receive(:client).and_return(libvirt_client)
|
|
|
|
|
allow(libvirt_client).to receive(:lookup_domain_by_uuid).and_return(libvirt_domain)
|
|
|
|
|
|
|
|
|
|
allow(connection).to receive(:servers).and_return(servers)
|
|
|
|
|
allow(servers).to receive(:get).and_return(domain)
|
2020-12-16 20:19:24 +01:00
|
|
|
|
2021-09-11 19:29:45 +01:00
|
|
|
allow(logger).to receive(:debug)
|
2022-06-03 10:42:28 +01:00
|
|
|
allow(logger).to receive(:info)
|
2021-09-11 22:00:33 +01:00
|
|
|
|
|
|
|
|
allow(libvirt_domain).to receive(:xml_desc).and_return(domain_xml)
|
|
|
|
|
|
|
|
|
|
allow(libvirt_domain).to receive(:max_memory).and_return(512*1024)
|
|
|
|
|
allow(libvirt_domain).to receive(:num_vcpus).and_return(1)
|
2020-11-15 23:28:43 +00:00
|
|
|
end
|
|
|
|
|
|
2021-09-11 22:00:33 +01:00
|
|
|
it 'should execute without changing' do
|
2022-06-03 10:42:28 +01:00
|
|
|
expect(ui).to_not receive(:error)
|
|
|
|
|
expect(libvirt_client).to_not receive(:define_domain_xml)
|
2021-09-11 22:00:33 +01:00
|
|
|
expect(libvirt_domain).to receive(:autostart=)
|
|
|
|
|
expect(domain).to receive(:start)
|
2020-11-15 23:28:43 +00:00
|
|
|
|
2021-09-11 22:00:33 +01:00
|
|
|
expect(subject.call(env)).to be_nil
|
|
|
|
|
end
|
2020-11-15 23:28:43 +00:00
|
|
|
|
2022-08-28 12:10:46 +01:00
|
|
|
context 'when xml is formatted differently' do
|
|
|
|
|
let(:test_file) { 'default_with_different_formatting.xml' }
|
|
|
|
|
let(:updated_domain_xml) {
|
|
|
|
|
new_xml = domain_xml.dup
|
|
|
|
|
new_xml.gsub!(/<cpu .*<\/cpu>/m, '<cpu check="none" mode="host-passthrough"/>')
|
|
|
|
|
new_xml
|
|
|
|
|
}
|
|
|
|
|
let(:vagrantfile_providerconfig) do
|
|
|
|
|
<<-EOF
|
|
|
|
|
libvirt.cpu_mode = "host-passthrough"
|
|
|
|
|
EOF
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
it 'should correctly detect the domain was updated' do
|
|
|
|
|
expect(ui).to_not receive(:error)
|
|
|
|
|
expect(libvirt_domain).to receive(:autostart=)
|
|
|
|
|
expect(connection).to receive(:define_domain).and_return(libvirt_domain)
|
|
|
|
|
expect(libvirt_domain).to receive(:xml_desc).and_return(domain_xml, updated_domain_xml)
|
|
|
|
|
expect(domain).to receive(:start)
|
|
|
|
|
|
|
|
|
|
expect(subject.call(env)).to be_nil
|
|
|
|
|
end
|
2022-08-30 12:47:05 +01:00
|
|
|
end
|
|
|
|
|
|
|
|
|
|
context 'when xml not applied' do
|
|
|
|
|
let(:test_file) { 'default_with_different_formatting.xml' }
|
|
|
|
|
let(:updated_domain_xml) {
|
|
|
|
|
new_xml = domain_xml.dup
|
|
|
|
|
new_xml.gsub!(/<cpu .*<\/cpu>/m, '<cpu mode="host-passthrough"/>')
|
|
|
|
|
new_xml
|
|
|
|
|
}
|
|
|
|
|
let(:vagrantfile_providerconfig) do
|
|
|
|
|
<<-EOF
|
|
|
|
|
libvirt.cpu_mode = "host-passthrough"
|
|
|
|
|
EOF
|
|
|
|
|
end
|
2022-08-28 12:10:46 +01:00
|
|
|
|
2022-08-30 12:47:05 +01:00
|
|
|
it 'should error and revert the update' do
|
|
|
|
|
expect(ui).to receive(:error)
|
|
|
|
|
expect(connection).to receive(:define_domain).and_return(libvirt_domain)
|
|
|
|
|
expect(connection).to receive(:define_domain).with(domain_xml) # undo
|
|
|
|
|
expect(libvirt_domain).to receive(:xml_desc).and_return(domain_xml, updated_domain_xml)
|
|
|
|
|
expect(domain).to_not receive(:start)
|
|
|
|
|
|
|
|
|
|
expect { subject.call(env) }.to raise_error(VagrantPlugins::ProviderLibvirt::Errors::FogError)
|
|
|
|
|
end
|
2022-08-28 12:10:46 +01:00
|
|
|
end
|
|
|
|
|
|
2022-06-03 10:42:28 +01:00
|
|
|
context 'when any setting changed' do
|
|
|
|
|
let(:vagrantfile_providerconfig) do
|
|
|
|
|
<<-EOF
|
|
|
|
|
libvirt.cpus = 2
|
|
|
|
|
EOF
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
let(:updated_domain_xml) {
|
|
|
|
|
new_xml = domain_xml.dup
|
|
|
|
|
new_xml['<vcpu>1</vcpu>'] = '<vcpu>2</vcpu>'
|
|
|
|
|
new_xml
|
|
|
|
|
}
|
2020-11-15 23:28:43 +00:00
|
|
|
|
2022-06-03 10:42:28 +01:00
|
|
|
it 'should update the domain' do
|
|
|
|
|
expect(ui).to_not receive(:error)
|
2020-11-15 23:28:43 +00:00
|
|
|
expect(libvirt_domain).to receive(:autostart=)
|
2022-06-03 10:42:28 +01:00
|
|
|
expect(connection).to receive(:define_domain).and_return(libvirt_domain)
|
|
|
|
|
expect(libvirt_domain).to receive(:xml_desc).and_return(domain_xml, updated_domain_xml)
|
2020-11-15 23:28:43 +00:00
|
|
|
expect(domain).to receive(:start)
|
|
|
|
|
|
|
|
|
|
expect(subject.call(env)).to be_nil
|
|
|
|
|
end
|
2022-06-03 10:42:28 +01:00
|
|
|
|
|
|
|
|
context 'when there is an error during update' do
|
|
|
|
|
it 'should skip attempting to start' do
|
|
|
|
|
expect(ui).to receive(:error)
|
|
|
|
|
expect(connection).to receive(:define_domain).and_raise(::Libvirt::Error)
|
|
|
|
|
|
|
|
|
|
expect { subject.call(env) }.to raise_error(VagrantPlugins::ProviderLibvirt::Errors::VagrantLibvirtError)
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
context 'when there is an interrupt' do
|
|
|
|
|
it 'should skip attempting to start' do
|
|
|
|
|
expect(connection).to receive(:define_domain).and_raise(Interrupt)
|
|
|
|
|
|
|
|
|
|
expect { subject.call(env) }.to raise_error(Interrupt)
|
|
|
|
|
end
|
|
|
|
|
end
|
2020-12-15 06:43:46 -06:00
|
|
|
end
|
|
|
|
|
|
2022-05-06 13:43:42 +02:00
|
|
|
context 'nvram' do
|
|
|
|
|
context 'when being added to existing' do
|
|
|
|
|
let(:vagrantfile_providerconfig) do
|
|
|
|
|
<<-EOF
|
2022-05-17 15:03:55 +01:00
|
|
|
libvirt.loader = "/path/to/loader/file"
|
2022-05-06 13:43:42 +02:00
|
|
|
libvirt.nvram = "/path/to/nvram/file"
|
|
|
|
|
EOF
|
|
|
|
|
end
|
|
|
|
|
let(:test_file) { 'existing.xml' }
|
|
|
|
|
let(:updated_test_file) { 'existing_added_nvram.xml' }
|
|
|
|
|
|
2022-06-03 10:42:28 +01:00
|
|
|
it 'should add the nvram element' do
|
|
|
|
|
expect(ui).to_not receive(:error)
|
|
|
|
|
expect(connection).to receive(:define_domain).with(updated_domain_xml).and_return(libvirt_domain)
|
|
|
|
|
expect(libvirt_domain).to receive(:xml_desc).and_return(domain_xml, updated_domain_xml)
|
2022-05-06 13:43:42 +02:00
|
|
|
expect(libvirt_domain).to receive(:autostart=)
|
|
|
|
|
expect(domain).to receive(:start)
|
|
|
|
|
|
|
|
|
|
expect(subject.call(env)).to be_nil
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
context 'when it was already in use' do
|
|
|
|
|
let(:vagrantfile_providerconfig) do
|
|
|
|
|
<<-EOF
|
2022-05-17 15:03:55 +01:00
|
|
|
libvirt.loader = "/path/to/loader/file"
|
2022-06-03 10:42:28 +01:00
|
|
|
libvirt.nvram = "/path/to/nvram/file1"
|
2022-05-06 13:43:42 +02:00
|
|
|
EOF
|
|
|
|
|
end
|
|
|
|
|
let(:test_file) { 'nvram_domain.xml' }
|
|
|
|
|
let(:updated_test_file) { 'nvram_domain_other_setting.xml' }
|
|
|
|
|
|
2022-06-03 10:42:28 +01:00
|
|
|
it 'should keep the XML element' do
|
|
|
|
|
expect(ui).to_not receive(:error)
|
|
|
|
|
expect(connection).to receive(:define_domain).with(updated_domain_xml).and_return(libvirt_domain)
|
|
|
|
|
expect(libvirt_domain).to receive(:xml_desc).and_return(domain_xml, updated_domain_xml)
|
2022-05-06 13:43:42 +02:00
|
|
|
expect(libvirt_domain).to receive(:autostart=)
|
|
|
|
|
expect(domain).to receive(:start)
|
|
|
|
|
|
|
|
|
|
expect(subject.call(env)).to be_nil
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
context 'when it is being disabled' do
|
|
|
|
|
let(:vagrantfile_providerconfig) { }
|
|
|
|
|
let(:updated_test_file) { 'nvram_domain_removed.xml' }
|
|
|
|
|
|
2022-06-03 10:42:28 +01:00
|
|
|
it 'should delete the XML element' do
|
|
|
|
|
expect(ui).to_not receive(:error)
|
|
|
|
|
expect(connection).to receive(:define_domain).with(updated_domain_xml).and_return(libvirt_domain)
|
|
|
|
|
expect(libvirt_domain).to receive(:xml_desc).and_return(domain_xml, updated_domain_xml)
|
2022-05-06 13:43:42 +02:00
|
|
|
expect(libvirt_domain).to receive(:autostart=)
|
|
|
|
|
expect(domain).to receive(:start)
|
|
|
|
|
|
|
|
|
|
expect(subject.call(env)).to be_nil
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
2020-12-15 06:43:46 -06:00
|
|
|
context 'tpm' do
|
|
|
|
|
context 'passthrough tpm added' do
|
2020-12-05 15:24:42 +00:00
|
|
|
let(:updated_test_file) { 'default_added_tpm_path.xml' }
|
|
|
|
|
let(:vagrantfile_providerconfig) do
|
|
|
|
|
<<-EOF
|
|
|
|
|
libvirt.tpm_path = '/dev/tpm0'
|
|
|
|
|
libvirt.tpm_type = 'passthrough'
|
|
|
|
|
libvirt.tpm_model = 'tpm-tis'
|
|
|
|
|
EOF
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
it 'should modify the domain tpm_path' do
|
2022-06-03 10:42:28 +01:00
|
|
|
expect(ui).to_not receive(:error)
|
2020-12-15 06:43:46 -06:00
|
|
|
expect(logger).to receive(:debug).with('tpm config changed')
|
2022-06-03 10:42:28 +01:00
|
|
|
expect(connection).to receive(:define_domain).with(updated_domain_xml).and_return(libvirt_domain)
|
|
|
|
|
expect(libvirt_domain).to receive(:xml_desc).and_return(domain_xml, updated_domain_xml)
|
2020-12-15 06:43:46 -06:00
|
|
|
expect(libvirt_domain).to receive(:autostart=)
|
|
|
|
|
expect(domain).to receive(:start)
|
|
|
|
|
|
|
|
|
|
expect(subject.call(env)).to be_nil
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
context 'emulated tpm added' do
|
|
|
|
|
let(:updated_test_file) { 'default_added_tpm_version.xml' }
|
|
|
|
|
let(:vagrantfile_providerconfig) do
|
|
|
|
|
<<-EOF
|
|
|
|
|
libvirt.tpm_type = 'emulator'
|
|
|
|
|
libvirt.tpm_model = 'tpm-crb'
|
|
|
|
|
libvirt.tpm_version = '2.0'
|
|
|
|
|
EOF
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
it 'should modify the domain tpm_path' do
|
2022-06-03 10:42:28 +01:00
|
|
|
expect(ui).to_not receive(:error)
|
2020-12-15 06:43:46 -06:00
|
|
|
expect(logger).to receive(:debug).with('tpm config changed')
|
2022-06-03 10:42:28 +01:00
|
|
|
expect(connection).to receive(:define_domain).with(updated_domain_xml).and_return(libvirt_domain)
|
|
|
|
|
expect(libvirt_domain).to receive(:xml_desc).and_return(domain_xml, updated_domain_xml)
|
2020-12-15 06:43:46 -06:00
|
|
|
expect(libvirt_domain).to receive(:autostart=)
|
|
|
|
|
expect(domain).to receive(:start)
|
|
|
|
|
|
|
|
|
|
expect(subject.call(env)).to be_nil
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
context 'same passthrough tpm config' do
|
|
|
|
|
let(:test_file) { 'default_added_tpm_path.xml' }
|
|
|
|
|
let(:updated_test_file) { 'default_added_tpm_path.xml' }
|
|
|
|
|
let(:vagrantfile_providerconfig) do
|
|
|
|
|
<<-EOF
|
|
|
|
|
libvirt.tpm_path = '/dev/tpm0'
|
|
|
|
|
libvirt.tpm_type = 'passthrough'
|
|
|
|
|
libvirt.tpm_model = 'tpm-tis'
|
|
|
|
|
EOF
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
it 'should execute without changing' do
|
2022-06-03 10:42:28 +01:00
|
|
|
expect(ui).to_not receive(:error)
|
2020-12-15 06:43:46 -06:00
|
|
|
expect(libvirt_domain).to receive(:autostart=)
|
|
|
|
|
expect(domain).to receive(:start)
|
|
|
|
|
|
|
|
|
|
expect(subject.call(env)).to be_nil
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
context 'same emulated tpm config' do
|
|
|
|
|
let(:test_file) { 'default_added_tpm_version.xml' }
|
|
|
|
|
let(:updated_test_file) { 'default_added_tpm_version.xml' }
|
|
|
|
|
let(:vagrantfile_providerconfig) do
|
|
|
|
|
<<-EOF
|
|
|
|
|
libvirt.tpm_type = 'emulator'
|
|
|
|
|
libvirt.tpm_model = 'tpm-crb'
|
|
|
|
|
libvirt.tpm_version = '2.0'
|
|
|
|
|
EOF
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
it 'should execute without changing' do
|
2022-06-03 10:42:28 +01:00
|
|
|
expect(ui).to_not receive(:error)
|
2020-12-15 06:43:46 -06:00
|
|
|
expect(libvirt_domain).to receive(:autostart=)
|
|
|
|
|
expect(domain).to receive(:start)
|
|
|
|
|
|
|
|
|
|
expect(subject.call(env)).to be_nil
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
context 'change from passthrough to emulated' do
|
|
|
|
|
let(:test_file) { 'default_added_tpm_path.xml' }
|
|
|
|
|
let(:updated_test_file) { 'default_added_tpm_version.xml' }
|
|
|
|
|
let(:vagrantfile_providerconfig) do
|
|
|
|
|
<<-EOF
|
|
|
|
|
libvirt.tpm_type = 'emulator'
|
|
|
|
|
libvirt.tpm_model = 'tpm-crb'
|
|
|
|
|
libvirt.tpm_version = '2.0'
|
|
|
|
|
EOF
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
it 'should modify the domain' do
|
2022-06-03 10:42:28 +01:00
|
|
|
expect(ui).to_not receive(:error)
|
2020-12-15 06:43:46 -06:00
|
|
|
expect(logger).to receive(:debug).with('tpm config changed')
|
2022-06-03 10:42:28 +01:00
|
|
|
expect(connection).to receive(:define_domain).with(updated_domain_xml).and_return(libvirt_domain)
|
|
|
|
|
expect(libvirt_domain).to receive(:xml_desc).and_return(domain_xml, updated_domain_xml)
|
2020-12-05 15:24:42 +00:00
|
|
|
expect(libvirt_domain).to receive(:autostart=)
|
|
|
|
|
expect(domain).to receive(:start)
|
|
|
|
|
|
|
|
|
|
expect(subject.call(env)).to be_nil
|
|
|
|
|
end
|
|
|
|
|
end
|
2020-11-15 23:28:43 +00:00
|
|
|
end
|
2020-12-16 20:19:24 +01:00
|
|
|
|
|
|
|
|
context 'clock_timers' do
|
|
|
|
|
let(:test_file) { 'clock_timer_rtc.xml' }
|
|
|
|
|
|
|
|
|
|
context 'timers unchanged' do
|
|
|
|
|
let(:vagrantfile_providerconfig) do
|
|
|
|
|
<<-EOF
|
|
|
|
|
libvirt.clock_timer(:name => "rtc")
|
|
|
|
|
EOF
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
it 'should not modify the domain' do
|
2022-06-03 10:42:28 +01:00
|
|
|
expect(ui).to_not receive(:error)
|
2020-12-16 20:19:24 +01:00
|
|
|
expect(logger).to_not receive(:debug).with('clock timers config changed')
|
2022-06-03 10:42:28 +01:00
|
|
|
expect(connection).to_not receive(:define_domain)
|
2020-12-16 20:19:24 +01:00
|
|
|
expect(libvirt_domain).to receive(:autostart=)
|
|
|
|
|
expect(domain).to receive(:start)
|
|
|
|
|
|
|
|
|
|
expect(subject.call(env)).to be_nil
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
context 'timers added' do
|
|
|
|
|
let(:vagrantfile_providerconfig) do
|
|
|
|
|
<<-EOF
|
|
|
|
|
libvirt.clock_timer(:name => "rtc")
|
|
|
|
|
libvirt.clock_timer(:name => "tsc")
|
|
|
|
|
EOF
|
|
|
|
|
end
|
|
|
|
|
|
2022-06-03 10:42:28 +01:00
|
|
|
let(:updated_test_file) { 'clock_timer_rtc_tsc.xml' }
|
|
|
|
|
|
2020-12-16 20:19:24 +01:00
|
|
|
it 'should modify the domain' do
|
2022-06-03 10:42:28 +01:00
|
|
|
expect(ui).to_not receive(:error)
|
2020-12-16 20:19:24 +01:00
|
|
|
expect(logger).to receive(:debug).with('clock timers config changed')
|
2022-06-03 10:42:28 +01:00
|
|
|
expect(connection).to receive(:define_domain).with(match(/<clock offset='utc'>\s*<timer name='rtc'\/>\s*<timer name='tsc'\/>\s*<\/clock>/)).and_return(libvirt_domain)
|
|
|
|
|
expect(libvirt_domain).to receive(:xml_desc).and_return(domain_xml, updated_domain_xml)
|
2020-12-16 20:19:24 +01:00
|
|
|
expect(libvirt_domain).to receive(:autostart=)
|
|
|
|
|
expect(domain).to receive(:start)
|
|
|
|
|
|
|
|
|
|
expect(subject.call(env)).to be_nil
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
context 'timers removed' do
|
2022-06-03 10:42:28 +01:00
|
|
|
let(:updated_test_file) { 'clock_timer_removed.xml' }
|
|
|
|
|
|
2020-12-16 20:19:24 +01:00
|
|
|
it 'should modify the domain' do
|
2022-06-03 10:42:28 +01:00
|
|
|
expect(ui).to_not receive(:error)
|
2020-12-16 20:19:24 +01:00
|
|
|
expect(logger).to receive(:debug).with('clock timers config changed')
|
2022-06-03 10:42:28 +01:00
|
|
|
expect(connection).to receive(:define_domain).with(match(/<clock offset='utc'>\s*<\/clock>/)).and_return(libvirt_domain)
|
|
|
|
|
expect(libvirt_domain).to receive(:xml_desc).and_return(domain_xml, updated_domain_xml)
|
2020-12-16 20:19:24 +01:00
|
|
|
expect(libvirt_domain).to receive(:autostart=)
|
|
|
|
|
expect(domain).to receive(:start)
|
|
|
|
|
|
|
|
|
|
expect(subject.call(env)).to be_nil
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
2020-11-15 23:28:43 +00:00
|
|
|
end
|
|
|
|
|
end
|