Use libvirt to query host physical devices (#1550)

Request the list of physical devices from libvirt when performing
config validation. This ensures remote instances using bridges will get
the correct list of devices as well as be alerted when the device needed
does not exist.

Fixes issue introduced with #1499
This commit is contained in:
Darragh Bailey
2022-08-17 15:14:25 +01:00
committed by GitHub
parent 06fd99fcef
commit 591e151b13
2 changed files with 10 additions and 9 deletions

View File

@@ -1067,8 +1067,9 @@ module VagrantPlugins
# only interested in public networks where portgroup is nil, as then source will be a host device # only interested in public networks where portgroup is nil, as then source will be a host device
if type == :public_network && opts[:portgroup] == nil if type == :public_network && opts[:portgroup] == nil
if !host_devices.include?(opts[:dev]) devices = host_devices(machine)
errors << "network configuration #{index} for machine #{machine.name} is a public_network referencing host device '#{opts[:dev]}' which does not exist, consider adding ':dev => ....' referencing one of #{host_devices.join(", ")}" if !devices.include?(opts[:dev])
errors << "network configuration #{index} for machine #{machine.name} is a public_network referencing host device '#{opts[:dev]}' which does not exist, consider adding ':dev => ....' referencing one of #{devices.join(", ")}"
end end
end end
end end
@@ -1210,11 +1211,9 @@ module VagrantPlugins
end end
end end
def host_devices def host_devices(machine)
@host_devices ||= begin @host_devices ||= begin
require 'socket' machine.provider.driver.connection.client.list_all_interfaces().map { |iface| iface.name }.uniq.select do |dev|
Socket.getifaddrs.map { |iface| iface.name }.uniq.select do |dev|
dev != "lo" && !@host_device_exclude_prefixes.any? { |exclude| dev.start_with?(exclude) } dev != "lo" && !@host_device_exclude_prefixes.any? { |exclude| dev.start_with?(exclude) }
end end
end end

View File

@@ -635,13 +635,15 @@ describe VagrantPlugins::ProviderLibvirt::Config do
end end
context 'with public_network defined' do context 'with public_network defined' do
let(:libvirt_client) { instance_double(::Libvirt::Connect) }
let(:host_devices) { [ let(:host_devices) { [
instance_double(Socket::Ifaddr), instance_double(Libvirt::Interface),
instance_double(Socket::Ifaddr), instance_double(Libvirt::Interface),
] } ] }
before do before do
machine.config.vm.network :public_network, dev: 'eth0', ip: "192.168.2.157" machine.config.vm.network :public_network, dev: 'eth0', ip: "192.168.2.157"
expect(Socket).to receive(:getifaddrs).and_return(host_devices) expect(machine).to receive_message_chain('provider.driver.connection.client').and_return(libvirt_client)
expect(libvirt_client).to receive(:list_all_interfaces).and_return(host_devices)
expect(host_devices[0]).to receive(:name).and_return('eth0') expect(host_devices[0]).to receive(:name).and_return('eth0')
expect(host_devices[1]).to receive(:name).and_return('virbr0') expect(host_devices[1]).to receive(:name).and_return('virbr0')
end end