From 2c6a1b75e7cd237e1c73d3f8dc3bc142abf2710b Mon Sep 17 00:00:00 2001 From: Dan Bode Date: Mon, 2 Jan 2012 15:39:23 -0800 Subject: [PATCH] saving my work (not even the initial commit) --- README | 3 + Rakefile | 14 +++ lib/puppet/provider/.keystone_manage.rb.swp | Bin 0 -> 12288 bytes lib/puppet/provider/keystone_manage.rb | 92 ++++++++++++++++ .../provider/keystone_role/keystone_manage.rb | 52 +++++++++ .../keystone_tenant/keystone_manage.rb | 57 ++++++++++ .../provider/keystone_user/keystone_manage.rb | 54 ++++++++++ lib/puppet/type/keystone_role.rb | 20 ++++ lib/puppet/type/keystone_tenant.rb | 26 +++++ lib/puppet/type/keystone_user.rb | 26 +++++ manifests/init.pp | 100 ++++++++++++++++++ spec/classes/keystone_spec.rb | 75 +++++++++++++ spec/spec.opts | 6 ++ spec/spec_helper.rb | 11 ++ templates/initial_data.sh.erb | 40 +++++++ templates/keystone.conf.erb | 81 ++++++++++++++ 16 files changed, 657 insertions(+) create mode 100644 README create mode 100644 Rakefile create mode 100644 lib/puppet/provider/.keystone_manage.rb.swp create mode 100644 lib/puppet/provider/keystone_manage.rb create mode 100644 lib/puppet/provider/keystone_role/keystone_manage.rb create mode 100644 lib/puppet/provider/keystone_tenant/keystone_manage.rb create mode 100644 lib/puppet/provider/keystone_user/keystone_manage.rb create mode 100644 lib/puppet/type/keystone_role.rb create mode 100644 lib/puppet/type/keystone_tenant.rb create mode 100644 lib/puppet/type/keystone_user.rb create mode 100644 manifests/init.pp create mode 100644 spec/classes/keystone_spec.rb create mode 100644 spec/spec.opts create mode 100644 spec/spec_helper.rb create mode 100644 templates/initial_data.sh.erb create mode 100644 templates/keystone.conf.erb diff --git a/README b/README new file mode 100644 index 000000000..77d28a3a0 --- /dev/null +++ b/README @@ -0,0 +1,3 @@ +This repo is not ready to be used. + +These initial check-ins are just to save my current progress. diff --git a/Rakefile b/Rakefile new file mode 100644 index 000000000..6242a3704 --- /dev/null +++ b/Rakefile @@ -0,0 +1,14 @@ +require 'rake' + +task :default => [:spec] + +desc "Run all module spec tests (Requires rspec-puppet gem)" +task :spec do + system("rspec spec/**/*_spec.rb") +end + +desc "Build package" +task :build do + system("puppet-module build") +end + diff --git a/lib/puppet/provider/.keystone_manage.rb.swp b/lib/puppet/provider/.keystone_manage.rb.swp new file mode 100644 index 0000000000000000000000000000000000000000..a9388afe50639370260784ef2b7128f3cd7aa91c GIT binary patch literal 12288 zcmeI2&u`pB6vwAX(3Vn&sKf;!z3z%`7A4;N0D&U5ErLW;v?Z-dDm95#v+LQciPyI5 zandx|!hsWT;lPhS0dYer7vKVdGk4SjLLA@^011SE?~KP@=SS0uTa~f&iS0M(|{fu47!7>*IfZr}R%qVw@PY~(g$E)UwFD^$zAhw)4LytA+0P2<>D<0~-_ zWFtzWNJyWzlkqSTK_Yo)wb2jV)E7x(Rcs_O3`E2C+QzdH#o?OginwTO^?ATogcG;- z?b$Y31rE3ZsqBuwaGXs~O-?8!s+E&;;_){QxF~k`RspMkRlq7>6|f3e1*`&AfrF)h zj1IB4Fysf!u$RpF(2ldYwI{29Rlq7>6|f3e1*`&A0jq#jz$#!BunJfO?n4E*%htGpN1q)yfjDs3D1^zzH*xTR+*Z?62z$Ne!I0k-ugs~sM7vLkX0YV_aHEnw|(IfmooO+sT7sEPEV8u z*dmvhm}Zk|SK?IEXltuvn&W;VYC6CbT}p)Cb#zx;ik3+|s(Y(5?KQ00_Y!G(8X7Tx zaNSt95A04uo4p>1j>G_}n?c%di@4PZ{j?t>12PwSnAJ_W5s86HKL$e@r~p-hlXy48 zz@hVApp@}(8Wa)`d0iEvo#4K`7b!I=pzY zs=QWFx(PA0Z&zm5)9&%4XKE=w?SZioju}@Zo!E<{7Y5Wk4c&dQIGqcpJrWVGc^%Qh zRL&iymdDCDN-Yzm7S;WtPB^)|4E;BYnCw+?)_ELw!OCc5PR|Wj;4yX}qpkw;!o*@~ zs41~6ok_K~I5ibm8>46Ij^Lf1etyc7KR=a8)sqQPDBVsy-)$+!mR3&pF%(YQNFPHZ z(Ka>n7aKxJTnBP-PpM4XF0qV#r(C;U?jm=-Y}`SI%nwRTmz2ni_oPMU`oGo4!qu!v zF^P6etCCc@bx)ym%PyI;^{yhBtap(}dF_}g%5+ciD91vaDE8Jcch!oUPmjI73-e~L zGbXrRx;s8rhyf-k)`%dKv>_xV_?CpR)Jp user[0], + :enabled => user[2], + :tenant => user[3] + } + end + hash + end + + def self.build_tenant_hash + hash = {} + list_keystone_objects('tenant', 3).each do |tenant| + validate_enabled(tenant[2]) + hash[tenant[1]] = { + :id => tenant[0], + :enabled => tenant[2], + } + end + hash + end + + def self.build_role_hash + hash = {} + list_keystone_objects('role', 4).each do |role| + Puppet.warning("Found deplicate role #{role[1]}") if hash[role[1]] + hash[role[1]] = { + :id => role[0], + :service_id => role[2], + :description => role[3] + } + end + hash + end + + def self.list_keystone_objects(type, number_columns) + # this assumes that all returned objects are of the form + # id, name, enabled_state, OTHER + list = keystone_manage(type, 'list').split("\n")[5..-2].collect do |line| + row = line.split(/\s*\|\s*/)[1..-1] + if row.size != number_columns + raise(Puppet::Error, "Expected #{number_columns} columns for #{type} row, found #{list.size}. Line #{line}") + end + row + end + list + end + + def self.validate_enabled(value) + unless value == 'True' || value == 'False' + raise(Puppet::Error, "Invalid value #{value} for enabled attribute") + end + end +end diff --git a/lib/puppet/provider/keystone_role/keystone_manage.rb b/lib/puppet/provider/keystone_role/keystone_manage.rb new file mode 100644 index 000000000..64c53decc --- /dev/null +++ b/lib/puppet/provider/keystone_role/keystone_manage.rb @@ -0,0 +1,52 @@ +require 'puppet/provider/keystone_manage' +Puppet::Type.type(:keystone_role).provide( + :keystone_manage, + :parent => Puppet::Provider::KeystoneManager +) do + + optional_commands :keystone_manage => 'keystone-manage' + + def self.instances + role_hash.collect do |k, v| + puts "|#{k}|" + new(:name => k) + end + end + + def create + keystone_manage('role', 'add', resource[:name], resource[:service]) + end + + def exists? + role_hash[resource[:name]] + end + + def destroy + raise(Puppet::Error, "keystone-manage does not support removing roles") + end + + def id + role_hash[resource[:name]][:id] + end + + def service + role_hash[resource[:name]][:service] + end + + def description + role_hash[resource[:name]][:description] + end + + def id=(id) + raise(Puppet::Error, "Id is a read only property") + end + + def service=(service_name) + property_not_supported('service') + end + + def description=(description) + property_not_supported('description') + end + +end diff --git a/lib/puppet/provider/keystone_tenant/keystone_manage.rb b/lib/puppet/provider/keystone_tenant/keystone_manage.rb new file mode 100644 index 000000000..6b19840b4 --- /dev/null +++ b/lib/puppet/provider/keystone_tenant/keystone_manage.rb @@ -0,0 +1,57 @@ +require 'puppet/provider/keystone_manage' +Puppet::Type.type(:keystone_tenant).provide( + :keystone_manage, + :parent => Puppet::Provider::KeystoneManager +) do + + desc <<-EOT + + Provider that uses the keystone-manage tool to + manage keystone tenants + + As of the essex release, there is no way to delete an existing + tenant. A disabled tenant will be considered the same as an + absent tenant (although they are not quite the same, I do not + think it will be possible to create a tenant once it has been + deleted) + + EOT + + optional_commands :keystone_manage => 'keystone-manage' + + def self.instances + tenant_hash.collect do |k, v| + new(:name => k) + end + end + + def create + keystone_manage('tenant', 'add', resource[:name]) + end + + def exists? + # a tenant is absent if it doesnt exist or if it is disabled + tenant_hash[resource[:name]] and tenant_hash[resource[:name]][:enabled] == 'True' + end + + def destroy + Puppet.warning("Deleting the tenant is not currently supported, it will be disabled") + keystone_manage('tenant', 'disable', resource[:name]) + end + +# def enabled=(state) +# if state == 'True' +# raise(Puppet::Error, 'Enabling a disabled Tenant is not currently supported') +# else +# keystone_manage('tenant', 'disable', resource[:name]) +# end +# end + +# def enabled +# tenant_hash[resource['name']][:enabled] +# end + + def id + tenant_hash[resource['name']][:id] + end +end diff --git a/lib/puppet/provider/keystone_user/keystone_manage.rb b/lib/puppet/provider/keystone_user/keystone_manage.rb new file mode 100644 index 000000000..9601ce197 --- /dev/null +++ b/lib/puppet/provider/keystone_user/keystone_manage.rb @@ -0,0 +1,54 @@ +require 'puppet/provider/keystone_manage' +Puppet::Type.type(:keystone_user).provide( + :keystone_manage, + :parent => Puppet::Provider::KeystoneManager +) do + + optional_commands :keystone_manage => 'keystone-manage' + + def self.instances + user_hash.collect do |k, v| + puts "|#{k}|" + new(:name => k) + end + end + + def create + ['tenant', 'password'].each do |x| + raise(Puppet::Error, "Cannot create keystone user without parameter: #{x}") unless self[x.to_sym] + end + keystone_manage( + 'user', + 'add', + resource[:name], + resource[:password], + resource[:tenant] + ) + end + + def exists? + user_hash[resource[:name]] and user_hash[resource[:name]][:enabled] == 'True' + end + + def destroy + Puppet.warning("Deleting the user is not currently supported, it will be disabled") + keystone_manage('user', 'disable', resource[:name]) + end + + def tenant=(tenant) + raise(Puppet::Error, "Setting the user tenant property is currently not supported") + end + + def tenant + # I need to translate this from the other command + tenant_id = user_hash[resource[:name]][:tenant] + if tenant_id == 'None' + 'None' + else + # maybe I should check more explicityly + # to see if the id is valid + tenant_hash.find {|k,v| v[:id] == tenant_id }[0] + end + end + +end diff --git a/lib/puppet/type/keystone_role.rb b/lib/puppet/type/keystone_role.rb new file mode 100644 index 000000000..2537287cf --- /dev/null +++ b/lib/puppet/type/keystone_role.rb @@ -0,0 +1,20 @@ +Puppet::Type.newtype(:keystone_role) do + + desc <<-EOT + Type to create new keystone roles. + EOT + + ensurable + + newparam(:name, :namevar => true) do + end + + newproperty(:id) do + end + + newproperty(:service) do + end + + newproperty(:description) do + end +end diff --git a/lib/puppet/type/keystone_tenant.rb b/lib/puppet/type/keystone_tenant.rb new file mode 100644 index 000000000..a93df4985 --- /dev/null +++ b/lib/puppet/type/keystone_tenant.rb @@ -0,0 +1,26 @@ +Puppet::Type.newtype(:keystone_tenant) do + + desc <<-EOT + This type can be used to create + keystone tenants. + EOT + + ensurable + + newparam(:name, :namevar => true) do + newvalues(/\w+/) + end + +# newproperty(:enabled) do +# newvalues(/(t|T)rue/, /(f|F)alse/) +# munge do |value| +# value.to_s.capitalize +# end +# end + + newproperty(:id) do + validate do |v| + raise(Puppet::Error, 'This is a read only property') + end + end +end diff --git a/lib/puppet/type/keystone_user.rb b/lib/puppet/type/keystone_user.rb new file mode 100644 index 000000000..a771e28e7 --- /dev/null +++ b/lib/puppet/type/keystone_user.rb @@ -0,0 +1,26 @@ +Puppet::Type.newtype(:keystone_user) do + + desc <<-EOT + + This is currently used to model the creation of + keystone users. + + It currently requires that both the password + as well as the tenant are specified. + + EOT + + newparam(:name, :namevar => true) do + newvalues(/\S+/) + end + + newparam(:password) do + newvalues(/\S+/) + end + + newproperty(:tenant) do + newvalues(/\S+/) + end + + +end diff --git a/manifests/init.pp b/manifests/init.pp new file mode 100644 index 000000000..df6a289a0 --- /dev/null +++ b/manifests/init.pp @@ -0,0 +1,100 @@ +# +# module for installing keystone +# +# does this always live on the nova API server? +# + +class keystone( + $package_ensure = 'present', + $log_verbose = 'False', + $log_debug = 'False', + $default_store = 'sqlite', + $bind_host = '0.0.0.0', + $bind_port = '5000', + $admin_bind_host = '0.0.0.0', + $admin_bind_port = '5001' +) { + + # may need to add a user for HA + + # TODO does keystone need nova-common? + + #Package['keystone'] ~> Service<| 'title' = 'nova-api' |> + + # this package dependency needs to be removed when it + # is added as a package dependency + # I filed the following ticket against the packages: 909941 + if(! defined(Package['python-migrate'])) { + package { 'python-migrate': + ensure => present, + } + } + + package { 'keystone': + ensure => $package_ensure, + # I do not understand what this does?? + #notify => Exec["fix_tools_tracer"], + } + + file { '/etc/keystone': + ensure => directory, + owner => 'keystone', + group => 'keystone', + mode => 0755, + require => Package['keystone'] + } + + file { 'keystone.conf': + path => '/etc/keystone/keystone.conf', + ensure => present, + owner => 'keystone', + mode => 0600, + content => template('keystone/keystone.conf.erb'), + notify => Service['keystone'], + require => Package['keystone'], #Exec['fix_tools_tracer']] + } + + +# # I would prefer not to be loading initial data into keystone +# file { 'initial_data.sh': +# path => '/var/lib/keystone/initial_data.sh', +# ensure => present, +# owner => 'keystone', +# mode => 0700, +# content => template('keystone/initial_data.sh.erb'), +# require => Package['keystone'] +# } +# +# exec { 'create_keystone_data': +# user => 'keystone', +# command => '/var/lib/keystone/initial_data.sh', +# path => [ '/bin', '/usr/bin' ], +# unless => 'keystone-manage user list | grep -q admin', +# require => [ +# Package['keystone'], +# File['keystone.conf'], +# File['initial_data.sh'] +# ] +# } + + service { 'keystone': + ensure => running, + enable => true, + hasstatus => true, + hasrestart => true, + } + + # TODO - figure out if I can remove this patching code? + # this can't be serious + # this Puppet code is patching keystone? Why? + #exec { "fix_tools_tracer": + # command => 'sed -e "s,^import tools.tracer,#import tools.tracer," -i /usr/lib/python2.6/dist-packages/keystone/middleware/auth_token.py /usr/bin/keystone', + # path => [ "/bin", "/usr/bin" ], + # notify => [Service["nova-api"]], + # refreshonly => true, + # require => [ + # Package['keystone'], + # ] + #} + +} diff --git a/spec/classes/keystone_spec.rb b/spec/classes/keystone_spec.rb new file mode 100644 index 000000000..c7adc6d2c --- /dev/null +++ b/spec/classes/keystone_spec.rb @@ -0,0 +1,75 @@ +require 'spec_helper' + +describe 'keystone' do + + let :default_params do + { + 'package_ensure' => 'present', + 'log_verbose' => 'False', + 'log_debug' => 'False', + 'default_store' => 'sqlite', + 'bind_host' => '0.0.0.0', + 'bind_port' => '5000', + 'admin_bind_host' => '0.0.0.0', + 'admin_bind_port' => '5001' + } + end + + [{}, + { + 'package_ensure' => 'latest', + 'log_verbose' => 'True', + 'log_debug' => 'True', + 'default_store' => 'ldap', + 'bind_host' => '127.0.0.1', + 'bind_port' => '50000', + 'admin_bind_host' => '127.0.0.1', + 'admin_bind_port' => '50001' + } + ].each do |param_set| + + describe "when #{param_set == {} ? "using default" : "specifying"} class parameters" do + let :param_hash do + param_set == {} ? default_params : param_set + end + + let :params do + param_set + end + + it { should contain_package('keystone').with_ensure(param_hash['package_ensure']) } + + it { should contain_file('/etc/keystone').with( + 'ensure' => 'directory', + 'owner' => 'keystone', + 'group' => 'keystone', + 'mode' => '0755', + 'require' => 'Package[keystone]' + ) } + + # maybe keystone should always be with the API server? + it 'should refresh nova-api if they are on the same machine' + + it { should contain_service('keystone').with( + 'ensure' => 'running', + 'enable' => 'true', + 'hasstatus' => 'true', + 'hasrestart' => 'true' + ) } + + it 'should compile the template based on the class parameters' do + content = param_value(subject, 'file', 'keystone.conf', 'content') + expected_lines = [ + "verbose = #{param_hash['log_verbose']}", + "debug = #{param_hash['log_debug']}", + "default_store = #{param_hash['default_store']}", + "service_host = #{param_hash['bind_host']}", + "service_port = #{param_hash['bind_port']}", + "admin_host = #{param_hash['admin_bind_host']}", + "admin_port = #{param_hash['admin_bind_port']}" + ] + (content.split("\n") & expected_lines).should == expected_lines + end + end + end +end diff --git a/spec/spec.opts b/spec/spec.opts new file mode 100644 index 000000000..91cd6427e --- /dev/null +++ b/spec/spec.opts @@ -0,0 +1,6 @@ +--format +s +--colour +--loadby +mtime +--backtrace diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb new file mode 100644 index 000000000..d2648da2b --- /dev/null +++ b/spec/spec_helper.rb @@ -0,0 +1,11 @@ +require 'puppet' +require 'rubygems' +require 'rspec-puppet' + +def param_value(subject, type, title, param) + subject.resource(type, title).send(:parameters)[param.to_sym] +end + +RSpec.configure do |c| + c.module_path = File.join(File.dirname(__FILE__), '../../') +end diff --git a/templates/initial_data.sh.erb b/templates/initial_data.sh.erb new file mode 100644 index 000000000..75ac54207 --- /dev/null +++ b/templates/initial_data.sh.erb @@ -0,0 +1,40 @@ +#!/bin/bash + +# Tenants +keystone-manage $* tenant add admin +keystone-manage $* tenant add demo + +# Users +keystone-manage $* user add demo secrete demo +keystone-manage $* user add admin secrete admin + +# Roles +keystone-manage $* role add Admin +keystone-manage $* role add Member +keystone-manage $* role grant Admin admin + +#endpointTemplates +keystone-manage $* endpointTemplates add RegionOne swift http://<%= api_vip %>:8080/v1/AUTH_%tenant_id% http://<%= api_vip %>:8080/ http://<%= api_vip %>:8080/v1/AUTH_%tenant_id% 1 1 +keystone-manage $* endpointTemplates add RegionOne nova_compat http://<%= api_vip %>:8774/v1.0/ http://<%= api_vip %>:8774/v1.0 http://<%= api_vip %>:8774/v1.0 1 1 +keystone-manage $* endpointTemplates add RegionOne nova http://<%= api_vip %>:8774/v1.1/%tenant_id% http://<%= api_vip %>:8774/v1.1/%tenant_id% http://<%= api_vip %>:8774/v1.1/%tenant_id% 1 1 +keystone-manage $* endpointTemplates add RegionOne glance http://<%= api_vip %>:9292/v1.1/%tenant_id% http://<%= api_vip %>:9292/v1.1/%tenant_id% http://<%= api_vip %>:9292/v1.1/%tenant_id% 1 1 +keystone-manage $* endpointTemplates add RegionOne keystone http://<%= api_vip %>:5000/v2.0 http://<%= api_vip %>:5001/v2.0 http://<%= api_vip %>:5000/v2.0 1 1 +keystone-manage $* endpointTemplates add RegionOne identity http://<%= api_vip %>:5000/v2.0 http://<%= api_vip %>:5001/v2.0 http://<%= api_vip %>:5000/v2.0 1 1 + +# Tokens +keystone-manage $* token add 999888777666 admin admin 2015-02-05T00:00 + +#Tenant endpoints +keystone-manage $* endpoint add admin 1 +keystone-manage $* endpoint add admin 2 +keystone-manage $* endpoint add admin 3 +keystone-manage $* endpoint add admin 4 +keystone-manage $* endpoint add admin 5 +keystone-manage $* endpoint add admin 6 + +keystone-manage $* endpoint add demo 1 +keystone-manage $* endpoint add demo 2 +keystone-manage $* endpoint add demo 3 +keystone-manage $* endpoint add demo 4 +keystone-manage $* endpoint add demo 5 +keystone-manage $* endpoint add demo 6 diff --git a/templates/keystone.conf.erb b/templates/keystone.conf.erb new file mode 100644 index 000000000..a3d91332b --- /dev/null +++ b/templates/keystone.conf.erb @@ -0,0 +1,81 @@ +[DEFAULT] +# Show more verbose log output (sets INFO log level output) +verbose = <%= log_verbose %> + +# Show debugging output in logs (sets DEBUG log level output) +debug = <%= log_debug %> + +# Which backend store should Keystone use by default. +# Default: 'sqlite' +# Available choices are 'sqlite' [future will include LDAP, PAM, etc] +default_store = <%= default_store %> + +# Log to this file. Make sure you do not set the same log +# file for both the API and registry servers! +log_file = /var/log/keystone/keystone.log + +# List of backends to be configured +backends = keystone.backends.sqlalchemy +#For LDAP support, add: ,keystone.backends.ldap + +# Dictionary Maps every service to a header.Missing services would get header +# X_(SERVICE_NAME) Key => Service Name, Value => Header Name +service-header-mappings = { + 'nova' : 'X-Server-Management-Url', + 'swift' : 'X-Storage-Url', + 'cdn' : 'X-CDN-Management-Url'} + +# Address to bind the API server +# TODO Properties defined within app not available via pipeline. +service_host = <%= bind_host %> + +# Port the bind the API server to +service_port = <%= bind_port %> + +# Address to bind the Admin API server +admin_host = <%= admin_bind_host %> + +# Port the bind the Admin API server to +admin_port = <%= admin_bind_port %> + +#Role that allows to perform admin operations. +keystone-admin-role = Admin + +#Role that allows to perform service admin operations. +keystone-service-admin-role = KeystoneServiceAdmin + +[keystone.backends.sqlalchemy] +# SQLAlchemy connection string for the reference implementation registry +# server. Any valid SQLAlchemy connection string is fine. +# See: http://bit.ly/ideIpI +sql_connection = sqlite:////var/lib/keystone/keystone.db +backend_entities = ['UserRoleAssociation', 'Endpoints', 'Role', 'Tenant', + 'User', 'Credentials', 'EndpointTemplates', 'Token', + 'Service'] + +# Period in seconds after which SQLAlchemy should reestablish its connection +# to the database. +sql_idle_timeout = 30 + +[pipeline:admin] +pipeline = + urlrewritefilter + admin_api + +[pipeline:keystone-legacy-auth] +pipeline = + urlrewritefilter + legacy_auth + service_api + +[app:service_api] +paste.app_factory = keystone.server:service_app_factory + +[app:admin_api] +paste.app_factory = keystone.server:admin_app_factory + +[filter:urlrewritefilter] +paste.filter_factory = keystone.middleware.url:filter_factory + +[filter:legacy_auth] +paste.filter_factory = keystone.frontends.legacy_token_auth:filter_factory