Merge "Add quantum_router custom type."

This commit is contained in:
Jenkins 2013-06-25 07:19:53 +00:00 committed by Gerrit Code Review
commit cc253f6bd7
4 changed files with 302 additions and 0 deletions

View File

@ -3,6 +3,10 @@
# resources necessary to boot a vm with network connectivity provided
# by quantum.
#
# Note that a quantum_router resouce must declare a dependency on the
# first subnet of the gateway network. Other dependencies for the
# resources used in this example can be automatically determined.
#
keystone_tenant { 'admin':
ensure => present,
@ -36,3 +40,11 @@ quantum_subnet { 'private_subnet':
network_name => 'private',
tenant_name => 'demo',
}
# Tenant-private router - assumes network namespace isolation
quantum_router { 'demo_router':
ensure => present,
tenant_name => 'demo',
gateway_network_name => 'public',
require => Quantum_subnet['public_subnet'],
}

View File

@ -0,0 +1,146 @@
require File.join(File.dirname(__FILE__), '..','..','..',
'puppet/provider/quantum')
Puppet::Type.type(:quantum_router).provide(
:quantum,
:parent => Puppet::Provider::Quantum
) do
desc <<-EOT
Quantum provider to manage quantum_router type.
Assumes that the quantum service is configured on the same host.
EOT
commands :quantum => 'quantum'
mk_resource_methods
def self.instances
list_quantum_resources('router').collect do |id|
attrs = get_quantum_resource_attrs('router', id)
new(
:ensure => :present,
:name => attrs['name'],
:id => attrs['id'],
:admin_state_up => attrs['admin_state_up'],
:external_gateway_info => attrs['external_gateway_info'],
:status => attrs['status'],
:tenant_id => attrs['tenant_id']
)
end
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
opts = Array.new
if @resource[:admin_state_up] == 'False'
opts << '--admin-state-down'
end
if @resource[:tenant_name]
opts << "--tenant_id=#{get_tenant_id}"
elsif @resource[:tenant_id]
opts << "--tenant_id=#{@resource[:tenant_id]}"
end
results = auth_quantum("router-create", '--format=shell',
opts, resource[:name])
if results =~ /Created a new router:/
@router = Hash.new
results.split("\n").compact do |line|
@router[line.split('=').first] = \
line.split('=', 2)[1].gsub(/\A"|"\Z/, '')
end
@property_hash = {
:ensure => :present,
:name => resource[:name],
:id => @router[:id],
:admin_state_up => @router[:admin_state_up],
:external_gateway_info => @router[:external_gateway_info],
:status => @router[:status],
:tenant_id => @router[:tenant_id],
}
if @resource[:gateway_network_name]
results = auth_quantum('router-gateway-set',
@resource[:name],
@resource[:gateway_network_name])
if results =~ /Set gateway for router/
attrs = self.class.get_quantum_resource_attrs('router',
@resource[:name])
@property_hash[:external_gateway_info] = \
attrs['external_gateway_info']
else
fail(<<-EOT
did not get expected message on setting router gateway, got #{results}
EOT
)
end
end
else
fail("did not get expected message on router creation, got #{results}")
end
end
def get_tenant_id
@tenant_id ||= model.catalog.resource( \
"Keystone_tenant[#{resource[:tenant_name]}]").provider.id
end
def destroy
auth_quantum('router-delete', name)
@property_hash[:ensure] = :absent
end
def gateway_network_name
if @gateway_network_name == nil and gateway_network_id
Puppet::Type.type('quantum_network').instances.each do |instance|
if instance.provider.id == gateway_network_id
@gateway_network_name = instance.provider.name
end
end
end
@gateway_network_name
end
def gateway_network_name=(value)
if value == ''
auth_quantum('router-gateway-clear', name)
else
auth_quantum('router-gateway-set', name, value)
end
end
def parse_gateway_network_id(external_gateway_info_)
match_data = /\{"network_id": "(.*)"\}/.match(external_gateway_info_)
if match_data
match_data[1]
else
''
end
end
def gateway_network_id
@gateway_network_id ||= parse_gateway_network_id(external_gateway_info)
end
def admin_state_up=(value)
auth_quantum('router-update', "--admin-state-up=#{value}", name)
end
end

View File

@ -0,0 +1,91 @@
Puppet::Type.newtype(:quantum_router) do
ensurable
newparam(:name, :namevar => true) do
desc 'Symbolic name for the router'
newvalues(/.*/)
end
newproperty(:id) do
desc 'The unique id of the router'
validate do |v|
raise(Puppet::Error, 'This is a read only property')
end
end
newproperty(:admin_state_up) do
desc 'The administrative status of the router'
newvalues(/(t|T)rue/, /(f|F)alse/)
munge do |v|
v.to_s.capitalize
end
end
newproperty(:external_gateway_info) do
desc <<-EOT
External network that this router connects to for gateway services
(e.g., NAT).
EOT
validate do |v|
raise(Puppet::Error, 'This is a read only property')
end
end
newproperty(:gateway_network_name) do
desc <<-EOT
The name of the external network that this router connects to
for gateway services (e.g. NAT).
EOT
end
newproperty(:gateway_network_id) do
desc <<-EOT
The uuid of the external network that this router connects to
for gateway services (e.g. NAT).
EOT
validate do |v|
raise(Puppet::Error, 'This is a read only property')
end
end
newproperty(:status) do
desc 'Whether the router is currently operational or not.'
validate do |v|
raise(Puppet::Error, 'This is a read only property')
end
end
newparam(:tenant_name) do
desc 'The name of the tenant which will own the router.'
end
newproperty(:tenant_id) do
desc 'A uuid identifying the tenant which will own the router.'
end
autorequire(:service) do
['quantum-server']
end
autorequire(:keystone_tenant) do
[self[:tenant_name]] if self[:tenant_name]
end
autorequire(:quantum_network) do
[self[:gateway_network_name]] if self[:gateway_network_name]
end
validate do
if self[:ensure] != :present
return
end
if self[:tenant_id] && self[:tenant_name]
raise(Puppet::Error, <<-EOT
Please provide a value for only one of tenant_name and tenant_id.
EOT
)
end
end
end

View File

@ -0,0 +1,53 @@
require 'puppet'
require 'spec_helper'
require 'puppet/provider/quantum_router/quantum'
provider_class = Puppet::Type.type(:quantum_router).provider(:quantum)
describe provider_class do
let :router_name do
'router1'
end
let :router_attrs do
{
:name => router_name,
:ensure => 'present',
:admin_state_up => 'True',
:tenant_id => '',
}
end
describe 'when updating a router' do
let :resource do
Puppet::Type::Quantum_router.new(router_attrs)
end
let :provider do
provider_class.new(resource)
end
it 'should call router-update to change admin_state_up' do
provider.expects(:auth_quantum).with('router-update',
'--admin-state-up=False',
router_name)
provider.admin_state_up=('False')
end
it 'should call router-gateway-clear for an empty network name' do
provider.expects(:auth_quantum).with('router-gateway-clear',
router_name)
provider.gateway_network_name=('')
end
it 'should call router-gateway-set to configure an external network' do
provider.expects(:auth_quantum).with('router-gateway-set',
router_name,
'net1')
provider.gateway_network_name=('net1')
end
end
end