refactor libraries/network.rb

- splitted the address_for method into address_for and get_address
- added the option to search for an address from another node
- added an optional filter for virtual ips in get_address
- refactored network specs

Change-Id: I4678969045b317071296b1d7dc8e7d13505f4db7
This commit is contained in:
Jan Klare 2015-04-24 17:54:11 +02:00
parent c4d2276953
commit 6e0b3f2ce3
2 changed files with 90 additions and 40 deletions

View File

@ -2,7 +2,7 @@
#
# Cookbook Name:: openstack-common
# library:: address
# library:: network
#
# Copyright 2012-2013, AT&T Services, Inc.
#
@ -24,14 +24,35 @@ module ::Openstack # rubocop:disable Documentation
#
# @param [String] interface The interface to query.
# @param [String] family The protocol family to use.
# @param [Mash] nodeish The node object to query.
# @param [Boolean] drop_vips Option to exclude virtual ips with netmask 32 (ipv4) or 128 (ipv6).
# @return [String] The address or log error when address is nil
def address_for(interface, family = node['openstack']['endpoints']['family'])
interface_node = node['network']['interfaces'][interface]['addresses']
fail "Interface #{interface} has no addresses assigned" if interface_node.to_a.empty?
def address_for(interface, family = node['openstack']['endpoints']['family'], nodeish = node, drop_vips = true)
Chef::Log.debug("address_for(#{interface}, #{family}, #{nodeish})")
if interface == 'all'
if family == 'inet6'
return '::'
else
return '0.0.0.0'
end
end
addresses = nodeish['network']['interfaces'][interface]['addresses']
fail "Interface #{interface} has no addresses assigned" if addresses.to_a.empty?
get_address addresses, family, drop_vips
end
address = interface_node.find { |addr, data| data['family'] == family }
fail "Interface #{interface} has no address for family #{family}" if address.nil?
private
address[0]
def get_address(addresses, family, drop_vips)
case family
when 'inet'
vip_prefixlen = '32'
when 'inet6'
vip_prefixlen = '128'
end
addresses.each do |addr, data|
return addr if data['family'] == family && (data['prefixlen'] != vip_prefixlen || !drop_vips)
end
fail "No address for family #{family} found"
end
end

View File

@ -7,28 +7,17 @@ describe 'openstack-common::default' do
let(:runner) { ChefSpec::SoloRunner.new(CHEFSPEC_OPTS) }
let(:node) { runner.node }
let(:chef_run) do
node.set['network'] = {
'interfaces' => {
'lo' => {
'addresses' => {
'127.0.0.1' => {
'family' => 'inet',
'prefixlen' => '8',
'netmask' => '255.0.0.0',
'scope' => 'Node'
},
'::1' => {
'family' => 'inet6',
'prefixlen' => '128',
'scope' => 'Node'
}
}
}
}
}
node.automatic['network']['interfaces'] = {
'lo' => { 'addresses' => { '127.0.0.1' => { 'family' => 'inet', 'prefixlen' => '8', 'netmask' => '255.0.0.0', 'scope' => 'Node' },
'::1' => { 'family' => 'inet6', 'prefixlen' => '128', 'scope' => 'Node' },
'2001:db8::1' => { 'family' => 'inet6', 'prefixlen' => '64', 'scope' => 'Node' } } },
'eth0' => { 'addresses' => { '10.0.0.2' => { 'family' => 'inet', 'prefixlen' => '32', 'netmask' => '255.255.255.255', 'scope' => 'Node' },
'10.0.0.3' => { 'family' => 'inet', 'prefixlen' => '24', 'netmask' => '255.255.255.0', 'scope' => 'Node' }
} } }
runner.converge(described_recipe)
end
let(:subject) { Object.new.extend(Openstack) }
include_context 'library-stubs'
@ -40,57 +29,80 @@ describe 'openstack-common::default' do
).to eq('127.0.0.1')
end
it 'returns ipv6 address' do
it 'returns first ipv4 address but no virtual ips with prefixlen 32' do
expect(
subject.address_for('lo', 'inet6')
).to eq('::1')
subject.address_for('eth0', 'inet', node, true)
).to eq('10.0.0.3')
end
it 'returns first ipv4 address even if virtual and with prefixlen 32' do
expect(
subject.address_for('eth0', 'inet', node, false)
).to eq('10.0.0.2')
end
it 'returns 0.0.0.0 for interface "all"' do
expect(
subject.address_for('all')
).to eq('0.0.0.0')
end
end
describe '#address_for ipv6' do
it 'returns ipv6 address' do
node.set['openstack']['endpoints']['family'] = 'inet6'
expect(
subject.address_for('lo')
).to eq('::1')
).to eq('2001:db8::1')
end
it 'returns ipv6 address' do
expect(
subject.address_for('lo', 'inet6')
).to eq('2001:db8::1')
end
it 'returns first ipv6 address and also virtual ips with prefixlen 128' do
expect(
subject.address_for('lo', 'inet6', node, false)
).to eq('::1')
end
it 'returns :: for interface "all"' do
expect(
subject.address_for('all', 'inet6')
).to eq('::')
end
end
describe '#address_for failures' do
it 'fails when addresses for interface is nil' do
node.set['network'] = {
node.automatic['network'] = {
'interfaces' => {
'lo' => {
'addresses' => nil
}
}
}
allow(subject).to receive(:address_for).with('lo')
.and_raise('Interface lo has no addresses assigned')
expect { subject.address_for('lo') }
.to raise_error(RuntimeError, 'Interface lo has no addresses assigned')
end
it 'fails when no addresses are avaiable for interface' do
node.set['network'] = {
node.automatic['network'] = {
'interfaces' => {
'lo' => {
'addresses' => {}
}
}
}
allow(subject).to receive(:address_for).with('lo')
.and_raise('Interface lo has no addresses assigned')
expect { subject.address_for('lo') }
.to raise_error(RuntimeError, 'Interface lo has no addresses assigned')
end
it 'fails when no address is available for interface family' do
node.set['network'] = {
node.automatic['network'] = {
'interfaces' => {
'lo' => {
'addresses' => {
@ -104,10 +116,27 @@ describe 'openstack-common::default' do
}
}
}
allow(subject).to receive(:address_for).with('lo', 'inet6')
.and_raise('Interface lo has no address for family inet6')
expect { subject.address_for('lo', 'inet6') }
.to raise_error(RuntimeError, 'Interface lo has no address for family inet6')
.to raise_error(RuntimeError, 'No address for family inet6 found')
end
it 'fails when no address is available after dropping virtual ips' do
node.automatic['network'] = {
'interfaces' => {
'lo' => {
'addresses' => {
'127.0.0.1' => {
'family' => 'inet',
'prefixlen' => '32',
'netmask' => '255.255.255.255',
'scope' => 'Node'
}
}
}
}
}
expect { subject.address_for('lo', 'inet') }
.to raise_error(RuntimeError, 'No address for family inet found')
end
end
end