2021-06-30 13:27:03 +01:00
|
|
|
# frozen_string_literal: true
|
|
|
|
|
|
2021-04-03 15:41:44 +02:00
|
|
|
require 'support/binding_proc'
|
2021-03-20 15:38:02 +00:00
|
|
|
|
2016-12-06 23:20:29 +01:00
|
|
|
require 'spec_helper'
|
2016-11-25 15:08:33 +00:00
|
|
|
|
2016-12-06 23:20:29 +01:00
|
|
|
require 'vagrant-libvirt/config'
|
2016-11-25 15:08:33 +00:00
|
|
|
|
|
|
|
|
describe VagrantPlugins::ProviderLibvirt::Config do
|
2016-12-06 23:20:29 +01:00
|
|
|
include_context 'unit'
|
2016-11-25 15:08:33 +00:00
|
|
|
|
2020-08-16 16:27:27 +01:00
|
|
|
let(:fake_env) { Hash.new }
|
|
|
|
|
|
2020-12-16 20:19:24 +01:00
|
|
|
describe '#clock_timer' do
|
|
|
|
|
it 'should handle all options' do
|
|
|
|
|
expect(
|
|
|
|
|
subject.clock_timer(
|
|
|
|
|
:name => 'rtc',
|
|
|
|
|
:track => 'wall',
|
|
|
|
|
:tickpolicy => 'delay',
|
|
|
|
|
:present => 'yes',
|
|
|
|
|
).length
|
|
|
|
|
).to be(1)
|
|
|
|
|
expect(
|
|
|
|
|
subject.clock_timer(
|
|
|
|
|
:name => 'tsc',
|
|
|
|
|
:tickpolicy => 'delay',
|
|
|
|
|
:frequency => '100',
|
|
|
|
|
:mode => 'auto',
|
|
|
|
|
:present => 'yes',
|
|
|
|
|
).length
|
|
|
|
|
).to be(2)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
it 'should correctly save the options' do
|
|
|
|
|
opts = {:name => 'rtc', :track => 'wall'}
|
|
|
|
|
expect(subject.clock_timer(opts).length).to be(1)
|
|
|
|
|
|
|
|
|
|
expect(subject.clock_timers[0]).to eq(opts)
|
|
|
|
|
|
|
|
|
|
opts[:name] = 'tsc'
|
|
|
|
|
expect(subject.clock_timers[0]).to_not eq(opts)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
it 'should error name option is missing' do
|
|
|
|
|
expect{ subject.clock_timer(:track => "wall") }.to raise_error("Clock timer name must be specified")
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
it 'should error if nil value for option supplied' do
|
|
|
|
|
expect{ subject.clock_timer(:name => "rtc", :track => nil) }.to raise_error("Value of timer option track is nil")
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
it 'should error if unrecognized option specified' do
|
|
|
|
|
expect{ subject.clock_timer(:name => "tsc", :badopt => "value") }.to raise_error("Unknown clock timer option: badopt")
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
2020-08-16 16:27:27 +01:00
|
|
|
describe '#finalize!' do
|
|
|
|
|
it 'is valid with defaults' do
|
|
|
|
|
subject.finalize!
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
context '@uri' do
|
|
|
|
|
before(:example) do
|
|
|
|
|
stub_const("ENV", fake_env)
|
2021-03-13 15:19:41 +00:00
|
|
|
fake_env['HOME'] = "/home/tests"
|
2020-08-16 16:27:27 +01:00
|
|
|
end
|
|
|
|
|
|
2021-03-13 15:19:41 +00:00
|
|
|
# table describing expected behaviour of inputs that affect the resulting uri as
|
|
|
|
|
# well as any subsequent settings that might be inferred if the uri was
|
|
|
|
|
# explicitly set.
|
|
|
|
|
[
|
|
|
|
|
# settings
|
|
|
|
|
[ # all default
|
|
|
|
|
{},
|
2021-03-17 15:36:09 +00:00
|
|
|
{:uri => "qemu:///system"},
|
2021-03-13 15:19:41 +00:00
|
|
|
],
|
|
|
|
|
|
2021-03-20 16:19:33 +00:00
|
|
|
# explicit uri settings
|
|
|
|
|
[ # transport and hostname
|
|
|
|
|
{:uri => "qemu+ssh://localhost/system"},
|
|
|
|
|
{:uri => "qemu+ssh://localhost/system", :connect_via_ssh => true, :host => "localhost", :username => nil},
|
|
|
|
|
],
|
|
|
|
|
[ # tcp transport with port
|
|
|
|
|
{:uri => "qemu+tcp://localhost:5000/system"},
|
|
|
|
|
{:uri => "qemu+tcp://localhost:5000/system", :connect_via_ssh => false, :host => "localhost", :username => nil},
|
|
|
|
|
],
|
|
|
|
|
[ # connect explicit to unix socket
|
|
|
|
|
{:uri => "qemu+unix:///system"},
|
|
|
|
|
{:uri => "qemu+unix:///system", :connect_via_ssh => false, :host => nil, :username => nil},
|
|
|
|
|
],
|
|
|
|
|
[ # via libssh2 should enable ssh as well
|
|
|
|
|
{:uri => "qemu+libssh2://user@remote/system?known_hosts=/home/user/.ssh/known_hosts"},
|
|
|
|
|
{
|
|
|
|
|
:uri => "qemu+libssh2://user@remote/system?known_hosts=/home/user/.ssh/known_hosts",
|
|
|
|
|
:connect_via_ssh => true, :host => "remote", :username => "user",
|
|
|
|
|
},
|
|
|
|
|
],
|
|
|
|
|
[ # xen
|
|
|
|
|
{:uri => "xen://remote/system?no_verify=1"},
|
|
|
|
|
{
|
|
|
|
|
:uri => "xen://remote/system?no_verify=1",
|
|
|
|
|
:connect_via_ssh => false, :host => "remote", :username => nil,
|
|
|
|
|
:id_ssh_key_file => nil,
|
|
|
|
|
},
|
|
|
|
|
{
|
2021-04-03 15:41:44 +02:00
|
|
|
:setup => ProcWithBinding.new {
|
2021-03-20 16:19:33 +00:00
|
|
|
expect(File).to_not receive(:file?)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
],
|
|
|
|
|
[ # xen
|
|
|
|
|
{:uri => "xen+ssh://remote/system?no_verify=1"},
|
|
|
|
|
{
|
|
|
|
|
:uri => "xen+ssh://remote/system?no_verify=1",
|
|
|
|
|
:connect_via_ssh => true, :host => "remote", :username => nil,
|
|
|
|
|
:id_ssh_key_file => "/home/tests/.ssh/id_rsa",
|
|
|
|
|
},
|
|
|
|
|
{
|
2021-04-03 15:41:44 +02:00
|
|
|
:setup => ProcWithBinding.new {
|
2021-03-20 16:19:33 +00:00
|
|
|
expect(File).to receive(:file?).with("/home/tests/.ssh/id_rsa").and_return(true)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
],
|
|
|
|
|
|
2021-03-13 15:19:41 +00:00
|
|
|
# with LIBVIRT_DEFAULT_URI
|
|
|
|
|
[ # all other set to default
|
|
|
|
|
{},
|
|
|
|
|
{:uri => "custom:///custom_path", :qemu_use_session => false},
|
2021-03-20 15:38:02 +00:00
|
|
|
{
|
|
|
|
|
:env => {'LIBVIRT_DEFAULT_URI' => "custom:///custom_path"},
|
|
|
|
|
}
|
2021-03-13 15:19:41 +00:00
|
|
|
],
|
|
|
|
|
[ # with session
|
|
|
|
|
{},
|
|
|
|
|
{:uri => "qemu:///session", :qemu_use_session => true},
|
2021-03-20 15:38:02 +00:00
|
|
|
{
|
|
|
|
|
:env => {'LIBVIRT_DEFAULT_URI' => "qemu:///session"},
|
|
|
|
|
}
|
2021-03-13 15:19:41 +00:00
|
|
|
],
|
2021-03-20 16:19:33 +00:00
|
|
|
[ # with session and using ssh infer connect by ssh and ignore host as not provided
|
2021-03-13 15:19:41 +00:00
|
|
|
{},
|
2021-03-20 16:19:33 +00:00
|
|
|
{:uri => "qemu+ssh:///session", :qemu_use_session => true, :connect_via_ssh => true, :host => nil},
|
2021-03-20 15:38:02 +00:00
|
|
|
{
|
|
|
|
|
:env => {'LIBVIRT_DEFAULT_URI' => "qemu+ssh:///session"},
|
|
|
|
|
}
|
2021-03-13 15:19:41 +00:00
|
|
|
],
|
|
|
|
|
[ # with session and using ssh to specific host with additional query options provided, infer host and ssh
|
|
|
|
|
{},
|
|
|
|
|
{:uri => "qemu+ssh://remote/session?keyfile=my_id_rsa", :qemu_use_session => true, :connect_via_ssh => true, :host => 'remote'},
|
2021-03-20 15:38:02 +00:00
|
|
|
{
|
|
|
|
|
:env => {'LIBVIRT_DEFAULT_URI' => "qemu+ssh://remote/session?keyfile=my_id_rsa"},
|
|
|
|
|
}
|
2021-03-13 15:19:41 +00:00
|
|
|
],
|
|
|
|
|
[ # when session not set
|
|
|
|
|
{},
|
|
|
|
|
{:uri => "qemu:///system", :qemu_use_session => false},
|
2021-03-20 15:38:02 +00:00
|
|
|
{
|
|
|
|
|
:env => {'LIBVIRT_DEFAULT_URI' => "qemu:///system"},
|
|
|
|
|
}
|
2021-03-13 15:19:41 +00:00
|
|
|
],
|
|
|
|
|
[ # when session appearing elsewhere
|
|
|
|
|
{},
|
|
|
|
|
{:uri => "qemu://remote/system?keyfile=my_session_id", :qemu_use_session => false},
|
2021-03-20 15:38:02 +00:00
|
|
|
{
|
|
|
|
|
:env => {'LIBVIRT_DEFAULT_URI' => "qemu://remote/system?keyfile=my_session_id"},
|
|
|
|
|
}
|
2021-03-13 15:19:41 +00:00
|
|
|
],
|
|
|
|
|
|
|
|
|
|
# ignore LIBVIRT_DEFAULT_URI due to explicit settings
|
|
|
|
|
[ # when uri explicitly set
|
|
|
|
|
{:uri => 'qemu:///system'},
|
2021-12-11 14:58:59 +00:00
|
|
|
{:uri => %r{qemu:///(system|session)}},
|
2021-03-20 15:38:02 +00:00
|
|
|
{
|
2021-12-11 14:58:59 +00:00
|
|
|
:env => {'LIBVIRT_DEFAULT_URI' => 'qemu:///custom'},
|
2021-03-20 15:38:02 +00:00
|
|
|
}
|
2021-03-13 15:19:41 +00:00
|
|
|
],
|
|
|
|
|
[ # when host explicitly set
|
|
|
|
|
{:host => 'remote'},
|
2021-12-11 14:58:59 +00:00
|
|
|
{:uri => %r{qemu://remote/(system|session)}},
|
2021-03-20 15:38:02 +00:00
|
|
|
{
|
2021-12-11 14:58:59 +00:00
|
|
|
:env => {'LIBVIRT_DEFAULT_URI' => 'qemu:///custom'},
|
2021-03-20 15:38:02 +00:00
|
|
|
}
|
2021-03-13 15:19:41 +00:00
|
|
|
],
|
|
|
|
|
[ # when connect_via_ssh explicitly set
|
|
|
|
|
{:connect_via_ssh => true},
|
2021-12-11 14:58:59 +00:00
|
|
|
{:uri => %r{qemu\+ssh://localhost/(system|session)\?no_verify=1}},
|
2021-03-20 15:38:02 +00:00
|
|
|
{
|
2021-12-11 14:58:59 +00:00
|
|
|
:env => {'LIBVIRT_DEFAULT_URI' => 'qemu:///custom'},
|
2021-03-20 15:38:02 +00:00
|
|
|
}
|
2021-03-13 15:19:41 +00:00
|
|
|
],
|
2021-03-17 15:36:09 +00:00
|
|
|
[ # when username explicitly set without ssh
|
2021-03-13 15:19:41 +00:00
|
|
|
{:username => 'my_user' },
|
2021-12-11 14:58:59 +00:00
|
|
|
{:uri => %r{qemu:///(system|session)}, :username => 'my_user'},
|
2021-03-20 15:38:02 +00:00
|
|
|
{
|
2021-12-11 14:58:59 +00:00
|
|
|
:env => {'LIBVIRT_DEFAULT_URI' => 'qemu:///custom'},
|
2021-03-20 15:38:02 +00:00
|
|
|
}
|
2021-03-13 15:19:41 +00:00
|
|
|
],
|
2022-08-24 18:16:14 +01:00
|
|
|
[ # when username explicitly set with @ symbol for domains
|
|
|
|
|
{:username => 'my_user@my_domain', :host => 'remote'},
|
|
|
|
|
{:uri => %r{qemu://remote/(system|session)}, :username => 'my_user@my_domain'},
|
|
|
|
|
{
|
|
|
|
|
:env => {'LIBVIRT_DEFAULT_URI' => 'qemu:///custom'},
|
|
|
|
|
}
|
|
|
|
|
],
|
2021-03-17 15:36:09 +00:00
|
|
|
[ # when username explicitly set with host but without ssh
|
2021-03-13 15:19:41 +00:00
|
|
|
{:username => 'my_user', :host => 'remote'},
|
2021-12-11 14:58:59 +00:00
|
|
|
{:uri => %r{qemu://remote/(system|session)}, :username => 'my_user'},
|
2021-03-20 15:38:02 +00:00
|
|
|
{
|
2021-12-11 14:58:59 +00:00
|
|
|
:env => {'LIBVIRT_DEFAULT_URI' => 'qemu:///custom'},
|
2021-03-20 15:38:02 +00:00
|
|
|
}
|
2021-03-13 15:19:41 +00:00
|
|
|
],
|
|
|
|
|
[ # when password explicitly set
|
|
|
|
|
{:password => 'some_password'},
|
2021-12-11 14:58:59 +00:00
|
|
|
{:uri => %r{qemu:///(system|session)}, :password => 'some_password'},
|
2021-03-20 15:38:02 +00:00
|
|
|
{
|
2021-12-11 14:58:59 +00:00
|
|
|
:env => {'LIBVIRT_DEFAULT_URI' => 'qemu:///custom'},
|
2021-03-20 15:38:02 +00:00
|
|
|
}
|
2021-03-13 15:19:41 +00:00
|
|
|
],
|
|
|
|
|
|
|
|
|
|
# driver settings
|
|
|
|
|
[ # set to kvm only
|
2021-03-17 15:36:09 +00:00
|
|
|
{:driver => 'kvm'},
|
2021-12-11 14:58:59 +00:00
|
|
|
{:uri => %r{qemu:///(system|session)}},
|
2021-03-13 15:19:41 +00:00
|
|
|
],
|
|
|
|
|
[ # set to qemu only
|
2021-03-17 15:36:09 +00:00
|
|
|
{:driver => 'qemu'},
|
2021-12-11 14:58:59 +00:00
|
|
|
{:uri => %r{qemu:///(system|session)}},
|
2021-03-13 15:19:41 +00:00
|
|
|
],
|
|
|
|
|
[ # set to qemu with session enabled
|
2021-03-17 15:36:09 +00:00
|
|
|
{:driver => 'qemu', :qemu_use_session => true},
|
|
|
|
|
{:uri => "qemu:///session"},
|
2021-03-13 15:19:41 +00:00
|
|
|
],
|
|
|
|
|
[ # set to openvz only
|
2021-03-17 15:36:09 +00:00
|
|
|
{:driver => 'openvz'},
|
|
|
|
|
{:uri => "openvz:///system"},
|
2021-03-13 15:19:41 +00:00
|
|
|
],
|
|
|
|
|
[ # set to esx
|
|
|
|
|
{:driver => 'esx'},
|
|
|
|
|
{:uri => "esx:///"},
|
|
|
|
|
],
|
|
|
|
|
[ # set to vbox only
|
2021-03-17 15:36:09 +00:00
|
|
|
{:driver => 'vbox'},
|
|
|
|
|
{:uri => "vbox:///session"},
|
2021-03-13 15:19:41 +00:00
|
|
|
],
|
|
|
|
|
|
|
|
|
|
# connect_via_ssh settings
|
|
|
|
|
[ # enabled
|
|
|
|
|
{:connect_via_ssh => true},
|
2021-12-11 14:58:59 +00:00
|
|
|
{:uri => %r{qemu\+ssh://localhost/(system|session)\?no_verify=1}},
|
2021-03-13 15:19:41 +00:00
|
|
|
],
|
|
|
|
|
[ # enabled with user
|
|
|
|
|
{:connect_via_ssh => true, :username => 'my_user'},
|
2021-12-11 14:58:59 +00:00
|
|
|
{:uri => %r{qemu\+ssh://my_user@localhost/(system|session)\?no_verify=1}},
|
2021-03-13 15:19:41 +00:00
|
|
|
],
|
|
|
|
|
[ # enabled with host
|
|
|
|
|
{:connect_via_ssh => true, :host => 'remote_server'},
|
2021-12-11 14:58:59 +00:00
|
|
|
{:uri => %r{qemu\+ssh://remote_server/(system|session)\?no_verify=1}},
|
2021-03-13 15:19:41 +00:00
|
|
|
],
|
|
|
|
|
|
|
|
|
|
# id_ssh_key_file behaviour
|
2021-03-20 15:38:02 +00:00
|
|
|
[ # set should take given value
|
|
|
|
|
{:connect_via_ssh => true, :id_ssh_key_file => '/path/to/keyfile'},
|
2021-12-11 14:58:59 +00:00
|
|
|
{:uri => %r{qemu\+ssh://localhost/(system|session)\?no_verify=1&keyfile=/path/to/keyfile}, :connect_via_ssh => true},
|
2021-03-20 15:38:02 +00:00
|
|
|
],
|
2021-03-17 15:36:09 +00:00
|
|
|
[ # set should infer use of ssh
|
2021-03-13 15:19:41 +00:00
|
|
|
{:id_ssh_key_file => '/path/to/keyfile'},
|
2021-12-11 14:58:59 +00:00
|
|
|
{:uri => %r{qemu\+ssh://localhost/(system|session)\?no_verify=1&keyfile=/path/to/keyfile}, :connect_via_ssh => true},
|
2021-03-20 15:38:02 +00:00
|
|
|
],
|
|
|
|
|
[ # connect_via_ssh should enable default but ignore due to not existing
|
|
|
|
|
{:connect_via_ssh => true},
|
2021-12-11 14:58:59 +00:00
|
|
|
{:uri => %r{qemu\+ssh://localhost/(system|session)\?no_verify=1}, :id_ssh_key_file => nil},
|
2021-03-20 15:38:02 +00:00
|
|
|
{
|
2021-04-03 15:41:44 +02:00
|
|
|
:setup => ProcWithBinding.new {
|
2021-03-20 15:38:02 +00:00
|
|
|
expect(File).to receive(:file?).with("/home/tests/.ssh/id_rsa").and_return(false)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
],
|
|
|
|
|
[ # connect_via_ssh should enable default and include due to existing
|
|
|
|
|
{:connect_via_ssh => true},
|
2021-12-11 14:58:59 +00:00
|
|
|
{:uri => %r{qemu\+ssh://localhost/(system|session)\?no_verify=1&keyfile=/home/tests/\.ssh/id_rsa}, :id_ssh_key_file => '/home/tests/.ssh/id_rsa'},
|
2021-03-20 15:38:02 +00:00
|
|
|
{
|
2021-04-03 15:41:44 +02:00
|
|
|
:setup => ProcWithBinding.new {
|
2021-03-20 15:38:02 +00:00
|
|
|
expect(File).to receive(:file?).with("/home/tests/.ssh/id_rsa").and_return(true)
|
|
|
|
|
}
|
|
|
|
|
}
|
2021-03-13 15:19:41 +00:00
|
|
|
],
|
|
|
|
|
|
|
|
|
|
# socket behaviour
|
|
|
|
|
[ # set
|
|
|
|
|
{:socket => '/var/run/libvirt/libvirt-sock'},
|
2021-12-11 14:58:59 +00:00
|
|
|
{:uri => %r{qemu:///(system|session)\?socket=/var/run/libvirt/libvirt-sock}},
|
2021-03-13 15:19:41 +00:00
|
|
|
],
|
2021-03-20 15:38:02 +00:00
|
|
|
].each do |inputs, outputs, options|
|
|
|
|
|
opts = {}
|
|
|
|
|
opts.merge!(options) if options
|
|
|
|
|
|
|
|
|
|
it "should handle inputs #{inputs} with env (#{opts[:env]})" do
|
2021-03-13 15:19:41 +00:00
|
|
|
# allow some of these to fail for now if marked as such
|
2021-03-20 15:38:02 +00:00
|
|
|
if !opts[:allow_failure].nil?
|
|
|
|
|
pending(opts[:allow_failure])
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
if !opts[:setup].nil?
|
2021-04-03 15:41:44 +02:00
|
|
|
opts[:setup].apply_binding(binding)
|
2021-03-13 15:19:41 +00:00
|
|
|
end
|
2019-11-15 17:11:36 -05:00
|
|
|
|
2021-03-13 15:19:41 +00:00
|
|
|
inputs.each do |k, v|
|
|
|
|
|
subject.instance_variable_set("@#{k}", v)
|
2019-11-15 17:11:36 -05:00
|
|
|
end
|
|
|
|
|
|
2021-03-20 15:38:02 +00:00
|
|
|
if !opts[:env].nil?
|
|
|
|
|
opts[:env].each do |k, v|
|
2021-03-13 15:19:41 +00:00
|
|
|
fake_env[k] = v
|
2020-08-16 16:27:27 +01:00
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
2021-03-13 15:19:41 +00:00
|
|
|
subject.finalize!
|
2020-08-16 16:27:27 +01:00
|
|
|
|
2021-03-13 15:19:41 +00:00
|
|
|
# ensure failed output indicates which settings are incorrect in the failed test
|
|
|
|
|
got = subject.instance_variables.each_with_object({}) do |name, hash|
|
|
|
|
|
if outputs.key?(name.to_s[1..-1].to_sym)
|
|
|
|
|
hash["#{name.to_s[1..-1]}".to_sym] =subject.instance_variable_get(name)
|
2020-08-16 16:27:27 +01:00
|
|
|
end
|
|
|
|
|
end
|
2021-12-11 14:58:59 +00:00
|
|
|
|
|
|
|
|
expect(got).to match(outputs.inject({}) { |h, (k, v)| h[k] = v.is_a?(Regexp) ? a_string_matching(v) : v; h })
|
2020-08-16 16:27:27 +01:00
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
2021-03-13 15:19:41 +00:00
|
|
|
context 'when invalid @driver is defined' do
|
|
|
|
|
it "should raise exception for unrecognized" do
|
|
|
|
|
subject.driver = "bad-driver"
|
2020-08-16 16:27:27 +01:00
|
|
|
|
2021-03-13 15:19:41 +00:00
|
|
|
expect { subject.finalize! }.to raise_error("Require specify driver bad-driver")
|
2020-08-16 16:27:27 +01:00
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
2021-03-13 15:19:41 +00:00
|
|
|
context 'when invalid @uri is defined' do
|
|
|
|
|
it "should raise exception for unrecognized" do
|
|
|
|
|
subject.uri = "://bad-uri"
|
2020-08-16 16:27:27 +01:00
|
|
|
|
2021-03-13 15:19:41 +00:00
|
|
|
expect { subject.finalize! }.to raise_error("@uri set to invalid uri '://bad-uri'")
|
2020-08-16 16:27:27 +01:00
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
2021-03-21 15:19:53 +00:00
|
|
|
|
2021-11-08 22:54:45 +00:00
|
|
|
context '@system_uri' do
|
|
|
|
|
[
|
|
|
|
|
# system uri
|
|
|
|
|
[ # transport and hostname
|
|
|
|
|
{:uri => "qemu+ssh://localhost/session"},
|
|
|
|
|
{:uri => "qemu+ssh://localhost/session", :system_uri => "qemu+ssh://localhost/system"},
|
|
|
|
|
],
|
|
|
|
|
[ # explicitly set
|
|
|
|
|
{:qemu_use_session => true, :system_uri => "custom://remote/system"},
|
|
|
|
|
{:uri => "qemu:///session", :system_uri => "custom://remote/system"},
|
|
|
|
|
],
|
|
|
|
|
].each do |inputs, outputs, options|
|
|
|
|
|
opts = {}
|
|
|
|
|
opts.merge!(options) if options
|
|
|
|
|
|
|
|
|
|
it "should handle inputs #{inputs} with env (#{opts[:env]})" do
|
|
|
|
|
# allow some of these to fail for now if marked as such
|
|
|
|
|
if !opts[:allow_failure].nil?
|
|
|
|
|
pending(opts[:allow_failure])
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
if !opts[:setup].nil?
|
|
|
|
|
opts[:setup].apply_binding(binding)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
inputs.each do |k, v|
|
|
|
|
|
subject.instance_variable_set("@#{k}", v)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
if !opts[:env].nil?
|
|
|
|
|
opts[:env].each do |k, v|
|
|
|
|
|
fake_env[k] = v
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
subject.finalize!
|
|
|
|
|
|
|
|
|
|
# ensure failed output indicates which settings are incorrect in the failed test
|
|
|
|
|
got = subject.instance_variables.each_with_object({}) do |name, hash|
|
|
|
|
|
if outputs.key?(name.to_s[1..-1].to_sym)
|
|
|
|
|
hash["#{name.to_s[1..-1]}".to_sym] =subject.instance_variable_get(name)
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
expect(got).to eq(outputs)
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
2021-03-21 15:19:53 +00:00
|
|
|
context '@proxy_command' do
|
|
|
|
|
before(:example) do
|
|
|
|
|
stub_const("ENV", fake_env)
|
|
|
|
|
fake_env['HOME'] = "/home/tests"
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
[
|
|
|
|
|
# no connect_via_ssh
|
|
|
|
|
[
|
|
|
|
|
{:host => "remote"},
|
|
|
|
|
nil,
|
|
|
|
|
],
|
|
|
|
|
|
|
|
|
|
# connect_via_ssh
|
|
|
|
|
[ # host
|
|
|
|
|
{:connect_via_ssh => true, :host => 'remote'},
|
|
|
|
|
"ssh 'remote' -W %h:%p",
|
|
|
|
|
],
|
|
|
|
|
[ # include user
|
|
|
|
|
{:connect_via_ssh => true, :host => 'remote', :username => 'myuser'},
|
|
|
|
|
"ssh 'remote' -l 'myuser' -W %h:%p",
|
|
|
|
|
],
|
2021-05-27 17:28:25 +01:00
|
|
|
[ # remote contains port
|
|
|
|
|
{:connect_via_ssh => true, :host => 'remote:2222'},
|
|
|
|
|
"ssh 'remote' -p 2222 -W %h:%p",
|
|
|
|
|
],
|
2021-03-21 15:19:53 +00:00
|
|
|
[ # include user and default ssh key exists
|
|
|
|
|
{:connect_via_ssh => true, :host => 'remote', :username => 'myuser'},
|
|
|
|
|
"ssh 'remote' -l 'myuser' -i '/home/tests/.ssh/id_rsa' -W %h:%p",
|
|
|
|
|
{
|
2021-04-03 15:41:44 +02:00
|
|
|
:setup => ProcWithBinding.new {
|
2021-03-21 15:19:53 +00:00
|
|
|
expect(File).to receive(:file?).with("/home/tests/.ssh/id_rsa").and_return(true)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
],
|
|
|
|
|
|
|
|
|
|
# disable id_ssh_key_file
|
|
|
|
|
[
|
|
|
|
|
{:connect_via_ssh => true, :host => 'remote', :id_ssh_key_file => nil},
|
|
|
|
|
"ssh 'remote' -W %h:%p",
|
|
|
|
|
],
|
|
|
|
|
[ # include user
|
|
|
|
|
{:connect_via_ssh => true, :host => 'remote', :id_ssh_key_file => nil},
|
|
|
|
|
"ssh 'remote' -W %h:%p",
|
|
|
|
|
],
|
|
|
|
|
|
|
|
|
|
# use @uri
|
|
|
|
|
[
|
|
|
|
|
{:uri => 'qemu+ssh://remote/system'},
|
|
|
|
|
"ssh 'remote' -W %h:%p",
|
|
|
|
|
],
|
|
|
|
|
[
|
|
|
|
|
{:uri => 'qemu+ssh://myuser@remote/system'},
|
|
|
|
|
"ssh 'remote' -l 'myuser' -W %h:%p",
|
|
|
|
|
],
|
|
|
|
|
[
|
|
|
|
|
{:uri => 'qemu+ssh://remote/system?keyfile=/some/path/to/keyfile'},
|
|
|
|
|
"ssh 'remote' -i '/some/path/to/keyfile' -W %h:%p",
|
|
|
|
|
],
|
|
|
|
|
|
|
|
|
|
# provide custom template
|
|
|
|
|
[
|
|
|
|
|
{:connect_via_ssh => true, :host => 'remote', :proxy_command => "ssh {host} nc %h %p" },
|
|
|
|
|
"ssh remote nc %h %p",
|
|
|
|
|
],
|
|
|
|
|
[
|
|
|
|
|
{:connect_via_ssh => true, :host => 'remote', :username => 'myuser', :proxy_command => "ssh {host} nc %h %p" },
|
|
|
|
|
"ssh remote nc %h %p",
|
|
|
|
|
],
|
|
|
|
|
[
|
|
|
|
|
{:connect_via_ssh => true, :host => 'remote', :username => 'myuser', :proxy_command => "ssh {host} -l {username} nc %h %p" },
|
|
|
|
|
"ssh remote -l myuser nc %h %p",
|
|
|
|
|
],
|
|
|
|
|
].each do |inputs, proxy_command, options|
|
|
|
|
|
opts = {}
|
|
|
|
|
opts.merge!(options) if options
|
|
|
|
|
|
|
|
|
|
it "should handle inputs #{inputs}" do
|
|
|
|
|
# allow some of these to fail for now if marked as such
|
|
|
|
|
if !opts[:allow_failure].nil?
|
|
|
|
|
pending(opts[:allow_failure])
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
if !opts[:setup].nil?
|
2021-04-03 15:41:44 +02:00
|
|
|
opts[:setup].apply_binding(binding)
|
2021-03-21 15:19:53 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
|
|
inputs.each do |k, v|
|
|
|
|
|
subject.instance_variable_set("@#{k}", v)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
subject.finalize!
|
|
|
|
|
|
|
|
|
|
expect(subject.proxy_command).to eq(proxy_command)
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
2021-09-27 16:49:15 +01:00
|
|
|
|
|
|
|
|
context '@usbctl_dev' do
|
|
|
|
|
it 'should be empty by default' do
|
|
|
|
|
subject.finalize!
|
|
|
|
|
|
|
|
|
|
expect(subject.usbctl_dev).to eq({})
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
context 'when usb devices added' do
|
|
|
|
|
it 'should inject a default controller' do
|
|
|
|
|
subject.usb :vendor => '0x1234', :product => '0xabcd'
|
|
|
|
|
|
|
|
|
|
subject.finalize!
|
|
|
|
|
|
|
|
|
|
expect(subject.usbctl_dev).to eq({:model => 'qemu-xhci'})
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
context 'when user specified a controller' do
|
|
|
|
|
it 'should retain the user setting' do
|
|
|
|
|
subject.usb :vendor => '0x1234', :product => '0xabcd'
|
|
|
|
|
subject.usb_controller :model => 'pii3-uchi'
|
|
|
|
|
|
|
|
|
|
subject.finalize!
|
|
|
|
|
expect(subject.usbctl_dev).to eq({:model => 'pii3-uchi'})
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
context 'when redirdevs entries added' do
|
|
|
|
|
it 'should inject a default controller' do
|
|
|
|
|
subject.redirdev :type => 'spicevmc'
|
|
|
|
|
|
|
|
|
|
subject.finalize!
|
|
|
|
|
|
|
|
|
|
expect(subject.usbctl_dev).to eq({:model => 'qemu-xhci'})
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
context 'when user specified a controller' do
|
|
|
|
|
it 'should retain the user setting' do
|
|
|
|
|
subject.redirdev :type => 'spicevmc'
|
|
|
|
|
subject.usb_controller :model => 'pii3-uchi'
|
|
|
|
|
|
|
|
|
|
subject.finalize!
|
|
|
|
|
expect(subject.usbctl_dev).to eq({:model => 'pii3-uchi'})
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
2021-11-26 18:12:21 +00:00
|
|
|
|
|
|
|
|
context '@channels' do
|
|
|
|
|
it 'should be empty by default' do
|
|
|
|
|
subject.finalize!
|
|
|
|
|
|
|
|
|
|
expect(subject.channels).to be_empty
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
context 'when qemu_use_agent is set' do
|
|
|
|
|
before do
|
|
|
|
|
subject.qemu_use_agent = true
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
it 'should inject a qemu agent channel' do
|
|
|
|
|
subject.finalize!
|
|
|
|
|
|
|
|
|
|
expect(subject.channels).to_not be_empty
|
|
|
|
|
expect(subject.channels).to match([a_hash_including({:target_name => 'org.qemu.guest_agent.0'})])
|
|
|
|
|
end
|
|
|
|
|
|
2022-10-02 21:43:37 +01:00
|
|
|
context 'another channel type already defined' do
|
|
|
|
|
it 'should inject a qemu agent channel' do
|
|
|
|
|
subject.channel :type => 'spicevmc', :target_name => 'com.redhat.spice.0', :target_type => 'virtio'
|
|
|
|
|
subject.finalize!
|
|
|
|
|
|
|
|
|
|
expect(subject.channels).to_not be_empty
|
|
|
|
|
expect(subject.channels).to match([
|
|
|
|
|
a_hash_including({:target_name => 'com.redhat.spice.0'}),
|
|
|
|
|
a_hash_including({:target_name => 'org.qemu.guest_agent.0'}),
|
|
|
|
|
])
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
2021-11-26 18:12:21 +00:00
|
|
|
context 'when agent channel already added' do
|
|
|
|
|
it 'should not modify the channels' do
|
|
|
|
|
subject.channel :type => 'unix', :target_name => 'org.qemu.guest_agent.0', :target_type => 'virtio'
|
|
|
|
|
|
|
|
|
|
subject.finalize!
|
|
|
|
|
|
|
|
|
|
expect(subject.channels.length).to eq(1)
|
|
|
|
|
end
|
|
|
|
|
|
2022-10-02 21:43:37 +01:00
|
|
|
context 'when agent channel explicitly disabled' do
|
2021-11-26 18:12:21 +00:00
|
|
|
it 'should not include an agent channel' do
|
|
|
|
|
subject.channel :type => 'unix', :target_name => 'org.qemu.guest_agent.0', :disabled => true
|
|
|
|
|
|
|
|
|
|
subject.finalize!
|
|
|
|
|
|
|
|
|
|
expect(subject.channels).to be_empty
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
2022-10-02 21:43:37 +01:00
|
|
|
|
|
|
|
|
context 'when graphics type set to spice' do
|
|
|
|
|
before do
|
|
|
|
|
subject.graphics_type = 'spice'
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
it 'should inject a spice agent channel' do
|
|
|
|
|
subject.finalize!
|
|
|
|
|
|
|
|
|
|
expect(subject.channels).to_not be_empty
|
|
|
|
|
expect(subject.channels).to match([a_hash_including({:target_name => 'com.redhat.spice.0'})])
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
context 'another channel type already defined' do
|
|
|
|
|
it 'should inject a spice agent channel' do
|
|
|
|
|
subject.channel :type => 'unix', :target_name => 'org.qemu.guest_agent.0', :target_type => 'virtio'
|
|
|
|
|
subject.finalize!
|
|
|
|
|
|
|
|
|
|
expect(subject.channels).to_not be_empty
|
|
|
|
|
expect(subject.channels).to match([
|
|
|
|
|
a_hash_including({:target_name => 'org.qemu.guest_agent.0'}),
|
|
|
|
|
a_hash_including({:target_name => 'com.redhat.spice.0'}),
|
|
|
|
|
])
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
context 'when spice channel already added' do
|
|
|
|
|
it 'should not modify the channels' do
|
|
|
|
|
subject.channel :type => 'spicevmc', :target_name => 'com.redhat.spice.0', :target_type => 'virtio'
|
|
|
|
|
|
|
|
|
|
subject.finalize!
|
|
|
|
|
|
|
|
|
|
expect(subject.channels.length).to eq(1)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
context 'when agent channel explicitly disabled' do
|
|
|
|
|
it 'should not include an agent channel' do
|
|
|
|
|
subject.channel :type => 'spicevmc', :target_name => 'com.redhat.spice.0', :disabled => true
|
|
|
|
|
|
|
|
|
|
subject.finalize!
|
|
|
|
|
|
|
|
|
|
expect(subject.channels).to be_empty
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
2021-11-26 18:12:21 +00:00
|
|
|
end
|
2022-09-30 17:06:59 +01:00
|
|
|
|
|
|
|
|
context '@inputs' do
|
|
|
|
|
it 'should contain ps/2 mouse by default' do
|
|
|
|
|
subject.finalize!
|
|
|
|
|
|
|
|
|
|
expect(subject.inputs).to eq([{:bus=>"ps2", :type=>"mouse"}])
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
it 'should contain only the specific entries' do
|
|
|
|
|
subject.input :type => "keyboard", :bus => "usb"
|
|
|
|
|
|
|
|
|
|
subject.finalize!
|
|
|
|
|
|
|
|
|
|
expect(subject.inputs).to eq([{:bus=>"usb", :type=>"keyboard"}])
|
|
|
|
|
end
|
|
|
|
|
end
|
2022-10-02 21:43:37 +01:00
|
|
|
|
|
|
|
|
context '@graphics_* and @video_*' do
|
|
|
|
|
it 'should set reasonable defaults' do
|
|
|
|
|
subject.finalize!
|
|
|
|
|
|
|
|
|
|
expect(subject.graphics_type).to eq('vnc')
|
|
|
|
|
expect(subject.graphics_port).to eq(-1)
|
|
|
|
|
expect(subject.graphics_ip).to eq('127.0.0.1')
|
|
|
|
|
expect(subject.graphics_autoport).to eq('yes')
|
|
|
|
|
expect(subject.channels).to be_empty
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
it 'should handle graphics_type set to spice' do
|
|
|
|
|
subject.graphics_type = 'spice'
|
|
|
|
|
subject.finalize!
|
|
|
|
|
|
|
|
|
|
expect(subject.graphics_port).to eq(nil)
|
|
|
|
|
expect(subject.graphics_ip).to eq(nil)
|
2022-10-11 18:12:32 +01:00
|
|
|
expect(subject.graphics_autoport).to eq(nil)
|
2022-10-02 21:43:37 +01:00
|
|
|
expect(subject.channels).to match([a_hash_including({:target_name => 'com.redhat.spice.0'})])
|
|
|
|
|
end
|
|
|
|
|
end
|
2020-08-16 16:27:27 +01:00
|
|
|
end
|
|
|
|
|
|
2016-11-25 15:08:33 +00:00
|
|
|
def assert_invalid
|
2019-11-15 17:11:36 -05:00
|
|
|
subject.finalize!
|
2022-08-16 18:44:11 +02:00
|
|
|
errors = subject.validate(machine).values.first
|
|
|
|
|
expect(errors).to_not be_empty
|
|
|
|
|
errors
|
2016-11-25 15:08:33 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def assert_valid
|
2019-11-15 17:11:36 -05:00
|
|
|
subject.finalize!
|
2022-08-16 18:44:11 +02:00
|
|
|
errors = subject.validate(machine).values.first
|
|
|
|
|
expect(errors).to be_empty
|
2016-11-25 15:08:33 +00:00
|
|
|
end
|
|
|
|
|
|
2016-12-06 23:20:29 +01:00
|
|
|
describe '#validate' do
|
2022-08-16 18:44:11 +02:00
|
|
|
before do
|
|
|
|
|
allow(machine).to receive(:provider_config).and_return(subject)
|
|
|
|
|
allow(machine).to receive(:ui).and_return(ui)
|
|
|
|
|
end
|
|
|
|
|
|
2016-12-06 23:20:29 +01:00
|
|
|
it 'is valid with defaults' do
|
2016-11-25 15:08:33 +00:00
|
|
|
assert_valid
|
|
|
|
|
end
|
|
|
|
|
|
2017-05-16 14:14:30 +01:00
|
|
|
context 'with disks defined' do
|
|
|
|
|
it 'is valid if relative path used for disk' do
|
|
|
|
|
subject.storage :file, path: '../path/to/file.qcow2'
|
|
|
|
|
assert_valid
|
|
|
|
|
end
|
2016-11-25 15:08:33 +00:00
|
|
|
|
2017-05-16 14:14:30 +01:00
|
|
|
it 'should be invalid if absolute path used for disk' do
|
|
|
|
|
subject.storage :file, path: '/absolute/path/to/file.qcow2'
|
|
|
|
|
assert_invalid
|
|
|
|
|
end
|
2016-11-25 15:08:33 +00:00
|
|
|
end
|
|
|
|
|
|
2016-12-06 23:20:29 +01:00
|
|
|
context 'with mac defined' do
|
|
|
|
|
let (:vm) { double('vm') }
|
2021-12-03 11:28:21 +00:00
|
|
|
before do
|
|
|
|
|
machine.config.instance_variable_get("@keys")[:vm] = vm
|
|
|
|
|
end
|
2016-11-25 15:08:33 +00:00
|
|
|
|
2016-12-06 23:20:29 +01:00
|
|
|
it 'is valid with valid mac' do
|
2017-05-16 14:14:30 +01:00
|
|
|
expect(vm).to receive(:networks).and_return([[:public, { mac: 'aa:bb:cc:dd:ee:ff' }]])
|
2016-11-25 15:08:33 +00:00
|
|
|
assert_valid
|
|
|
|
|
end
|
|
|
|
|
|
2017-05-16 14:20:44 +01:00
|
|
|
it 'is valid with MAC containing no delimiters' do
|
|
|
|
|
network = [:public, { mac: 'aabbccddeeff' }]
|
|
|
|
|
expect(vm).to receive(:networks).and_return([network])
|
|
|
|
|
assert_valid
|
|
|
|
|
expect(network[1][:mac]).to eql('aa:bb:cc:dd:ee:ff')
|
|
|
|
|
end
|
|
|
|
|
|
2016-12-06 23:20:29 +01:00
|
|
|
it 'should be invalid if MAC not formatted correctly' do
|
2017-05-16 14:20:44 +01:00
|
|
|
expect(vm).to receive(:networks).and_return([[:public, { mac: 'aa/bb/cc/dd/ee/ff' }]])
|
2016-11-25 15:08:33 +00:00
|
|
|
assert_invalid
|
|
|
|
|
end
|
|
|
|
|
end
|
2021-12-08 19:48:31 +00:00
|
|
|
|
2022-06-03 14:54:37 +01:00
|
|
|
context 'with public_network defined' do
|
2022-08-17 15:14:25 +01:00
|
|
|
let(:libvirt_client) { instance_double(::Libvirt::Connect) }
|
2022-06-03 14:54:37 +01:00
|
|
|
let(:host_devices) { [
|
2022-10-05 14:29:44 +01:00
|
|
|
'lo',
|
|
|
|
|
'eth0',
|
|
|
|
|
'virbr0',
|
2022-08-22 18:05:04 +01:00
|
|
|
] }
|
|
|
|
|
let(:driver) { instance_double(::VagrantPlugins::ProviderLibvirt::Driver) }
|
2022-06-03 14:54:37 +01:00
|
|
|
before do
|
|
|
|
|
machine.config.vm.network :public_network, dev: 'eth0', ip: "192.168.2.157"
|
2022-08-22 18:05:04 +01:00
|
|
|
allow(machine.provider).to receive(:driver).and_return(driver)
|
2022-10-05 14:29:44 +01:00
|
|
|
expect(driver).to receive(:host_devices).and_return(host_devices).at_least(:once).times
|
2022-06-03 14:54:37 +01:00
|
|
|
end
|
|
|
|
|
|
|
|
|
|
it 'should validate use of existing device' do
|
|
|
|
|
assert_valid
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
context 'when default device not on host' do
|
|
|
|
|
before do
|
|
|
|
|
machine.config.vm.network :public_network, dev: 'eno1', ip: "192.168.2.157"
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
it 'should be invalid' do
|
|
|
|
|
assert_invalid
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
context 'when using excluded host device' do
|
|
|
|
|
before do
|
|
|
|
|
machine.config.vm.network :public_network, dev: 'virbr0', ip: "192.168.2.157"
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
it 'should be invalid' do
|
|
|
|
|
assert_invalid
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
context 'when user overrides to allow device' do
|
|
|
|
|
before do
|
|
|
|
|
subject.host_device_exclude_prefixes = []
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
it 'should validate' do
|
|
|
|
|
assert_valid
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
2022-05-17 15:03:55 +01:00
|
|
|
context 'with nvram defined' do
|
|
|
|
|
before do
|
|
|
|
|
subject.nvram = '/path/to/some/nvram'
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
it 'should be invalid as loader not set' do
|
|
|
|
|
assert_invalid
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
context 'with loader defined' do
|
|
|
|
|
it 'should be valid' do
|
|
|
|
|
subject.loader = '/path/to/some/loader'
|
|
|
|
|
|
|
|
|
|
assert_valid
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
2021-12-08 19:48:31 +00:00
|
|
|
context 'with cpu_mode and cpu_model defined' do
|
|
|
|
|
it 'should discard model if mode is passthrough' do
|
|
|
|
|
subject.cpu_mode = 'host-passthrough'
|
|
|
|
|
subject.cpu_model = 'qemu64'
|
|
|
|
|
assert_valid
|
|
|
|
|
expect(subject.cpu_model).to be_empty
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
it 'should allow custom mode with model' do
|
|
|
|
|
subject.cpu_mode = 'custom'
|
|
|
|
|
subject.cpu_model = 'qemu64'
|
|
|
|
|
assert_valid
|
|
|
|
|
end
|
|
|
|
|
end
|
2022-08-16 18:44:11 +02:00
|
|
|
|
|
|
|
|
context 'with sysinfo defined' do
|
|
|
|
|
context 'when invalid block name provided' do
|
|
|
|
|
it 'should be invalid' do
|
|
|
|
|
subject.sysinfo = {'bad bios': {'vendor': 'some vendor'}}
|
|
|
|
|
|
|
|
|
|
errors = assert_invalid
|
|
|
|
|
expect(errors).to include(match(/invalid sysinfo element 'bad bios';/))
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
context 'when invalid element name provided' do
|
|
|
|
|
it 'should be invalid' do
|
|
|
|
|
subject.sysinfo = {'bios': {'bad vendor': 'some vendor'}}
|
|
|
|
|
|
|
|
|
|
errors = assert_invalid
|
|
|
|
|
expect(errors).to include(match(/'sysinfo.bios' does not support entry name 'bad vendor'/))
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
context 'when empty element value provided' do
|
|
|
|
|
it 'should succeed with a warning' do
|
|
|
|
|
expect(ui).to receive(:warn).with(/Libvirt Provider: sysinfo.bios.vendor is nil or empty/)
|
|
|
|
|
subject.sysinfo = {'bios': {'vendor': ''}}
|
|
|
|
|
|
|
|
|
|
assert_valid
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
context 'when handling "oem strings"' do
|
|
|
|
|
it 'should succeed' do
|
|
|
|
|
subject.sysinfo = {'oem strings': ['string 1']}
|
|
|
|
|
|
|
|
|
|
assert_valid
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
context 'when empty entries' do
|
|
|
|
|
it 'should succeed with a warning' do
|
|
|
|
|
expect(ui).to receive(:warn).with(/Libvirt Provider: 'sysinfo.oem strings' contains an empty/)
|
|
|
|
|
subject.sysinfo = {'oem strings': ['']}
|
|
|
|
|
|
|
|
|
|
assert_valid
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
context 'when non string passed' do
|
|
|
|
|
it 'should be invalid' do
|
|
|
|
|
subject.sysinfo = {'oem strings': [true]}
|
|
|
|
|
|
|
|
|
|
assert_invalid
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
2022-10-08 13:59:06 +03:00
|
|
|
|
|
|
|
|
context 'with cdroms and floppies' do
|
|
|
|
|
it 'should be invalid if too many cdroms' do
|
|
|
|
|
subject.storage :file, :device => :cdrom
|
|
|
|
|
subject.storage :file, :device => :cdrom
|
|
|
|
|
subject.storage :file, :device => :cdrom
|
|
|
|
|
subject.storage :file, :device => :cdrom
|
|
|
|
|
subject.storage :file, :device => :cdrom
|
|
|
|
|
|
|
|
|
|
expect{ subject.finalize! }.to raise_error('Only four cdroms may be attached at a time')
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
it 'sould be invalid if too many floppies' do
|
|
|
|
|
subject.storage :file, :device => :floppy
|
|
|
|
|
subject.storage :file, :device => :floppy
|
|
|
|
|
subject.storage :file, :device => :floppy
|
|
|
|
|
|
|
|
|
|
expect{ subject.finalize! }.to raise_error('Only two floppies may be attached at a time')
|
|
|
|
|
end
|
|
|
|
|
end
|
2016-11-25 15:08:33 +00:00
|
|
|
end
|
|
|
|
|
|
2016-12-06 23:20:29 +01:00
|
|
|
describe '#merge' do
|
2016-11-25 15:08:33 +00:00
|
|
|
let(:one) { described_class.new }
|
|
|
|
|
let(:two) { described_class.new }
|
|
|
|
|
|
|
|
|
|
subject { one.merge(two) }
|
|
|
|
|
|
2016-12-06 23:20:29 +01:00
|
|
|
context 'storage' do
|
|
|
|
|
context 'with disks' do
|
|
|
|
|
context 'assigned specific devices' do
|
|
|
|
|
it 'should merge disks with specific devices' do
|
|
|
|
|
one.storage(:file, device: 'vdb')
|
|
|
|
|
two.storage(:file, device: 'vdc')
|
2016-11-25 15:08:33 +00:00
|
|
|
subject.finalize!
|
2016-12-06 23:20:29 +01:00
|
|
|
expect(subject.disks).to include(include(device: 'vdb'),
|
|
|
|
|
include(device: 'vdc'))
|
2016-11-25 15:08:33 +00:00
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
2016-12-06 23:20:29 +01:00
|
|
|
context 'without devices given' do
|
2021-11-22 10:02:18 +00:00
|
|
|
it 'should merge disks without assigning devices automatically' do
|
2016-11-25 15:08:33 +00:00
|
|
|
one.storage(:file)
|
|
|
|
|
two.storage(:file)
|
|
|
|
|
subject.finalize!
|
2021-11-22 10:02:18 +00:00
|
|
|
expect(subject.disks).to_not include(include(device: 'vdb'),
|
2016-12-06 23:20:29 +01:00
|
|
|
include(device: 'vdc'))
|
2016-11-25 15:08:33 +00:00
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
2016-12-06 23:20:29 +01:00
|
|
|
context 'with cdroms only' do
|
|
|
|
|
context 'assigned specific devs' do
|
|
|
|
|
it 'should merge disks with specific devices' do
|
|
|
|
|
one.storage(:file, device: :cdrom, dev: 'hda')
|
|
|
|
|
two.storage(:file, device: :cdrom, dev: 'hdb')
|
2016-11-25 15:08:33 +00:00
|
|
|
subject.finalize!
|
2016-12-06 23:20:29 +01:00
|
|
|
expect(subject.cdroms).to include(include(dev: 'hda'),
|
|
|
|
|
include(dev: 'hdb'))
|
2016-11-25 15:08:33 +00:00
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
2016-12-06 23:20:29 +01:00
|
|
|
context 'without devs given' do
|
|
|
|
|
it 'should merge cdroms with different devs assigned automatically' do
|
|
|
|
|
one.storage(:file, device: :cdrom)
|
|
|
|
|
two.storage(:file, device: :cdrom)
|
2016-11-25 15:08:33 +00:00
|
|
|
subject.finalize!
|
2016-12-06 23:20:29 +01:00
|
|
|
expect(subject.cdroms).to include(include(dev: 'hda'),
|
|
|
|
|
include(dev: 'hdb'))
|
2016-11-25 15:08:33 +00:00
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
2022-10-08 13:59:06 +03:00
|
|
|
|
|
|
|
|
context 'with floppies only' do
|
|
|
|
|
context 'assigned specific devs' do
|
|
|
|
|
it 'should merge floppies with specific devices' do
|
|
|
|
|
one.storage(:file, device: :floppy, dev: 'fda')
|
|
|
|
|
two.storage(:file, device: :floppy, dev: 'fdb')
|
|
|
|
|
subject.finalize!
|
|
|
|
|
expect(subject.floppies).to include(include(dev: 'fda'),
|
|
|
|
|
include(dev: 'fdb'))
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
context 'without devs given' do
|
|
|
|
|
it 'should merge floppies with different devs assigned automatically' do
|
|
|
|
|
one.storage(:file, device: :floppy)
|
|
|
|
|
two.storage(:file, device: :floppy)
|
|
|
|
|
subject.finalize!
|
|
|
|
|
expect(subject.floppies).to include(include(dev: 'fda'),
|
|
|
|
|
include(dev: 'fdb'))
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
2016-11-25 15:08:33 +00:00
|
|
|
end
|
2020-12-16 20:19:24 +01:00
|
|
|
|
|
|
|
|
context 'clock_timers' do
|
|
|
|
|
it 'should merge clock_timers' do
|
|
|
|
|
one.clock_timer(:name => 'rtc', :tickpolicy => 'catchup')
|
|
|
|
|
two.clock_timer(:name => 'hpet', :present => 'no')
|
|
|
|
|
|
|
|
|
|
expect(subject.clock_timers).to include(include(name: 'rtc'),
|
|
|
|
|
include(name: 'hpet'))
|
|
|
|
|
end
|
|
|
|
|
end
|
2022-08-16 18:44:11 +02:00
|
|
|
|
|
|
|
|
context 'sysinfo' do
|
|
|
|
|
it 'should merge' do
|
|
|
|
|
one.sysinfo = {
|
|
|
|
|
'bios' => {'vendor': 'Some Vendor'},
|
|
|
|
|
'system' => {'manufacturer': 'some manufacturer'},
|
|
|
|
|
'oem strings' => ['string 1'],
|
|
|
|
|
}
|
|
|
|
|
two.sysinfo = {
|
|
|
|
|
'bios' => {'vendor': 'Another Vendor'},
|
|
|
|
|
'system' => {'serial': 'AABBCCDDEE'},
|
|
|
|
|
'oem strings' => ['string 2'],
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
subject.finalize!
|
|
|
|
|
expect(subject.sysinfo).to eq(
|
|
|
|
|
'bios' => {'vendor': 'Another Vendor'},
|
|
|
|
|
'system' => {'manufacturer': 'some manufacturer', 'serial': 'AABBCCDDEE'},
|
|
|
|
|
'oem strings' => ['string 1', 'string 2'],
|
|
|
|
|
)
|
|
|
|
|
end
|
|
|
|
|
end
|
2022-08-25 18:46:33 +01:00
|
|
|
|
|
|
|
|
context 'boot_order' do
|
|
|
|
|
it 'should merge' do
|
|
|
|
|
one.boot 'network'
|
|
|
|
|
|
|
|
|
|
subject.finalize!
|
|
|
|
|
expect(subject.boot_order).to eq(['network'])
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
it 'should have last definition win' do
|
|
|
|
|
one.boot 'network'
|
|
|
|
|
two.boot 'hd'
|
|
|
|
|
two.boot 'cdrom'
|
|
|
|
|
|
|
|
|
|
subject.finalize!
|
|
|
|
|
expect(subject.boot_order).to eq(['hd', 'cdrom'])
|
|
|
|
|
end
|
|
|
|
|
end
|
2022-09-30 17:06:59 +01:00
|
|
|
|
|
|
|
|
context 'inputs' do
|
|
|
|
|
it 'should merge' do
|
|
|
|
|
one.input :type => "tablet", :bus => "usb"
|
|
|
|
|
two.input :type => "keyboard", :bus => "usb"
|
|
|
|
|
|
|
|
|
|
subject.finalize!
|
|
|
|
|
expect(subject.inputs).to eq([{:type => "tablet", :bus => "usb"}, {:type => "keyboard", :bus => "usb"}])
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
it 'should respect explicit blanking' do
|
|
|
|
|
one.inputs = []
|
|
|
|
|
|
|
|
|
|
subject.finalize!
|
|
|
|
|
expect(subject.inputs).to eq([])
|
|
|
|
|
end
|
|
|
|
|
end
|
2016-11-25 15:08:33 +00:00
|
|
|
end
|
|
|
|
|
end
|