Support Neutron API in WSGI with Apache
Allow to deploy Neutron API in WSGI with Apache. Note: the feature is not tested yet in our functional testing jobs because it doesn't work in devstack yet. This code will maybe need some change but that's fine, it's for Pike cycle, nothing needs to be backported, so we can easily iterate later. Also remove dependencies in keystone auth manifest where keystone resources had to be created before we start neutron-server. This is not possible anymore since neutron-server is run in httpd. Change-Id: I27bdd8d011097c5fd49277578404b4facafaca25
This commit is contained in:
parent
4950563c8d
commit
c1f019f8e1
17
examples/neutron_wsgi.pp
Normal file
17
examples/neutron_wsgi.pp
Normal file
@ -0,0 +1,17 @@
|
||||
# Example of manifest to deploy Neutron API in WSGI with Apache
|
||||
class { '::neutron':
|
||||
allow_overlapping_ips => true,
|
||||
rabbit_password => 'password',
|
||||
rabbit_user => 'guest',
|
||||
rabbit_host => 'localhost',
|
||||
}
|
||||
|
||||
class { '::neutron::server':
|
||||
auth_password => 'password',
|
||||
database_connection => 'mysql://neutron:password@192.168.1.1/neutron',
|
||||
service_name => 'httpd',
|
||||
}
|
||||
include ::apache
|
||||
class { '::neutron::wsgi::apache':
|
||||
ssl => false,
|
||||
}
|
@ -80,11 +80,11 @@ class neutron::keystone::auth (
|
||||
include ::neutron::deps
|
||||
|
||||
if $configure_endpoint {
|
||||
Keystone_endpoint["${region}/${service_name}::${service_type}"] ~> Service <| title == 'neutron-server' |>
|
||||
Keystone_endpoint["${region}/${service_name}::${service_type}"] ~> Service <| tag == 'neutron-server-eventlet' |>
|
||||
}
|
||||
|
||||
if $configure_user_role {
|
||||
Keystone_user_role["${auth_name}@${tenant}"] ~> Service <| title == 'neutron-server' |>
|
||||
Keystone_user_role["${auth_name}@${tenant}"] ~> Service <| tag == 'neutron-server-eventlet' |>
|
||||
}
|
||||
|
||||
keystone::resource::service_identity { 'neutron':
|
||||
|
@ -71,6 +71,8 @@ class neutron::params {
|
||||
$libreswan_package = 'libreswan'
|
||||
$l3_agent_package = false
|
||||
$fwaas_package = 'openstack-neutron-fwaas'
|
||||
$neutron_wsgi_script_path = '/var/www/cgi-bin/neutron'
|
||||
$neutron_wsgi_script_source = '/usr/bin/neutron-api'
|
||||
} elsif($::osfamily == 'Debian') {
|
||||
$nobody_user_group = 'nogroup'
|
||||
$package_name = 'neutron-common'
|
||||
@ -102,6 +104,8 @@ class neutron::params {
|
||||
$fwaas_package = 'python-neutron-fwaas'
|
||||
$l2gw_agent_package = 'neutron-l2gateway-agent'
|
||||
$l2gw_package = 'python-networking-l2gw'
|
||||
$neutron_wsgi_script_path = '/usr/lib/cgi-bin/neutron'
|
||||
$neutron_wsgi_script_source = '/usr/bin/neutron-api'
|
||||
} else {
|
||||
fail("Unsupported osfamily ${::osfamily}")
|
||||
}
|
||||
|
@ -17,8 +17,13 @@
|
||||
# Defaults to true
|
||||
#
|
||||
# [*service_name*]
|
||||
# (optional) The name of the neutron-server service
|
||||
# Defaults to $::neutron::params::server_service
|
||||
# (optional) Name of the service that will be providing the
|
||||
# server functionality of neutron-api.
|
||||
# If the value is 'httpd', this means neutron-api will be a web
|
||||
# service, and you must use another class to configure that
|
||||
# web service. For example, use class { 'neutron::wsgi::apache'...}
|
||||
# to make neutron-api be a web app using apache mod_wsgi.
|
||||
# Defaults to '$::neutron::params::server_service'
|
||||
#
|
||||
# [*log_file*]
|
||||
# REMOVED: Use log_file of neutron class instead.
|
||||
@ -409,7 +414,30 @@ class neutron::server (
|
||||
$service_ensure = 'stopped'
|
||||
}
|
||||
}
|
||||
|
||||
if $service_name == $::neutron::params::server_service {
|
||||
service { 'neutron-server':
|
||||
ensure => $service_ensure,
|
||||
name => $::neutron::params::server_service,
|
||||
enable => $enabled,
|
||||
hasstatus => true,
|
||||
hasrestart => true,
|
||||
tag => ['neutron-service', 'neutron-db-sync-service', 'neutron-server-eventlet'],
|
||||
}
|
||||
} elsif $service_name == 'httpd' {
|
||||
include ::apache::params
|
||||
service { 'neutron-server':
|
||||
ensure => 'stopped',
|
||||
name => $::neutron::params::server_service,
|
||||
enable => false,
|
||||
hasstatus => true,
|
||||
hasrestart => true,
|
||||
tag => ['neutron-service', 'neutron-db-sync-service'],
|
||||
}
|
||||
Service <<| title == 'httpd' |>> { tag +> 'neutron-service' }
|
||||
# we need to make sure neutron-server is stopped before trying to start apache
|
||||
Service[$::neutron::params::server_service] -> Service[$service_name]
|
||||
} else {
|
||||
# backward compatibility so operators can customize the service name.
|
||||
service { 'neutron-server':
|
||||
ensure => $service_ensure,
|
||||
name => $service_name,
|
||||
@ -419,3 +447,4 @@ class neutron::server (
|
||||
tag => ['neutron-service', 'neutron-db-sync-service'],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -111,9 +111,6 @@ class neutron::server::notifications (
|
||||
|
||||
include ::neutron::deps
|
||||
|
||||
# Depend on the specified keystone_user resource, if it exists.
|
||||
Keystone_user <| title == 'nova' |> -> Class[neutron::server::notifications]
|
||||
|
||||
if is_service_default($tenant_id) and (! $tenant_name) {
|
||||
fail('You must provide either tenant_name or tenant_id.')
|
||||
}
|
||||
|
153
manifests/wsgi/apache.pp
Normal file
153
manifests/wsgi/apache.pp
Normal file
@ -0,0 +1,153 @@
|
||||
#
|
||||
# Copyright (C) 2017 Red Hat Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
#
|
||||
# Class to serve neutron API with apache mod_wsgi in place of neutron-api service.
|
||||
#
|
||||
# Serving neutron API from apache is the recommended way to go for production
|
||||
# because of limited performance for concurrent accesses when running eventlet.
|
||||
#
|
||||
# When using this class you should disable your neutron-api service.
|
||||
#
|
||||
# == Parameters
|
||||
#
|
||||
# [*servername*]
|
||||
# The servername for the virtualhost.
|
||||
# Optional. Defaults to $::fqdn
|
||||
#
|
||||
# [*port*]
|
||||
# The port.
|
||||
# Optional. Defaults to 9696
|
||||
#
|
||||
# [*bind_host*]
|
||||
# The host/ip address Apache will listen on.
|
||||
# Optional. Defaults to undef (listen on all ip addresses).
|
||||
#
|
||||
# [*path*]
|
||||
# The prefix for the endpoint.
|
||||
# Optional. Defaults to '/'
|
||||
#
|
||||
# [*ssl*]
|
||||
# Use ssl ? (boolean)
|
||||
# Optional. Defaults to true
|
||||
#
|
||||
# [*workers*]
|
||||
# Number of WSGI workers to spawn.
|
||||
# Optional. Defaults to 1
|
||||
#
|
||||
# [*priority*]
|
||||
# (optional) The priority for the vhost.
|
||||
# Defaults to '10'
|
||||
#
|
||||
# [*threads*]
|
||||
# (optional) The number of threads for the vhost.
|
||||
# Defaults to $::os_workers
|
||||
#
|
||||
# [*wsgi_process_display_name*]
|
||||
# (optional) Name of the WSGI process display-name.
|
||||
# Defaults to undef
|
||||
#
|
||||
# [*ssl_cert*]
|
||||
# [*ssl_key*]
|
||||
# [*ssl_chain*]
|
||||
# [*ssl_ca*]
|
||||
# [*ssl_crl_path*]
|
||||
# [*ssl_crl*]
|
||||
# [*ssl_certs_dir*]
|
||||
# apache::vhost ssl parameters.
|
||||
# Optional. Default to apache::vhost 'ssl_*' defaults.
|
||||
#
|
||||
# == Dependencies
|
||||
#
|
||||
# requires Class['apache'] & Class['neutron']
|
||||
#
|
||||
# == Examples
|
||||
#
|
||||
# include apache
|
||||
#
|
||||
# class { 'neutron::wsgi::apache': }
|
||||
#
|
||||
class neutron::wsgi::apache (
|
||||
$servername = $::fqdn,
|
||||
$port = 9696,
|
||||
$bind_host = undef,
|
||||
$path = '/',
|
||||
$ssl = true,
|
||||
$workers = $::os_workers,
|
||||
$ssl_cert = undef,
|
||||
$ssl_key = undef,
|
||||
$ssl_chain = undef,
|
||||
$ssl_ca = undef,
|
||||
$ssl_crl_path = undef,
|
||||
$ssl_crl = undef,
|
||||
$ssl_certs_dir = undef,
|
||||
$wsgi_process_display_name = undef,
|
||||
$threads = 1,
|
||||
$priority = '10',
|
||||
) {
|
||||
|
||||
include ::neutron::deps
|
||||
include ::neutron::params
|
||||
include ::apache
|
||||
include ::apache::mod::wsgi
|
||||
if $ssl {
|
||||
include ::apache::mod::ssl
|
||||
}
|
||||
|
||||
# The httpd package is untagged, but needs to have ordering enforced,
|
||||
# so handle it here rather than in the deps class.
|
||||
Anchor['neutron::install::begin']
|
||||
-> Package['httpd']
|
||||
-> Anchor['neutron::install::end']
|
||||
|
||||
# Configure apache during the config phase
|
||||
Anchor['neutron::config::begin']
|
||||
-> Apache::Vhost<||>
|
||||
~> Anchor['neutron::config::end']
|
||||
|
||||
# Start the service during the service phase
|
||||
Anchor['neutron::service::begin']
|
||||
-> Service['httpd']
|
||||
-> Anchor['neutron::service::end']
|
||||
|
||||
# Notify the service when config changes
|
||||
Anchor['neutron::config::end']
|
||||
~> Service['httpd']
|
||||
|
||||
::openstacklib::wsgi::apache { 'neutron_wsgi':
|
||||
bind_host => $bind_host,
|
||||
bind_port => $port,
|
||||
group => 'neutron',
|
||||
path => $path,
|
||||
priority => $priority,
|
||||
servername => $servername,
|
||||
ssl => $ssl,
|
||||
ssl_ca => $ssl_ca,
|
||||
ssl_cert => $ssl_cert,
|
||||
ssl_certs_dir => $ssl_certs_dir,
|
||||
ssl_chain => $ssl_chain,
|
||||
ssl_crl => $ssl_crl,
|
||||
ssl_crl_path => $ssl_crl_path,
|
||||
ssl_key => $ssl_key,
|
||||
threads => $threads,
|
||||
user => 'neutron',
|
||||
workers => $workers,
|
||||
wsgi_daemon_process => 'neutron',
|
||||
wsgi_process_display_name => $wsgi_process_display_name,
|
||||
wsgi_process_group => 'neutron',
|
||||
wsgi_script_dir => $::neutron::params::neutron_wsgi_script_path,
|
||||
wsgi_script_file => 'app',
|
||||
wsgi_script_source => $::neutron::params::neutron_wsgi_script_source,
|
||||
}
|
||||
}
|
6
releasenotes/notes/neutron-wsgi-1c0c06dddb8ac447.yaml
Normal file
6
releasenotes/notes/neutron-wsgi-1c0c06dddb8ac447.yaml
Normal file
@ -0,0 +1,6 @@
|
||||
---
|
||||
features:
|
||||
- |
|
||||
Neutron API can now be deployed in WSGI with Apache, like we support it
|
||||
for other modules. Switch neutron::server::service_name to 'httpd' and use
|
||||
neutron::wsgi::apache class to deploy it.
|
@ -61,7 +61,6 @@ describe 'neutron::keystone::auth' do
|
||||
}
|
||||
end
|
||||
|
||||
it { is_expected.to contain_keystone_endpoint('RegionOne/neutron::network').with_notify(['Service[neutron-server]']) }
|
||||
end
|
||||
|
||||
describe 'with endpoint URL parameters' do
|
||||
|
@ -66,7 +66,7 @@ describe 'neutron::server' do
|
||||
:name => platform_params[:server_service],
|
||||
:enable => true,
|
||||
:ensure => 'running',
|
||||
:tag => ['neutron-service', 'neutron-db-sync-service'],
|
||||
:tag => ['neutron-service', 'neutron-db-sync-service', 'neutron-server-eventlet'],
|
||||
)
|
||||
is_expected.to contain_service('neutron-server').that_subscribes_to('Anchor[neutron::service::begin]')
|
||||
is_expected.to contain_service('neutron-server').that_notifies('Anchor[neutron::service::end]')
|
||||
@ -140,15 +140,6 @@ describe 'neutron::server' do
|
||||
end
|
||||
end
|
||||
|
||||
context 'with custom service name' do
|
||||
before :each do
|
||||
params.merge!(:service_name => 'custom-service-name')
|
||||
end
|
||||
it 'should configure proper service name' do
|
||||
is_expected.to contain_service('neutron-server').with_name('custom-service-name')
|
||||
end
|
||||
end
|
||||
|
||||
context 'with state_path and lock_path parameters' do
|
||||
before :each do
|
||||
params.merge!(:state_path => 'state_path',
|
||||
@ -234,6 +225,44 @@ describe 'neutron::server' do
|
||||
|
||||
it { is_expected.to contain_neutron_config('oslo_middleware/enable_proxy_headers_parsing').with_value(true) }
|
||||
end
|
||||
|
||||
context 'when running neutron-api in wsgi' do
|
||||
before :each do
|
||||
params.merge!({ :service_name => 'httpd' })
|
||||
end
|
||||
|
||||
let :pre_condition do
|
||||
"class { 'neutron': rabbit_password => 'passw0rd' }
|
||||
include ::apache
|
||||
class { '::neutron::keystone::authtoken':
|
||||
password => 'passw0rd',
|
||||
}"
|
||||
end
|
||||
|
||||
it 'configures neutron-api service with Apache' do
|
||||
is_expected.to contain_service('neutron-server').with(
|
||||
:ensure => 'stopped',
|
||||
:name => platform_params[:server_service],
|
||||
:enable => false,
|
||||
:tag => ['neutron-service', 'neutron-db-sync-service'],
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when service_name is customized' do
|
||||
before :each do
|
||||
params.merge!({ :service_name => 'foobar' })
|
||||
end
|
||||
|
||||
it 'configures neutron-api service with custom name' do
|
||||
is_expected.to contain_service('neutron-server').with(
|
||||
:name => 'foobar',
|
||||
:enable => true,
|
||||
:ensure => 'running',
|
||||
:tag => ['neutron-service', 'neutron-db-sync-service'],
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
shared_examples_for 'VPNaaS, FWaaS and LBaaS package installation' do
|
||||
|
126
spec/classes/neutron_wsgi_apache_spec.rb
Normal file
126
spec/classes/neutron_wsgi_apache_spec.rb
Normal file
@ -0,0 +1,126 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe 'neutron::wsgi::apache' do
|
||||
|
||||
shared_examples_for 'apache serving neutron with mod_wsgi' do
|
||||
it { is_expected.to contain_service('httpd').with_name(platform_parameters[:httpd_service_name]) }
|
||||
it { is_expected.to contain_class('neutron::deps') }
|
||||
it { is_expected.to contain_class('neutron::params') }
|
||||
it { is_expected.to contain_class('apache') }
|
||||
it { is_expected.to contain_class('apache::mod::wsgi') }
|
||||
|
||||
describe 'with default parameters' do
|
||||
|
||||
it { is_expected.to contain_file("#{platform_parameters[:wsgi_script_path]}").with(
|
||||
'ensure' => 'directory',
|
||||
'owner' => 'neutron',
|
||||
'group' => 'neutron',
|
||||
'require' => 'Package[httpd]'
|
||||
)}
|
||||
|
||||
|
||||
it { is_expected.to contain_file('neutron_wsgi').with(
|
||||
'ensure' => 'file',
|
||||
'path' => "#{platform_parameters[:wsgi_script_path]}/app",
|
||||
'source' => platform_parameters[:wsgi_script_source],
|
||||
'owner' => 'neutron',
|
||||
'group' => 'neutron',
|
||||
'mode' => '0644'
|
||||
)}
|
||||
it { is_expected.to contain_file('neutron_wsgi').that_requires("File[#{platform_parameters[:wsgi_script_path]}]") }
|
||||
|
||||
it { is_expected.to contain_apache__vhost('neutron_wsgi').with(
|
||||
'servername' => 'some.host.tld',
|
||||
'ip' => nil,
|
||||
'port' => '9696',
|
||||
'docroot' => "#{platform_parameters[:wsgi_script_path]}",
|
||||
'docroot_owner' => 'neutron',
|
||||
'docroot_group' => 'neutron',
|
||||
'ssl' => 'true',
|
||||
'wsgi_daemon_process' => 'neutron',
|
||||
'wsgi_daemon_process_options' => {
|
||||
'user' => 'neutron',
|
||||
'group' => 'neutron',
|
||||
'processes' => '8',
|
||||
'threads' => '1',
|
||||
'display-name' => 'neutron_wsgi',
|
||||
},
|
||||
'wsgi_process_group' => 'neutron',
|
||||
'wsgi_script_aliases' => { '/' => "#{platform_parameters[:wsgi_script_path]}/app" },
|
||||
'require' => 'File[neutron_wsgi]'
|
||||
)}
|
||||
it { is_expected.to contain_concat("#{platform_parameters[:httpd_ports_file]}") }
|
||||
end
|
||||
|
||||
describe 'when overriding parameters using different ports' do
|
||||
let :params do
|
||||
{
|
||||
:servername => 'dummy.host',
|
||||
:bind_host => '10.42.51.1',
|
||||
:port => 12345,
|
||||
:ssl => false,
|
||||
:wsgi_process_display_name => 'neutron',
|
||||
:workers => 37,
|
||||
}
|
||||
end
|
||||
|
||||
it { is_expected.to contain_apache__vhost('neutron_wsgi').with(
|
||||
'servername' => 'dummy.host',
|
||||
'ip' => '10.42.51.1',
|
||||
'port' => '12345',
|
||||
'docroot' => "#{platform_parameters[:wsgi_script_path]}",
|
||||
'docroot_owner' => 'neutron',
|
||||
'docroot_group' => 'neutron',
|
||||
'ssl' => 'false',
|
||||
'wsgi_daemon_process' => 'neutron',
|
||||
'wsgi_daemon_process_options' => {
|
||||
'user' => 'neutron',
|
||||
'group' => 'neutron',
|
||||
'processes' => '37',
|
||||
'threads' => '1',
|
||||
'display-name' => 'neutron',
|
||||
},
|
||||
'wsgi_process_group' => 'neutron',
|
||||
'wsgi_script_aliases' => { '/' => "#{platform_parameters[:wsgi_script_path]}/app" },
|
||||
'require' => 'File[neutron_wsgi]'
|
||||
)}
|
||||
|
||||
it { is_expected.to contain_concat("#{platform_parameters[:httpd_ports_file]}") }
|
||||
end
|
||||
end
|
||||
|
||||
on_supported_os({
|
||||
:supported_os => OSDefaults.get_supported_os
|
||||
}).each do |os,facts|
|
||||
context "on #{os}" do
|
||||
let (:facts) do
|
||||
facts.merge!(OSDefaults.get_facts({
|
||||
:os_workers => 8,
|
||||
:concat_basedir => '/var/lib/puppet/concat',
|
||||
:fqdn => 'some.host.tld'
|
||||
}))
|
||||
end
|
||||
|
||||
let(:platform_parameters) do
|
||||
case facts[:osfamily]
|
||||
when 'Debian'
|
||||
{
|
||||
:httpd_service_name => 'apache2',
|
||||
:httpd_ports_file => '/etc/apache2/ports.conf',
|
||||
:wsgi_script_path => '/usr/lib/cgi-bin/neutron',
|
||||
:wsgi_script_source => '/usr/bin/neutron-api'
|
||||
}
|
||||
when 'RedHat'
|
||||
{
|
||||
:httpd_service_name => 'httpd',
|
||||
:httpd_ports_file => '/etc/httpd/conf/ports.conf',
|
||||
:wsgi_script_path => '/var/www/cgi-bin/neutron',
|
||||
:wsgi_script_source => '/usr/bin/neutron-api'
|
||||
}
|
||||
|
||||
end
|
||||
end
|
||||
it_configures 'apache serving neutron with mod_wsgi'
|
||||
end
|
||||
end
|
||||
end
|
Loading…
Reference in New Issue
Block a user