Enable keystone wsgi support

* New task to deploy Apache and configure MPM
* Run keystone as Apache vhost
* Pull wsgi threads and priority configuration from upstream
  change-id: Ib05ac81381e169845b44b2ef7cb810a4d5db17de
* Pull custom file source for wsgi scripts from upstream
  change-id: I941bf8804982e9081812e076f7a736f413220047
* Fix for keystone spec tests (use concat 1.2.1 in fixtures)
* Use keystone.py wsgi script from packages instead of downloading
  it from puppet module. Requires deb package with this patch:
  https://review.fuel-infra.org/6251
  Until it's megred, we'll use upstream wsgi script for Debian

Change-Id: I85008079b0e922a4518c696a097238500132fa04
Closes-Bug: 1313662
This commit is contained in:
Dmitry Ilyin 2015-04-03 20:39:08 +03:00 committed by Aleksandr Didenko
parent 156fb11bbf
commit 4b1a790959
19 changed files with 296 additions and 133 deletions

View File

@ -1,7 +1,6 @@
fixtures:
repositories:
'apache': 'git://github.com/puppetlabs/puppetlabs-apache.git'
'concat': 'git://github.com/puppetlabs/puppetlabs-concat.git'
'apt': 'git://github.com/puppetlabs/puppetlabs-apt.git'
'mysql':
repo: 'git://github.com/puppetlabs/puppetlabs-mysql.git'
@ -11,5 +10,8 @@ fixtures:
'postgresql':
repo: 'git://github.com/puppetlabs/puppetlabs-postgresql.git'
ref: '2.5.0'
'concat':
'repo': 'git://github.com/puppetlabs/puppetlabs-concat.git'
'ref': '1.2.1'
symlinks:
'keystone': "#{source_dir}"

View File

@ -1,5 +1,3 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright 2013 OpenStack Foundation
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
@ -15,8 +13,6 @@
# under the License.
#
# This file was copied from https://github.com/openstack/keystone/raw/
# c3b92295b718a41c3136876eb39297081015a97c/httpd/keystone.py
# It's only required for platforms on which it is not packaged yet.
# It should be removed when available everywhere in a package.
#
@ -24,23 +20,33 @@
import logging
import os
from paste import deploy
from oslo import i18n
from keystone.openstack.common import gettextutils
# NOTE(blk-u):
# gettextutils.install() must run to set _ before importing any modules that
# contain static translated strings.
gettextutils.install('keystone')
# NOTE(dstanek): i18n.enable_lazy() must be called before
# keystone.i18n._() is called to ensure it has the desired lazy lookup
# behavior. This includes cases, like keystone.exceptions, where
# keystone.i18n._() is called at import time.
i18n.enable_lazy()
from keystone import backends
from keystone.common import dependency
from keystone.common import environment
from keystone.common import sql
from keystone import config
from keystone.openstack.common import log
from keystone import service
CONF = config.CONF
config.configure()
sql.initialize()
config.set_default_for_default_log_levels()
CONF(project='keystone')
config.setup_logging(CONF)
config.setup_logging()
environment.use_stdlib()
name = os.path.basename(__file__)
@ -48,8 +54,12 @@ name = os.path.basename(__file__)
if CONF.debug:
CONF.log_opt_values(log.getLogger(CONF.prog), logging.DEBUG)
drivers = backends.load_backends()
# NOTE(ldbragst): 'application' is required in this context by WSGI spec.
# The following is a reference to Python Paste Deploy documentation
# http://pythonpaste.org/deploy/
application = deploy.loadapp('config:%s' % config.find_paste_config(),
name=name)
application = service.loadapp('config:%s' % config.find_paste_config(), name)
dependency.resolve_future_dependencies()

View File

@ -79,21 +79,25 @@
# Copyright 2013 eNovance <licensing@enovance.com>
#
class keystone::wsgi::apache (
$servername = $::fqdn,
$public_port = 5000,
$admin_port = 35357,
$bind_host = undef,
$public_path = '/',
$admin_path = '/',
$ssl = true,
$workers = 1,
$ssl_cert = undef,
$ssl_key = undef,
$ssl_chain = undef,
$ssl_ca = undef,
$ssl_crl_path = undef,
$ssl_crl = undef,
$ssl_certs_dir = undef
$servername = $::fqdn,
$public_port = 5000,
$admin_port = 35357,
$bind_host = undef,
$public_path = '/',
$admin_path = '/',
$ssl = true,
$workers = 1,
$ssl_cert = undef,
$ssl_key = undef,
$ssl_chain = undef,
$ssl_ca = undef,
$ssl_crl_path = undef,
$ssl_crl = undef,
$ssl_certs_dir = undef,
$threads = $::processorcount,
$priority = '10',
$wsgi_script_ensure = 'file',
$wsgi_script_source = undef,
) {
include keystone::params
@ -130,31 +134,40 @@ class keystone::wsgi::apache (
require => Package['httpd'],
}
file { 'keystone_wsgi_admin':
ensure => file,
path => "${::keystone::params::keystone_wsgi_script_path}/admin",
source => $::keystone::params::keystone_wsgi_script_source,
owner => 'keystone',
group => 'keystone',
mode => '0644',
require => File[$::keystone::params::keystone_wsgi_script_path],
$wsgi_files = {
'keystone_wsgi_admin' => {
'path' => "${::keystone::params::keystone_wsgi_script_path}/admin",
},
'keystone_wsgi_main' => {
'path' => "${::keystone::params::keystone_wsgi_script_path}/main",
},
}
file { 'keystone_wsgi_main':
ensure => file,
path => "${::keystone::params::keystone_wsgi_script_path}/main",
source => $::keystone::params::keystone_wsgi_script_source,
owner => 'keystone',
group => 'keystone',
mode => '0644',
require => File[$::keystone::params::keystone_wsgi_script_path],
$wsgi_file_defaults = {
'ensure' => $wsgi_script_ensure,
'owner' => 'keystone',
'group' => 'keystone',
'mode' => '0644',
'require' => File[$::keystone::params::keystone_wsgi_script_path],
}
$wsgi_script_source_real = $wsgi_script_source ? {
default => $wsgi_script_source,
undef => $::keystone::params::keystone_wsgi_script_source,
}
case $wsgi_script_ensure {
default: { $wsgi_file_source = { 'source' => $wsgi_script_source_real } }
'link': { $wsgi_file_source = { 'target' => $wsgi_script_source_real } }
}
create_resources('file', $wsgi_files, merge($wsgi_file_defaults, $wsgi_file_source))
$wsgi_daemon_process_options = {
user => 'keystone',
group => 'keystone',
processes => $workers,
threads => '1'
threads => $threads
}
$wsgi_script_aliases_main = hash([$public_path_real,"${::keystone::params::keystone_wsgi_script_path}/main"])
$wsgi_script_aliases_admin = hash([$admin_path_real, "${::keystone::params::keystone_wsgi_script_path}/admin"])
@ -172,6 +185,7 @@ class keystone::wsgi::apache (
docroot => $::keystone::params::keystone_wsgi_script_path,
docroot_owner => 'keystone',
docroot_group => 'keystone',
priority => $priority,
ssl => $ssl,
ssl_cert => $ssl_cert,
ssl_key => $ssl_key,
@ -180,32 +194,35 @@ class keystone::wsgi::apache (
ssl_crl_path => $ssl_crl_path,
ssl_crl => $ssl_crl,
ssl_certs_dir => $ssl_certs_dir,
wsgi_daemon_process => 'keystone',
wsgi_daemon_process => 'keystone_main',
wsgi_daemon_process_options => $wsgi_daemon_process_options,
wsgi_process_group => 'keystone',
wsgi_process_group => 'keystone_main',
wsgi_script_aliases => $wsgi_script_aliases_main_real,
require => [Class['apache::mod::wsgi'], File['keystone_wsgi_main']],
}
if $public_port != $admin_port {
apache::vhost { 'keystone_wsgi_admin':
servername => $servername,
ip => $bind_host,
port => $admin_port,
docroot => $::keystone::params::keystone_wsgi_script_path,
docroot_owner => 'keystone',
docroot_group => 'keystone',
ssl => $ssl,
ssl_cert => $ssl_cert,
ssl_key => $ssl_key,
ssl_chain => $ssl_chain,
ssl_ca => $ssl_ca,
ssl_crl_path => $ssl_crl_path,
ssl_crl => $ssl_crl,
ssl_certs_dir => $ssl_certs_dir,
wsgi_process_group => 'keystone',
wsgi_script_aliases => $wsgi_script_aliases_admin,
require => [Class['apache::mod::wsgi'], File['keystone_wsgi_admin']],
servername => $servername,
ip => $bind_host,
port => $admin_port,
docroot => $::keystone::params::keystone_wsgi_script_path,
docroot_owner => 'keystone',
docroot_group => 'keystone',
priority => $priority,
ssl => $ssl,
ssl_cert => $ssl_cert,
ssl_key => $ssl_key,
ssl_chain => $ssl_chain,
ssl_ca => $ssl_ca,
ssl_crl_path => $ssl_crl_path,
ssl_crl => $ssl_crl,
ssl_certs_dir => $ssl_certs_dir,
wsgi_daemon_process => 'keystone_admin',
wsgi_daemon_process_options => $wsgi_daemon_process_options,
wsgi_process_group => 'keystone_admin',
wsgi_script_aliases => $wsgi_script_aliases_admin,
require => [Class['apache::mod::wsgi'], File['keystone_wsgi_admin']],
}
}
}

View File

@ -59,7 +59,7 @@ describe 'keystone::wsgi::apache' do
'docroot_owner' => 'keystone',
'docroot_group' => 'keystone',
'ssl' => 'true',
'wsgi_process_group' => 'keystone',
'wsgi_process_group' => 'keystone_admin',
'wsgi_script_aliases' => { '/' => "#{platform_parameters[:wsgi_script_path]}/admin" },
'require' => ['Class[Apache::Mod::Wsgi]', 'File[keystone_wsgi_admin]']
)}
@ -72,8 +72,8 @@ describe 'keystone::wsgi::apache' do
'docroot_owner' => 'keystone',
'docroot_group' => 'keystone',
'ssl' => 'true',
'wsgi_daemon_process' => 'keystone',
'wsgi_process_group' => 'keystone',
'wsgi_daemon_process' => 'keystone_main',
'wsgi_process_group' => 'keystone_main',
'wsgi_script_aliases' => { '/' => "#{platform_parameters[:wsgi_script_path]}/main" },
'require' => ['Class[Apache::Mod::Wsgi]', 'File[keystone_wsgi_main]']
)}
@ -104,7 +104,7 @@ describe 'keystone::wsgi::apache' do
'docroot_owner' => 'keystone',
'docroot_group' => 'keystone',
'ssl' => 'false',
'wsgi_process_group' => 'keystone',
'wsgi_process_group' => 'keystone_admin',
'wsgi_script_aliases' => { '/' => "#{platform_parameters[:wsgi_script_path]}/admin" },
'require' => ['Class[Apache::Mod::Wsgi]', 'File[keystone_wsgi_admin]']
)}
@ -117,8 +117,8 @@ describe 'keystone::wsgi::apache' do
'docroot_owner' => 'keystone',
'docroot_group' => 'keystone',
'ssl' => 'false',
'wsgi_daemon_process' => 'keystone',
'wsgi_process_group' => 'keystone',
'wsgi_daemon_process' => 'keystone_main',
'wsgi_process_group' => 'keystone_main',
'wsgi_script_aliases' => { '/' => "#{platform_parameters[:wsgi_script_path]}/main" },
'require' => ['Class[Apache::Mod::Wsgi]', 'File[keystone_wsgi_main]']
)}
@ -152,8 +152,8 @@ describe 'keystone::wsgi::apache' do
'docroot_owner' => 'keystone',
'docroot_group' => 'keystone',
'ssl' => 'true',
'wsgi_daemon_process' => 'keystone',
'wsgi_process_group' => 'keystone',
'wsgi_daemon_process' => 'keystone_main',
'wsgi_process_group' => 'keystone_main',
'wsgi_script_aliases' => {
'/main/endpoint' => "#{platform_parameters[:wsgi_script_path]}/main",
'/admin/endpoint' => "#{platform_parameters[:wsgi_script_path]}/admin"
@ -182,6 +182,35 @@ describe 'keystone::wsgi::apache' do
it_raises 'a Puppet::Error', /When using the same port for public & private endpoints, public_path and admin_path should be different\./
end
describe 'when overriding parameters using symlink and custom file source' do
let :params do
{
:wsgi_script_ensure => 'link',
:wsgi_script_source => '/opt/keystone/httpd/keystone.py',
}
end
it { is_expected.to contain_file('keystone_wsgi_admin').with(
'ensure' => 'link',
'path' => "#{platform_parameters[:wsgi_script_path]}/admin",
'target' => '/opt/keystone/httpd/keystone.py',
'owner' => 'keystone',
'group' => 'keystone',
'mode' => '0644',
'require' => "File[#{platform_parameters[:wsgi_script_path]}]"
)}
it { is_expected.to contain_file('keystone_wsgi_main').with(
'ensure' => 'link',
'path' => "#{platform_parameters[:wsgi_script_path]}/main",
'target' => '/opt/keystone/httpd/keystone.py',
'owner' => 'keystone',
'group' => 'keystone',
'mode' => '0644',
'require' => "File[#{platform_parameters[:wsgi_script_path]}]"
)}
end
end
context 'on RedHat platforms' do

View File

@ -58,55 +58,9 @@ class openstack::horizon (
$log_level_real = $log_level
}
# Performance optimization for wsgi
if ($::memorysize_mb < 1200 or $::processorcount <= 3) {
$wsgi_processes = 2
$wsgi_threads = 9
} else {
$wsgi_processes = $::processorcount
$wsgi_threads = 15
}
# Performance optimization for Apache mpm
if $::memorysize_mb < 4100 {
$maxclients = 100
} else {
$maxclients = inline_template('<%= Integer(@memorysize_mb.to_i / 10) %>')
}
if $::processorcount <= 2 {
$startservers = 2
} else {
$startservers = $::processorcount
}
$maxrequestsperchild = 0
$threadsperchild = 25
$minsparethreads = 25
$serverlimit = inline_template('<%= Integer(@maxclients.to_i / @threadsperchild.to_i) %>')
$maxsparethreads = inline_template('<%= Integer(@maxclients.to_i / 2) %>')
# Define apache mpm
if $::osfamily == 'RedHat' {
$mpm_module = 'event'
} else {
$mpm_module = 'worker'
}
class { '::apache':
mpm_module => false,
default_vhost => false,
servername => $servername,
}
class { "::apache::mod::$mpm_module":
startservers => $startservers,
maxclients => $maxclients,
minsparethreads => $minsparethreads,
maxsparethreads => $maxsparethreads,
threadsperchild => $threadsperchild,
maxrequestsperchild => $maxrequestsperchild,
serverlimit => $serverlimit,
# Apache and listen ports
class { 'osnailyfacter::apache':
listen_ports => hiera_array('apache_ports', ['80', '8888']),
}
class { '::horizon':
@ -131,14 +85,24 @@ class openstack::horizon (
secure_cookies => false,
}
# Performance optimization for wsgi
if ($::memorysize_mb < 1200 or $::processorcount <= 3) {
$wsgi_processes = 2
$wsgi_threads = 9
} else {
$wsgi_processes = $::processorcount
$wsgi_threads = 15
}
class { '::horizon::wsgi::apache':
priority => false,
bind_address => "*",
bind_address => $bind_address,
wsgi_processes => $wsgi_processes,
wsgi_threads => $wsgi_threads,
listen_ssl => $use_ssl,
extra_params => {
default_vhost => true,
add_listen => false,
custom_fragment => template("openstack/horizon/wsgi_vhost_custom.erb"),
},
} ~>

View File

@ -213,7 +213,7 @@ class openstack::keystone (
debug => $debug,
catalog_type => 'sql',
admin_token => $admin_token,
enabled => $enabled,
enabled => false,
sql_connection => $sql_conn,
public_bind_host => $public_bind_host,
admin_bind_host => $admin_bind_host,

View File

@ -1,6 +1,7 @@
# Configure apache and listen ports
class osnailyfacter::apache (
$listen_ports = '80',
$purge_configs = false,
$listen_ports = '80',
) {
define apache_port {
@ -11,7 +12,7 @@ class osnailyfacter::apache (
class { '::apache':
mpm_module => false,
default_vhost => false,
purge_configs => false,
purge_configs => $purge_configs,
servername => $::hostname,
}

View File

@ -0,0 +1,39 @@
# Configure apache MPM
class osnailyfacter::apache_mpm {
# Performance optimization for Apache mpm
if $::memorysize_mb < 4100 {
$maxclients = 100
} else {
$maxclients = inline_template('<%= Integer(@memorysize_mb.to_i / 10) %>')
}
if $::processorcount <= 2 {
$startservers = 2
} else {
$startservers = $::processorcount
}
$maxrequestsperchild = 0
$threadsperchild = 25
$minsparethreads = 25
$serverlimit = inline_template('<%= Integer(@maxclients.to_i / @threadsperchild.to_i) %>')
$maxsparethreads = inline_template('<%= Integer(@maxclients.to_i / 2) %>')
# Define apache mpm
if $::osfamily == 'RedHat' {
$mpm_module = 'event'
} else {
$mpm_module = 'worker'
}
class { "::apache::mod::$mpm_module":
startservers => $startservers,
maxclients => $maxclients,
minsparethreads => $minsparethreads,
maxsparethreads => $maxsparethreads,
threadsperchild => $threadsperchild,
maxrequestsperchild => $maxrequestsperchild,
serverlimit => $serverlimit,
}
}

View File

@ -0,0 +1,9 @@
notice('MODULAR: apache.pp')
class { 'osnailyfacter::apache':
purge_configs => true,
listen_ports => hiera_array('apache_ports', ['80', '8888']),
}
include ::osnailyfacter::apache_mpm

View File

@ -0,0 +1,10 @@
require File.join File.dirname(__FILE__), '../test_common.rb'
class ApachePostTest < Test::Unit::TestCase
def test_apache_80_on_public
ip = TestCommon::Settings.public_address
assert TestCommon::Network.connection?(ip, 80), 'Cannot connect to apache on the public address!'
end
end

View File

@ -0,0 +1,11 @@
- id: apache
type: puppet
groups: [primary-controller, controller]
required_for: [keystone]
requires: [openstack-haproxy]
parameters:
puppet_manifest: /etc/puppet/modules/osnailyfacter/modular/apache/apache.pp
puppet_modules: /etc/puppet/modules
timeout: 1200
test_post:
cmd: ruby /etc/puppet/modules/osnailyfacter/modular/apache/apache_post.rb

View File

@ -2,7 +2,7 @@
type: puppet
groups: [primary-controller, controller]
required_for: [deploy_end, controller_remaining_tasks]
requires: [horizon]
requires: [apache]
parameters:
puppet_manifest: /etc/puppet/modules/osnailyfacter/modular/api-proxy/api-proxy.pp
puppet_modules: /etc/puppet/modules

View File

@ -2,7 +2,7 @@
type: puppet
groups: [primary-controller, controller]
required_for: [deploy_end, controller_remaining_tasks]
requires: [horizon, ceph-mon]
requires: [apache, ceph-mon]
parameters:
puppet_manifest: /etc/puppet/modules/osnailyfacter/modular/ceph/radosgw.pp
puppet_modules: /etc/puppet/modules

View File

@ -54,7 +54,7 @@ $syslog_log_facility_ceph = hiera('syslog_log_facility_ceph','LOG_LOCAL0')
$nova_report_interval = hiera('nova_report_interval', 60)
$nova_service_down_time = hiera('nova_service_down_time', 180)
$apache_ports = hiera_array('apache_ports', ['80', '8888'])
$apache_ports = hiera_array('apache_ports', ['80', '8888', '5000', '35357'])
$openstack_version = hiera('openstack_version',
{

View File

@ -15,7 +15,7 @@ class { 'openstack::horizon':
secret_key => $secret_key,
cache_server_ip => $controller_nodes,
package_ensure => hiera('horizon_package_ensure', 'installed'),
bind_address => hiera('internal_address'),
bind_address => '*',
cache_server_port => '11211',
neutron => hiera('use_neutron'),
keystone_host => hiera('management_vip'),

View File

@ -49,6 +49,7 @@ $ceilometer_user_password = $ceilometer_hash['user_password']
$cinder = true
$ceilometer = $ceilometer_hash['enabled']
$enabled = true
$ssl = false
$rabbit_password = $rabbit_hash['password']
$rabbit_user = $rabbit_hash['user']
@ -107,6 +108,29 @@ class { 'openstack::keystone':
idle_timeout => $idle_timeout,
}
####### WSGI ###########
class { 'osnailyfacter::apache':
listen_ports => hiera_array('apache_ports', ['80', '8888']),
}
# TODO: (adidenko) use file from package for Debian, when
# https://review.fuel-infra.org/6251 is merged.
class { 'keystone::wsgi::apache':
priority => '05',
threads => min($::processorcount, 24),
ssl => $ssl,
wsgi_script_ensure => $::osfamily ? {
'RedHat' => 'link',
default => 'file',
},
wsgi_script_source => $::osfamily ? {
# 'Debian' => '/usr/share/keystone/wsgi.py',
'RedHat' => '/usr/share/keystone/keystone.wsgi',
default => undef,
},
}
###############################################################################
class { 'keystone::roles::admin':
@ -132,7 +156,6 @@ class { 'openstack::workloads_collector':
workloads_create_user=> $workloads_hash['create_user'],
}
Exec <| title == 'keystone-manage db_sync' |> ->
Class['keystone::roles::admin'] ->
Class['openstack::auth_file']
@ -153,6 +176,8 @@ haproxy_backend_status { 'keystone-admin' :
}
Service['keystone'] -> Haproxy_backend_status<||>
Service<| title == 'httpd' |> -> Haproxy_backend_status<||>
Haproxy_backend_status<||> -> Class['keystone::roles::admin']
case $::osfamily {
'RedHat': {

View File

@ -0,0 +1,8 @@
require 'spec_helper'
require 'shared-examples'
manifest = 'apache/apache.pp'
describe manifest do
test_ubuntu_and_centos manifest
end

View File

@ -5,14 +5,14 @@ manifest = 'horizon/horizon.pp'
describe manifest do
shared_examples 'catalog' do
horizon_bind_address = Noop.node_hash['internal_address']
internal_address = Noop.node_hash['internal_address']
nova_quota = Noop.hiera 'nova_quota'
# Horizon
it 'should declare openstack::horizon class' do
should contain_class('openstack::horizon').with(
'nova_quota' => nova_quota,
'bind_address' => horizon_bind_address,
'bind_address' => '*',
)
end

View File

@ -33,6 +33,44 @@ describe manifest do
should contain_keystone_config('cache/memcache_pool_unused_timeout').with(:value => '60')
end
it 'should declare keystone::wsgi::apache class with 4 threads on 4 CPU system' do
should contain_class('keystone::wsgi::apache').with(
'threads' => '4',
)
end
it 'should declare keystone::wsgi::apache class with 24 threads on 48 CPU system' do
facts[:processorcount] = 48
should contain_class('keystone::wsgi::apache').with(
'threads' => '24',
)
end
it 'should setup keystone_wsgi_admin file properly' do
case facts[:operatingsystem]
when 'CentOS'
should contain_file('keystone_wsgi_admin').with(
'ensure' => 'link',
'path' => "/var/www/cgi-bin/keystone/admin",
'target' => '/usr/share/keystone/keystone.wsgi',
'owner' => 'keystone',
'group' => 'keystone',
'mode' => '0644',
'require' => "File[/var/www/cgi-bin/keystone]"
)
when 'Ubuntu'
should contain_file('keystone_wsgi_admin').with(
'ensure' => 'file',
'path' => "/usr/lib/cgi-bin/keystone/admin",
'source' => 'puppet:///modules/keystone/httpd/keystone.py',
'owner' => 'keystone',
'group' => 'keystone',
'mode' => '0644',
'require' => "File[/usr/lib/cgi-bin/keystone]"
)
end
end
end # end of shared_examples
test_ubuntu_and_centos manifest