Merge "Add quantum_router_interface custom type."

This commit is contained in:
Jenkins 2013-06-25 07:19:54 +00:00 committed by Gerrit Code Review
commit 5391172b55
6 changed files with 248 additions and 0 deletions

View File

@ -48,3 +48,7 @@ quantum_router { 'demo_router':
gateway_network_name => 'public',
require => Quantum_subnet['public_subnet'],
}
quantum_router_interface { 'demo_router:private_subnet':
ensure => present,
}

View File

@ -1,4 +1,6 @@
require 'csv'
require 'puppet/util/inifile'
class Puppet::Provider::Quantum < Puppet::Provider
def self.conf_filename
@ -140,4 +142,29 @@ correctly configured.")
return exts
end
def self.list_router_ports(router_name_or_id)
results = []
cmd_output = auth_quantum("router-port-list",
'--format=csv',
router_name_or_id)
if ! cmd_output
return results
end
headers = nil
CSV.parse(cmd_output) do |row|
if headers == nil
headers = row
else
result = Hash[*headers.zip(row).flatten]
match_data = /.*"subnet_id": "(.*)", .*/.match(result['fixed_ips'])
if match_data
result['subnet_id'] = match_data[1]
end
results << result
end
end
return results
end
end

View File

@ -0,0 +1,90 @@
require File.join(File.dirname(__FILE__), '..','..','..',
'puppet/provider/quantum')
Puppet::Type.type(:quantum_router_interface).provide(
:quantum,
:parent => Puppet::Provider::Quantum
) do
desc <<-EOT
Quantum provider to manage quantum_router_interface type.
Assumes that the quantum service is configured on the same host.
It is not possible to manage an interface for the subnet used by
the gateway network, and such an interface will appear in the list
of resources ('puppet resource [type]'). Attempting to manage the
gateway interfae will result in an error.
EOT
commands :quantum => 'quantum'
mk_resource_methods
def self.instances
subnet_name_hash = {}
Puppet::Type.type('quantum_subnet').instances.each do |instance|
subnet_name_hash[instance.provider.id] = instance.provider.name
end
instances_ = []
Puppet::Type.type('quantum_router').instances.each do |instance|
list_router_ports(instance.provider.id).each do |port_hash|
router_name = instance.provider.name
subnet_name = subnet_name_hash[port_hash['subnet_id']]
name = "#{router_name}:#{subnet_name}"
instances_ << new(
:ensure => :present,
:name => name,
:id => port_hash['id']
)
end
end
return instances_
end
def self.prefetch(resources)
instances_ = instances
resources.keys.each do |name|
if provider = instances_.find{ |instance| instance.name == name }
resources[name].provider = provider
end
end
end
def exists?
@property_hash[:ensure] == :present
end
def create
results = auth_quantum("router-interface-add", '--format=shell',
resource[:name].split(':', 2))
if results =~ /Added interface to router/
@property_hash = {
:ensure => :present,
:name => resource[:name],
}
else
fail("did not get expected message on interface addition, got #{results}")
end
end
def router_name
name.split(':', 2).first
end
def subnet_name
name.split(':', 2).last
end
def id
# TODO: Need to look this up for newly-added resources since it is
# not returned on creation
end
def destroy
auth_quantum('router-interface-delete', router_name, subnet_name)
@property_hash[:ensure] = :absent
end
end

View File

@ -0,0 +1,47 @@
Puppet::Type.newtype(:quantum_router_interface) do
desc <<-EOT
This is currently used to model the creation of
quantum router interfaces.
Router interfaces are an association between a router and a
subnet.
EOT
ensurable
newparam(:name, :namevar => true) do
newvalues(/^\S+:\S+$/)
end
newproperty(:id) do
validate do |v|
raise(Puppet::Error, 'This is a read only property')
end
end
newproperty(:router_name) do
validate do |v|
raise(Puppet::Error, 'This is a read only property')
end
end
newproperty(:subnet_name) do
validate do |v|
raise(Puppet::Error, 'This is a read only property')
end
end
autorequire(:service) do
['quantum-server']
end
autorequire(:quantum_router) do
self[:name].split(':', 2).first
end
autorequire(:quantum_subnet) do
self[:name].split(':', 2).last
end
end

View File

@ -0,0 +1,36 @@
require 'puppet'
require 'spec_helper'
require 'puppet/provider/quantum_router_interface/quantum'
provider_class = Puppet::Type.type(:quantum_router_interface).
provider(:quantum)
describe provider_class do
let :interface_attrs do
{
:name => 'router:subnet',
:ensure => 'present',
}
end
describe 'when accessing attributes of an interface' do
let :resource do
Puppet::Type::Quantum_router_interface.new(interface_attrs)
end
let :provider do
provider_class.new(resource)
end
it 'should return the correct router name' do
provider.router_name.should eql('router')
end
it 'should return the correct subnet name' do
provider.subnet_name.should eql('subnet')
end
end
end

View File

@ -128,4 +128,48 @@ subnet2"
end
describe 'when listing router ports' do
let :router do
'router1'
end
it 'should handle an empty port list' do
klass.expects(:auth_quantum).with('router-port-list',
'--format=csv',
router)
result = klass.list_router_ports(router)
result.should eql([])
end
it 'should handle several ports' do
output = <<-EOT
"id","name","mac_address","fixed_ips"
"1345e576-a21f-4c2e-b24a-b245639852ab","","fa:16:3e:e3:e6:38","{""subnet_id"": ""839a1d2d-2c6e-44fb-9a2b-9b011dce8c2f"", ""ip_address"": ""10.0.0.1""}"
"de0dc526-02b2-467c-9832-2c3dc69ac2b4","","fa:16:3e:f6:b5:72","{""subnet_id"": ""e4db0abd-276a-4f69-92ea-8b9e4eacfd43"", ""ip_address"": ""172.24.4.226""}"
EOT
expected =
[{ "fixed_ips"=>
"{\"subnet_id\": \"839a1d2d-2c6e-44fb-9a2b-9b011dce8c2f\", \
\"ip_address\": \"10.0.0.1\"}",
"name"=>"",
"subnet_id"=>"839a1d2d-2c6e-44fb-9a2b-9b011dce8c2f",
"id"=>"1345e576-a21f-4c2e-b24a-b245639852ab",
"mac_address"=>"fa:16:3e:e3:e6:38"},
{"fixed_ips"=>
"{\"subnet_id\": \"e4db0abd-276a-4f69-92ea-8b9e4eacfd43\", \
\"ip_address\": \"172.24.4.226\"}",
"name"=>"",
"subnet_id"=>"e4db0abd-276a-4f69-92ea-8b9e4eacfd43",
"id"=>"de0dc526-02b2-467c-9832-2c3dc69ac2b4",
"mac_address"=>"fa:16:3e:f6:b5:72"}]
klass.expects(:auth_quantum).
with('router-port-list', '--format=csv', router).
returns(output)
result = klass.list_router_ports(router)
result.should eql(expected)
end
end
end