Floating IP range support in Nova network

This patch provides a possibility to add
ip ranges of networks (i.e.: 192.168.1.210-192.168.1.224)
to a floating ip pool.

Depends-On: I802280e4e2912c9aed1c10d519ead84b1f22f900

Change-Id: Iffb0af32753708decb8d2b60f1075b66f7520553
This commit is contained in:
Maksym Yatsenko 2015-10-09 14:31:31 +03:00
parent d5d73d795b
commit 7e7e848170
4 changed files with 172 additions and 9 deletions

View File

@ -15,6 +15,7 @@ group :development, :test do
gem 'json', :require => 'false'
gem 'webmock', :require => 'false'
gem 'r10k', :require => 'false'
gem 'netaddr', :require => 'false'
end
group :system_tests do

View File

@ -1,3 +1,5 @@
require 'netaddr'
Puppet::Type.type(:nova_floating).provide(:nova_manage) do
desc "Manage nova floating"
@ -5,19 +7,79 @@ Puppet::Type.type(:nova_floating).provide(:nova_manage) do
optional_commands :nova_manage => 'nova-manage'
def exists?
# Calculate num quads to grab for prefix
mask=resource[:network].sub(/.*\/([0-9][0-9]?)/, '\1').to_i
num_quads = 4 - mask / 8
prefix=resource[:network].sub(/(\.[0-9]{1,3}){#{num_quads}}(\/[0-9]{1,2})?$/, '') + "."
return nova_manage("floating", "list").match(/#{prefix}/)
if resource[:network] =~ /^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\/[0-9]{1,2}$/
# Calculate num quads to grab for prefix$$
mask=resource[:network].sub(/.*\/([0-9][0-9]?)/, '\1').to_i
num_quads = 4 - mask / 8
prefix=resource[:network].sub(/(\.[0-9]{1,3}){#{num_quads}}(\/[0-9]{1,2})?$/, '') + "."
return nova_manage("floating", "list").match(/#{prefix}/)
elsif resource[:network].to_s =~ /^.{0,2}\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}-\d{1,3}\.\d{1,3}.\d{1,3}.\d{1,3}.{0,2}/
if resource[:ensure] == :absent
operate_range.any?
else
operate_range.empty?
end
end
end
def create
nova_manage("floating", "create", '--pool', resource[:pool], resource[:network])
if resource[:network] =~ /^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\/[0-9]{1,2}$/
nova_manage("floating", "create", '--pool', resource[:pool], resource[:network])
elsif resource[:network].to_s =~ /^.{0,2}\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}-\d{1,3}\.\d{1,3}.\d{1,3}.\d{1,3}.{0,2}/
mixed_range.each do |ip|
nova_manage("floating", "create", ip)
end
end
end
def destroy
nova_manage("floating", "delete", resource[:network])
if resource[:network] =~ /^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\/[0-9]{1,2}$/
nova_manage("floating", "delete", resource[:network])
elsif resource[:network].to_s =~ /^.{0,2}\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}-\d{1,3}\.\d{1,3}.\d{1,3}.\d{1,3}.{0,2}/
mixed_range.each do |ip|
nova_manage("floating", "delete", ip )
end
end
end
# Create range in cidr, including first and last ip
# Nova will create this range, excluding network and broadcast IPs
def mixed_range
range = []
NetAddr.merge(operate_range).each do |cidr|
tmp_range = NetAddr::CIDR.create(cidr).enumerate
range << tmp_range.first.to_s
range << tmp_range.last.to_s
end
range.uniq!
range += NetAddr.merge(operate_range).delete_if{ |part| part =~ /\/3[12]/}
end
# Calculate existed IPs and provided ip ranges
def operate_range
exist_range = []
output = nova_manage("floating", "list")
range_list = output.scan(/\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/)
range_list.each do |element|
exist_range << element
end
if @resource[:ensure] == :absent
ip_range & exist_range
else
ip_range - exist_range
end
end
def ip_range
ip_range = []
Array(@resource[:network]).each do |rng|
ip = rng.split('-')
generated_range = NetAddr.range(NetAddr::CIDR.create(ip.first), NetAddr::CIDR.create(ip.last))
ip_range += generated_range.unshift(ip.first).push(ip.last)
end
return ip_range
end
end

View File

@ -5,8 +5,9 @@ Puppet::Type.newtype(:nova_floating) do
ensurable
newparam(:network, :namevar => true) do
desc "Network (ie, 192.168.1.0/24 or 192.168.1.128/25 etc.)"
newvalues(/^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\/[0-9]{1,2}$/)
desc "It can contain network (ie, 192.168.1.0/24 or 192.168.1.128/25 etc.),
ip range ('192.168.1.1-192.168.1.55' or list of ip ranges ['192.168.1.1-192.168.1.25', '192.168.1.30-192.168.1.55'])"
newvalues(/^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\/[0-9]{1,2}$ || ^(\d{1,3}\.){3}\d{1,3}-(\d{1,3}\.){3}\d{1,3}$/)
end
newparam(:pool) do

View File

@ -0,0 +1,99 @@
require 'puppet'
require 'puppet/provider/nova_floating/nova_manage'
require 'tempfile'
provider_class = Puppet::Type.type(:nova_floating).provider(:nova_manage)
describe provider_class do
let :range_attrs do
{
:ensure => 'present',
:pool => 'nova',
:network => '10.1.0.1-10.1.0.2',
}
end
let :network_attrs do
{
:ensure => 'present',
:pool => 'nova',
:network => '11.1.0.0/30'
}
end
let :resource_range do
Puppet::Type::Nova_floating.new(range_attrs)
end
let :resource_network do
Puppet::Type::Nova_floating.new(network_attrs)
end
let :provider_range do
provider_class.new(resource_range)
end
let :provider_network do
provider_class.new(resource_network)
end
shared_examples 'nova_floating' do
describe '#exists?' do
it 'should check if ips of a network are not existing' do
provider_network.expects(:nova_manage).with('floating', 'list').returns('No floating IP addresses have been defined.')
expect(provider_network.exists?).to be_falsey
end
it 'should check if ips of a network are existing' do
provider_network.expects(:nova_manage).with('floating', 'list').returns('None 11.1.0.1 None nova br-ex\nNone 11.1.0.2 None nova br-ex')
expect(provider_network.exists?).to be_truthy
end
it 'should check if ips are not existing' do
provider_range.expects(:nova_manage).with('floating', 'list').returns('No floating IP addresses have been defined.')
expect(provider_range.exists?).to be_falsey
end
it 'should check if ips are existing' do
provider_range.expects(:nova_manage).with('floating', 'list').returns('None 10.1.0.1 None nova br-ex\nNone 10.1.0.2 None nova br-ex')
expect(provider_range.exists?).to be_truthy
end
end
describe '#create' do
it 'should check if ips of network were created' do
provider_network.expects(:nova_manage).with('floating', 'create', '--pool', 'nova', '11.1.0.0/30').returns('None 11.1.0.1 None nova br-ex\nNone 11.1.0.2 None nova br-ex')
expect(provider_network.create).to be_truthy
end
it 'should check if ips of range were created' do
provider_range.stubs(:nova_manage).with('floating', 'create', '10.1.0.1')
provider_range.stubs(:nova_manage).with('floating', 'create', '10.1.0.2')
provider_range.stubs(:nova_manage).with('floating', 'list').returns('None 10.1.0.1 None nova br-ex\nNone 10.1.0.2 None nova br-ex')
expect(provider_range.create).to be_truthy
end
end
describe '#destroy' do
it 'should check if ips of network were deleted' do
provider_network.expects(:nova_manage).with('floating', 'delete', '11.1.0.0/30').returns('No floating IP addresses have been defined.')
expect(provider_network.destroy).to be_truthy
end
it 'should check if ips of range were deleted' do
provider_range.stubs(:nova_manage).with('floating', 'delete', '10.1.0.1')
provider_range.expects(:nova_manage).with('floating', 'list').returns('None 10.1.0.2 None nova br-ex')
provider_range.stubs(:nova_manage).with('floating', 'delete', '10.1.0.2')
provider_range.expects(:nova_manage).with('floating', 'list').returns('No floating IP addresses have been defined.')
expect(provider_range.destroy).to be_truthy
end
end
end
it_behaves_like('nova_floating')
end