Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion lib/fog/libvirt/models/compute/server.rb
Original file line number Diff line number Diff line change
Expand Up @@ -478,7 +478,11 @@ def read_ceph_args(path = "/etc/foreman/ceph.conf")
# if the server has multiple network interface
def addresses(service_arg=service, options={})
ip_address = nil
if (nic = self.nics&.first)
# Pick the first nic that actually has a network. Bridge/direct
# interfaces carry a nil network name, which can't be looked up and
# never has a libvirt-managed lease, so skip them in favour of a nic
# that can resolve to an address.
if (nic = self.nics&.find { |n| n.network })
net = service.networks.all(:name => nic.network).first
# Assume the lease expiring last is the current IP address
ip_address = net&.dhcp_leases(nic.mac)&.max_by { |lse| lse["expirytime"] }&.dig("ipaddr")
Expand Down
4 changes: 3 additions & 1 deletion lib/fog/libvirt/requests/compute/list_networks.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ def list_networks(filter = { })
data << network_to_attributes(client.lookup_network_by_name(network_name))
end
else
data = [network_to_attributes(get_network_by_filter(filter))]
data = [network_to_attributes(get_network_by_filter(filter))].compact
end
data
end
Expand All @@ -21,6 +21,8 @@ def get_network_by_filter(filter)
when :uuid
client.lookup_network_by_uuid(filter[:uuid])
when :name
return nil if filter[:name].nil?

client.lookup_network_by_name(filter[:name])
end
end
Expand Down
40 changes: 40 additions & 0 deletions minitests/server/nil_network_address_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
require 'test_helper'

# Bridge and direct interfaces have a nil network name. #addresses used to
# pass that nil straight into a network lookup, which raised. It should instead
# skip network-less nics and resolve an address from a nic that has one.
class NilNetworkAddressTest < Minitest::Test
def setup
@compute = Fog::Compute[:libvirt]
@server = @compute.servers.new(:name => "test")
end

def test_returns_nil_without_raising_when_only_nic_has_no_network
bridge_nic = stub(:network => nil, :mac => "52:54:00:aa:bb:cc")
@server.stubs(:nics).returns([bridge_nic])
# No network is ever looked up, so the connection is never touched.
@server.service.expects(:networks).never

result = @server.send(:addresses)

assert_nil result[:public].first
assert_nil result[:private].first
end

def test_skips_network_less_nic_and_resolves_address_from_next
bridge_nic = stub(:network => nil, :mac => "52:54:00:aa:bb:cc")
nat_nic = stub(:network => "default", :mac => "52:54:00:01:02:03")
@server.stubs(:nics).returns([bridge_nic, nat_nic])

net = stub(:name => "default")
net.stubs(:dhcp_leases).with("52:54:00:01:02:03").returns([{ "expirytime" => 1000, "ipaddr" => "192.168.122.10" }])
networks = stub
networks.stubs(:all).with(:name => "default").returns([net])
@server.service.stubs(:networks).returns(networks)

result = @server.send(:addresses)

assert_equal "192.168.122.10", result[:public].first
assert_equal "192.168.122.10", result[:private].first
end
end
Loading