From be76a4fbb5578402b2a60c5fb7f95ceaaddf0600 Mon Sep 17 00:00:00 2001 From: Emilien Macchi Date: Fri, 2 Dec 2016 12:15:37 -0500 Subject: [PATCH] Nova Placement API support - Nova Placement API deployment in WSGI with Apache by using nova::wsgi::apache_placement. - Keystones resources support for Nova Placement API by using nova::keystone::auth_placement. - Allow to configure [placement] section in nova.conf by using nova::placement. - nova::wsgi::apache is deprecated in favor of nova::wsgi::apache_api. Notes: - This service will be required in the future. See docs.openstack.org/developer/nova/placement.html - Disable testing on Ubuntu, the package is broken and not idempotent. Change-Id: I7f9bc831005029f12d4259b411b58c0319c2a043 --- manifests/keystone/auth_placement.pp | 93 +++++++++ manifests/params.pp | 4 + manifests/placement.pp | 69 +++++++ manifests/wsgi/apache.pp | 50 +++-- manifests/wsgi/apache_api.pp | 133 +++++++++++++ manifests/wsgi/apache_placement.pp | 144 ++++++++++++++ .../nova-placement-30566167309fd124.yaml | 7 + spec/acceptance/nova_wsgi_apache_spec.rb | 21 ++- .../nova_keystone_auth_placement_spec.rb | 161 ++++++++++++++++ spec/classes/nova_placement_spec.rb | 58 ++++++ spec/classes/nova_wsgi_apache_api_spec.rb | 168 +++++++++++++++++ .../nova_wsgi_apache_placement_spec.rb | 176 ++++++++++++++++++ spec/classes/nova_wsgi_apache_spec.rb | 31 +-- 13 files changed, 1073 insertions(+), 42 deletions(-) create mode 100644 manifests/keystone/auth_placement.pp create mode 100644 manifests/placement.pp create mode 100644 manifests/wsgi/apache_api.pp create mode 100644 manifests/wsgi/apache_placement.pp create mode 100644 releasenotes/notes/nova-placement-30566167309fd124.yaml create mode 100644 spec/classes/nova_keystone_auth_placement_spec.rb create mode 100644 spec/classes/nova_placement_spec.rb create mode 100644 spec/classes/nova_wsgi_apache_api_spec.rb create mode 100644 spec/classes/nova_wsgi_apache_placement_spec.rb diff --git a/manifests/keystone/auth_placement.pp b/manifests/keystone/auth_placement.pp new file mode 100644 index 000000000..8b26d6ad5 --- /dev/null +++ b/manifests/keystone/auth_placement.pp @@ -0,0 +1,93 @@ +# == Class: nova::keystone::auth_placement +# +# Creates nova placement api endpoints and service account in keystone +# +# === Parameters: +# +# [*password*] +# Password to create for the service user +# +# [*auth_name*] +# (optional) The name of the placement service user +# Defaults to 'placement' +# +# [*service_name*] +# (optional) Name of the service. +# Defaults to 'placement'. +# +# [*service_description*] +# (optional) Description for keystone service. +# Defaults to 'Openstack Placement Service'. +# +# [*public_url*] +# (optional) The endpoint's public url. +# Defaults to 'http://127.0.0.1:8778' +# +# [*internal_url*] +# (optional) The endpoint's internal url. +# Defaults to 'http://127.0.0.1:8778' +# +# [*admin_url*] +# (optional) The endpoint's admin url. +# Defaults to 'http://127.0.0.1:8778' +# +# [*region*] +# (optional) The region in which to place the endpoints +# Defaults to 'RegionOne' +# +# [*tenant*] +# (optional) The tenant to use for the nova service user +# Defaults to 'services' +# +# [*email*] +# (optional) The email address for the nova service user +# Defaults to 'placement@localhost' +# +# [*configure_endpoint*] +# (optional) Whether to create the endpoint. +# Defaults to true +# +# [*configure_user*] +# (optional) Whether to create the service user. +# Defaults to true +# +# [*configure_user_role*] +# (optional) Whether to configure the admin role for the service user. +# Defaults to true +# +class nova::keystone::auth_placement( + $password, + $auth_name = 'placement', + $service_name = 'placement', + $service_description = 'Openstack Placement Service', + $region = 'RegionOne', + $tenant = 'services', + $email = 'placement@localhost', + $public_url = 'http://127.0.0.1:8778', + $internal_url = 'http://127.0.0.1:8778', + $admin_url = 'http://127.0.0.1:8778', + $configure_endpoint = true, + $configure_user = true, + $configure_user_role = true, +) { + + include ::nova::deps + + keystone::resource::service_identity { 'placement': + configure_user => $configure_user, + configure_user_role => $configure_user_role, + configure_endpoint => $configure_endpoint, + service_type => 'placement', + service_description => $service_description, + service_name => $service_name, + region => $region, + auth_name => $auth_name, + password => $password, + email => $email, + tenant => $tenant, + public_url => $public_url, + admin_url => $admin_url, + internal_url => $internal_url, + } + +} diff --git a/manifests/params.pp b/manifests/params.pp index b3787d426..5480b4420 100644 --- a/manifests/params.pp +++ b/manifests/params.pp @@ -9,6 +9,7 @@ class nova::params { 'RedHat': { # package names $api_package_name = 'openstack-nova-api' + $placement_package_name = 'openstack-nova-placement-api' $cells_package_name = 'openstack-nova-cells' $cert_package_name = 'openstack-nova-cert' $common_package_name = 'openstack-nova-common' @@ -51,6 +52,7 @@ class nova::params { $nova_log_group = 'nova' $nova_wsgi_script_path = '/var/www/cgi-bin/nova' $nova_api_wsgi_script_source = '/usr/lib/python2.7/site-packages/nova/wsgi/nova-api.py' + $placement_wsgi_script_source = '/usr/bin/nova-placement-api' case $::operatingsystem { 'RedHat', 'CentOS', 'Scientific', 'OracleLinux': { if (versioncmp($::operatingsystemmajrelease, '7') < 0) { @@ -75,6 +77,7 @@ class nova::params { 'Debian': { # package names $api_package_name = 'nova-api' + $placement_package_name = 'nova-placement-api' $cells_package_name = 'nova-cells' $cert_package_name = 'nova-cert' $common_package_name = 'nova-common' @@ -106,6 +109,7 @@ class nova::params { $nova_log_group = 'adm' $nova_wsgi_script_path = '/usr/lib/cgi-bin/nova' $nova_api_wsgi_script_source = '/usr/lib/python2.7/dist-packages/nova/wsgi/nova-api.py' + $placement_wsgi_script_source = '/usr/bin/nova-placement-api' # debian specific nova config $root_helper = 'sudo nova-rootwrap' $lock_path = '/var/lock/nova' diff --git a/manifests/placement.pp b/manifests/placement.pp new file mode 100644 index 000000000..15003e516 --- /dev/null +++ b/manifests/placement.pp @@ -0,0 +1,69 @@ +# == Class: nova::placement +# +# Class for configuring [placement] section in nova.conf. +# +# === Parameters: +# +# [*password*] +# (required) Password for connecting to Nova Placement API service in +# admin context through the OpenStack Identity service. +# +# [*auth_type*] +# Name of the auth type to load (string value) +# Defaults to 'password' +# +# [*project_name*] +# (optional) Project name for connecting to Nova Placement API service in +# admin context through the OpenStack Identity service. +# Defaults to 'services' +# +# [*project_domain_name*] +# (optional) Project Domain name for connecting to Nova Placement API service in +# admin context through the OpenStack Identity service. +# Defaults to 'Default' +# +# [*user_domain_name*] +# (optional) User Domain name for connecting to Nova Placement API service in +# admin context through the OpenStack Identity service. +# Defaults to 'Default' +# +# [*os_region_name*] +# (optional) Region name for connecting to Nova Placement API service in admin context +# through the OpenStack Identity service. +# Defaults to 'RegionOne' +# +# [*username*] +# (optional) Username for connecting to Nova Placement API service in admin context +# through the OpenStack Identity service. +# Defaults to 'placement' +# +# [*auth_url*] +# (optional) Points to the OpenStack Identity server IP and port. +# This is the Identity (keystone) admin API server IP and port value, +# and not the Identity service API IP and port. +# Defaults to 'http://127.0.0.1:35357/v3' +# +class nova::placement( + $password = false, + $auth_type = 'password', + $auth_url = 'http://127.0.0.1:35357/v3', + $os_region_name = 'RegionOne', + $project_domain_name = 'Default', + $project_name = 'services', + $user_domain_name = 'Default', + $username = 'placement', +) { + include ::nova::deps + + nova_config { + 'placement/auth_type': value => $auth_type; + 'placement/auth_url': value => $auth_url; + 'placement/password': value => $password, secret => true; + 'placement/project_domain_name': value => $project_domain_name; + 'placement/project_name': value => $project_name; + 'placement/user_domain_name': value => $user_domain_name; + 'placement/username': value => $username; + 'placement/os_region_name': value => $os_region_name; + } + +} diff --git a/manifests/wsgi/apache.pp b/manifests/wsgi/apache.pp index 99e67c008..201e4ccef 100644 --- a/manifests/wsgi/apache.pp +++ b/manifests/wsgi/apache.pp @@ -15,7 +15,8 @@ # License for the specific language governing permissions and limitations # under the License. # -# Class to serve Nova API and EC2 with apache mod_wsgi in place of nova-api and nova-api-ec2 services. +# Deprecated Class to serve Nova API and EC2 with apache mod_wsgi in place of nova-api and nova-api-ec2 services. +# Use ::nova::wsgi::apache::api. # # Serving Nova API and Nova API EC2 from apache is the recommended way to go for production # because of limited performance for concurrent accesses. @@ -54,7 +55,7 @@ # # [*threads*] # (optional) The number of threads for the vhost. -# Defaults to $::processorcount +# Defaults to $::os_workers # # [*ssl_cert*] # [*ssl_key*] @@ -76,6 +77,8 @@ # # class { 'nova::wsgi::apache': } # +# Note: we can't transform this class in a define for backward compatibility. +# though this class might become a define in the future. class nova::wsgi::apache ( $servername = $::fqdn, $api_port = 8774, @@ -90,7 +93,7 @@ class nova::wsgi::apache ( $ssl_crl_path = undef, $ssl_crl = undef, $ssl_certs_dir = undef, - $threads = $::processorcount, + $threads = $::os_workers, $priority = '10', ) { @@ -105,29 +108,24 @@ class nova::wsgi::apache ( fail('::nova::api class must be declared in composition layer.') } - ::openstacklib::wsgi::apache { 'nova_api_wsgi': - bind_host => $bind_host, - bind_port => $api_port, - group => 'nova', - 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 => 'nova', - workers => $workers, - wsgi_daemon_process => 'nova-api', - wsgi_process_group => 'nova-api', - wsgi_script_dir => $::nova::params::nova_wsgi_script_path, - wsgi_script_file => 'nova-api', - wsgi_script_source => $::nova::params::nova_api_wsgi_script_source, + warning('nova::wsgi::apache is deprecated and will be removed in a future release, please use nova::wsgi::apache::api') + + class { '::nova::wsgi::apache_api': + servername => $servername, + api_port => $api_port, + bind_host => $bind_host, + path => $path, + ssl => $ssl, + workers => $workers, + 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, + threads => $threads, + priority => $priority, } } diff --git a/manifests/wsgi/apache_api.pp b/manifests/wsgi/apache_api.pp new file mode 100644 index 000000000..bc7fa258a --- /dev/null +++ b/manifests/wsgi/apache_api.pp @@ -0,0 +1,133 @@ +# +# Copyright (C) 2015 eNovance SAS +# +# Author: Emilien Macchi +# +# 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 Nova API and EC2 with apache mod_wsgi in place of nova-api and nova-api-ec2 services. +# +# Serving Nova API and Nova API EC2 from apache is the recommended way to go for production +# because of limited performance for concurrent accesses. +# +# When using this class you should disable your nova-api and nova-api-ec2 service. +# +# == Parameters +# +# [*servername*] +# The servername for the virtualhost. +# Optional. Defaults to $::fqdn +# +# [*api_port*] +# The port for Nova API service. +# Optional. Defaults to 8774 +# +# [*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 +# +# [*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['nova'] & Class['nova::api'] +# +# == Examples +# +# include apache +# +# class { 'nova::wsgi::apache': } +# +class nova::wsgi::apache_api ( + $servername = $::fqdn, + $api_port = 8774, + $bind_host = undef, + $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 = $::os_workers, + $priority = '10', +) { + + include ::nova::params + include ::apache + include ::apache::mod::wsgi + if $ssl { + include ::apache::mod::ssl + } + + if ! defined(Class[::nova::api]) { + fail('::nova::api class must be declared in composition layer.') + } + + ::openstacklib::wsgi::apache { 'nova_api_wsgi': + bind_host => $bind_host, + bind_port => $api_port, + group => 'nova', + 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 => 'nova', + workers => $workers, + wsgi_daemon_process => 'nova-api', + wsgi_process_group => 'nova-api', + wsgi_script_dir => $::nova::params::nova_wsgi_script_path, + wsgi_script_file => 'nova-api', + wsgi_script_source => $::nova::params::nova_api_wsgi_script_source, + } + +} diff --git a/manifests/wsgi/apache_placement.pp b/manifests/wsgi/apache_placement.pp new file mode 100644 index 000000000..17078f531 --- /dev/null +++ b/manifests/wsgi/apache_placement.pp @@ -0,0 +1,144 @@ +# +# Copyright (C) 2015 eNovance SAS +# +# Author: Emilien Macchi +# +# 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 Nova Placement API service. + +# Serving Nova Placement API from apache is the recommended way to go for production +# because of limited performance for concurrent accesses. +# +# == Parameters +# +# [*servername*] +# The servername for the virtualhost. +# Optional. Defaults to $::fqdn +# +# [*api_port*] +# The port for Novai Placement API service. +# Optional. Defaults to 8778 +# +# [*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 +# +# [*ensure_package*] +# (optional) Control the ensure parameter for the Nova Placement API package ressource. +# Defaults to 'present' +# +# [*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['nova'] & Class['nova::api'] +# +# == Examples +# +# include apache +# +# class { 'nova::wsgi::apache': } +# +class nova::wsgi::apache_placement ( + $servername = $::fqdn, + $api_port = 8778, + $bind_host = undef, + $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 = $::os_workers, + $priority = '10', + $ensure_package = 'present', +) { + + include ::nova::params + include ::apache + include ::apache::mod::wsgi + if $ssl { + include ::apache::mod::ssl + } + + if ! defined(Class[::nova::api]) { + fail('::nova::api class must be declared in composition layer.') + } + + nova::generic_service { 'placement-api': + service_name => false, + package_name => $::nova::params::placement_package_name, + ensure_package => $ensure_package, + } + # Ubuntu requires nova-placement-api to be installed before apache to find wsgi script + Package<| title == 'nova-placement-api'|> -> Package<| title == 'httpd'|> + + ::openstacklib::wsgi::apache { 'placement_wsgi': + bind_host => $bind_host, + bind_port => $api_port, + group => 'nova', + 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 => 'nova', + workers => $workers, + wsgi_daemon_process => 'placement-api', + wsgi_process_group => 'placement-api', + wsgi_script_dir => $::nova::params::nova_wsgi_script_path, + wsgi_script_file => 'nova-placement-api', + wsgi_script_source => $::nova::params::placement_wsgi_script_source, + } + +} diff --git a/releasenotes/notes/nova-placement-30566167309fd124.yaml b/releasenotes/notes/nova-placement-30566167309fd124.yaml new file mode 100644 index 000000000..6fe5ff3b3 --- /dev/null +++ b/releasenotes/notes/nova-placement-30566167309fd124.yaml @@ -0,0 +1,7 @@ +--- +features: + - Nova Placement API deployment in WSGI with Apache by using nova::wsgi::apache_placement. + - Keystone resources support for Nova Placement API by using nova::keystone::auth_placement. + - Allow to configure [placement] section in nova.conf by using nova::placement. +deprecations: + - nova::wsgi::apache is deprecated in favor of nova::wsgi::apache_api. diff --git a/spec/acceptance/nova_wsgi_apache_spec.rb b/spec/acceptance/nova_wsgi_apache_spec.rb index 76d18df92..c5365992e 100644 --- a/spec/acceptance/nova_wsgi_apache_spec.rb +++ b/spec/acceptance/nova_wsgi_apache_spec.rb @@ -45,6 +45,9 @@ describe 'basic nova' do class { '::nova::keystone::auth': password => 'a_big_secret', } + class { '::nova::keystone::auth_placement': + password => 'a_big_secret', + } class { '::nova::keystone::authtoken': password => 'a_big_secret', } @@ -52,9 +55,19 @@ describe 'basic nova' do service_name => 'httpd', } include ::apache - class { '::nova::wsgi::apache': + class { '::nova::wsgi::apache_api': ssl => false, } + # The Ubuntu package is now broken, it tries to run the app with systemd. + # Until it's fixed, let's test it on Red Hat only. + if $::osfamily == 'RedHat' { + class { '::nova::wsgi::apache_placement': + ssl => false, + } + class { '::nova::placement': + password => 'a_big_secret', + } + } class { '::nova::cert': } class { '::nova::client': } class { '::nova::conductor': } @@ -106,6 +119,12 @@ describe 'basic nova' do it { is_expected.to be_listening } end + if os[:family].casecmp('RedHat') == 0 + describe port(8778) do + it { is_expected.to be_listening } + end + end + describe port(6080) do it { is_expected.to be_listening } end diff --git a/spec/classes/nova_keystone_auth_placement_spec.rb b/spec/classes/nova_keystone_auth_placement_spec.rb new file mode 100644 index 000000000..efad40e59 --- /dev/null +++ b/spec/classes/nova_keystone_auth_placement_spec.rb @@ -0,0 +1,161 @@ +require 'spec_helper' + +describe 'nova::keystone::auth_placement' do + + let :params do + {:password => 'placement_password'} + end + + let :default_params do + { :auth_name => 'placement', + :service_name => 'placement', + :region => 'RegionOne', + :tenant => 'services', + :email => 'placement@localhost', + :public_url => 'http://127.0.0.1:8778', + :internal_url => 'http://127.0.0.1:8778', + :admin_url => 'http://127.0.0.1:8778' } + end + + context 'with default parameters' do + + it { is_expected.to contain_keystone_user('placement').with( + :ensure => 'present', + :password => 'placement_password' + ) } + + it { is_expected.to contain_keystone_user_role('placement@services').with( + :ensure => 'present', + :roles => ['admin'] + )} + + it { is_expected.to contain_keystone_service('placement::placement').with( + :ensure => 'present', + :description => 'Openstack Placement Service' + )} + + it { is_expected.to contain_keystone_endpoint('RegionOne/placement::placement').with( + :ensure => 'present', + :public_url => 'http://127.0.0.1:8778', + :admin_url => 'http://127.0.0.1:8778', + :internal_url => 'http://127.0.0.1:8778' + )} + + end + + context 'when setting auth name' do + before do + params.merge!( :auth_name => 'foo' ) + end + + it { is_expected.to contain_keystone_user('foo').with( + :ensure => 'present', + :password => 'placement_password' + ) } + + it { is_expected.to contain_keystone_user_role('foo@services').with( + :ensure => 'present', + :roles => ['admin'] + )} + + it { is_expected.to contain_keystone_service('placement::placement').with( + :ensure => 'present', + :description => 'Openstack Placement Service' + )} + + end + + context 'when overriding endpoint parameters' do + before do + params.merge!( + :region => 'RegionTwo', + :public_url => 'https://10.0.0.1:9778', + :internal_url => 'https://10.0.0.3:9778', + :admin_url => 'https://10.0.0.2:9778', + ) + end + + it { is_expected.to contain_keystone_endpoint('RegionTwo/placement::placement').with( + :ensure => 'present', + :public_url => params[:public_url], + :internal_url => params[:internal_url], + :admin_url => params[:admin_url] + )} + + end + + describe 'when disabling endpoint configuration' do + before do + params.merge!( :configure_endpoint => false ) + end + + it { is_expected.to_not contain_keystone_endpoint('RegionOne/placement::placement') } + end + + describe 'when disabling user configuration' do + before do + params.merge!( :configure_user => false ) + end + + it { is_expected.to_not contain_keystone_user('placement') } + it { is_expected.to contain_keystone_user_role('placement@services') } + it { is_expected.to contain_keystone_service('placement::placement').with( + :ensure => 'present', + :description => 'Openstack Placement Service' + )} + end + + describe 'when disabling user and user role configuration' do + let :params do + { + :configure_user => false, + :configure_user_role => false, + :password => 'placement_password' + } + end + + it { is_expected.to_not contain_keystone_user('placement') } + it { is_expected.to_not contain_keystone_user_role('placement@services') } + it { is_expected.to contain_keystone_service('placement::placement').with( + :ensure => 'present', + :description => 'Openstack Placement Service' + )} + end + + describe 'when configuring nova-placement and the keystone endpoint' do + let :pre_condition do + "class { '::nova::keystone::authtoken': + password => 'secrete', + } + class { 'nova::api':} + include nova" + end + + let :facts do + @default_facts.merge({ :osfamily => "Debian"}) + end + + let :params do + { + :password => 'test' + } + end + end + + describe 'when overriding service names' do + + let :params do + { + :service_name => 'nova_service', + :password => 'placement_password' + } + end + + it { is_expected.to contain_keystone_user('placement') } + it { is_expected.to contain_keystone_user_role('placement@services') } + it { is_expected.to contain_keystone_service('nova_service::placement') } + it { is_expected.to contain_keystone_endpoint('RegionOne/nova_service::placement') } + + end + +end diff --git a/spec/classes/nova_placement_spec.rb b/spec/classes/nova_placement_spec.rb new file mode 100644 index 000000000..14eb678f5 --- /dev/null +++ b/spec/classes/nova_placement_spec.rb @@ -0,0 +1,58 @@ +require 'spec_helper' + +describe 'nova::placement' do + + let :default_params do + { :auth_type => 'password', + :project_name => 'services', + :project_domain_name => 'Default', + :os_region_name => 'RegionOne', + :username => 'placement', + :user_domain_name => 'Default', + :auth_url => 'http://127.0.0.1:35357/v3', + } + end + + let :params do + { :password => 's3cr3t' } + end + + context 'with required parameters' do + it 'configures [placement] parameters in nova.conf' do + is_expected.to contain_nova_config('placement/password').with_value(params[:password]).with_secret(true) + is_expected.to contain_nova_config('placement/auth_type').with_value(default_params[:auth_type]) + is_expected.to contain_nova_config('placement/project_name').with_value(default_params[:project_name]) + is_expected.to contain_nova_config('placement/project_domain_name').with_value(default_params[:project_domain_name]) + is_expected.to contain_nova_config('placement/os_region_name').with_value(default_params[:os_region_name]) + is_expected.to contain_nova_config('placement/username').with_value(default_params[:username]) + is_expected.to contain_nova_config('placement/user_domain_name').with_value(default_params[:user_domain_name]) + is_expected.to contain_nova_config('placement/auth_url').with_value(default_params[:auth_url]) + end + end + + context 'when overriding class parameters' do + before do + params.merge!( + :auth_type => 'password', + :project_name => 'service', + :project_domain_name => 'default', + :os_region_name => 'RegionTwo', + :username => 'placement2', + :user_domain_name => 'default', + :auth_url => 'https://127.0.0.1:35357/v3', + ) + end + + it 'configures [placement] parameters in nova.conf' do + is_expected.to contain_nova_config('placement/password').with_value(params[:password]).with_secret(true) + is_expected.to contain_nova_config('placement/auth_type').with_value(params[:auth_type]) + is_expected.to contain_nova_config('placement/project_name').with_value(params[:project_name]) + is_expected.to contain_nova_config('placement/project_domain_name').with_value(params[:project_domain_name]) + is_expected.to contain_nova_config('placement/os_region_name').with_value(params[:os_region_name]) + is_expected.to contain_nova_config('placement/username').with_value(params[:username]) + is_expected.to contain_nova_config('placement/user_domain_name').with_value(params[:user_domain_name]) + is_expected.to contain_nova_config('placement/auth_url').with_value(params[:auth_url]) + end + end + +end diff --git a/spec/classes/nova_wsgi_apache_api_spec.rb b/spec/classes/nova_wsgi_apache_api_spec.rb new file mode 100644 index 000000000..e59a28fe6 --- /dev/null +++ b/spec/classes/nova_wsgi_apache_api_spec.rb @@ -0,0 +1,168 @@ +require 'spec_helper' + +describe 'nova::wsgi::apache_api' do + + let :global_facts do + @default_facts.merge({ + :processorcount => 42, + :concat_basedir => '/var/lib/puppet/concat', + :fqdn => 'some.host.tld' + }) + end + + let :pre_condition do + "include nova + class { '::nova::keystone::authtoken': + password => 'secrete', + } + class { '::nova::api': + service_name => 'httpd', + }" + end + + shared_examples_for 'apache serving nova with mod_wsgi' do + it { is_expected.to contain_service('httpd').with_name(platform_params[:httpd_service_name]) } + it { is_expected.to contain_class('nova::params') } + it { is_expected.to contain_class('apache') } + it { is_expected.to contain_class('apache::mod::wsgi') } + + describe 'with default parameters' do + + let :pre_condition do + "include nova + class { '::nova::keystone::authtoken': + password => 'secrete', + } + class { '::nova::api': + service_name => 'httpd', + }" + end + + it { is_expected.to contain_file("#{platform_params[:wsgi_script_path]}").with( + 'ensure' => 'directory', + 'owner' => 'nova', + 'group' => 'nova', + 'require' => 'Package[httpd]' + )} + + + it { is_expected.to contain_file('nova_api_wsgi').with( + 'ensure' => 'file', + 'path' => "#{platform_params[:wsgi_script_path]}/nova-api", + 'source' => platform_params[:api_wsgi_script_source], + 'owner' => 'nova', + 'group' => 'nova', + 'mode' => '0644' + )} + it { is_expected.to contain_file('nova_api_wsgi').that_requires("File[#{platform_params[:wsgi_script_path]}]") } + + it { is_expected.to contain_apache__vhost('nova_api_wsgi').with( + 'servername' => 'some.host.tld', + 'ip' => nil, + 'port' => '8774', + 'docroot' => "#{platform_params[:wsgi_script_path]}", + 'docroot_owner' => 'nova', + 'docroot_group' => 'nova', + 'ssl' => 'true', + 'wsgi_daemon_process' => 'nova-api', + 'wsgi_process_group' => 'nova-api', + 'wsgi_script_aliases' => { '/' => "#{platform_params[:wsgi_script_path]}/nova-api" }, + 'require' => 'File[nova_api_wsgi]' + )} + it { is_expected.to contain_concat("#{platform_params[:httpd_ports_file]}") } + + it { is_expected.to contain_file('nova_api_wsgi').with( + 'ensure' => 'file', + 'path' => "#{platform_params[:wsgi_script_path]}/nova-api", + 'source' => platform_params[:api_wsgi_script_source], + 'owner' => 'nova', + 'group' => 'nova', + 'mode' => '0644' + )} + it { is_expected.to contain_file('nova_api_wsgi').that_requires("File[#{platform_params[:wsgi_script_path]}]") } + + it { is_expected.to contain_concat("#{platform_params[:httpd_ports_file]}") } + end + + describe 'when overriding parameters using different ports' do + let :pre_condition do + "include nova + class { '::nova::keystone::authtoken': + password => 'secrete', + } + class { '::nova::api': + service_name => 'httpd', + }" + end + + let :params do + { + :servername => 'dummy.host', + :bind_host => '10.42.51.1', + :api_port => 12345, + :ssl => false, + :workers => 37, + } + end + + it { is_expected.to contain_apache__vhost('nova_api_wsgi').with( + 'servername' => 'dummy.host', + 'ip' => '10.42.51.1', + 'port' => '12345', + 'docroot' => "#{platform_params[:wsgi_script_path]}", + 'docroot_owner' => 'nova', + 'docroot_group' => 'nova', + 'ssl' => 'false', + 'wsgi_daemon_process' => 'nova-api', + 'wsgi_process_group' => 'nova-api', + 'wsgi_script_aliases' => { '/' => "#{platform_params[:wsgi_script_path]}/nova-api" }, + 'require' => 'File[nova_api_wsgi]' + )} + end + + describe 'when ::nova::api is missing in the composition layer' do + + let :pre_condition do + "include nova" + end + + it { is_expected.to raise_error Puppet::Error, /::nova::api class must be declared in composition layer./ } + 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 => 42, + :concat_basedir => '/var/lib/puppet/concat', + :fqdn => 'some.host.tld', + })) + end + + let(:platform_params) do + case facts[:osfamily] + when 'Debian' + { + :httpd_service_name => 'apache2', + :httpd_ports_file => '/etc/apache2/ports.conf', + :wsgi_script_path => '/usr/lib/cgi-bin/nova', + :api_wsgi_script_source => '/usr/lib/python2.7/dist-packages/nova/wsgi/nova-api.py', + } + when 'RedHat' + { + :httpd_service_name => 'httpd', + :httpd_ports_file => '/etc/httpd/conf/ports.conf', + :wsgi_script_path => '/var/www/cgi-bin/nova', + :api_wsgi_script_source => '/usr/lib/python2.7/site-packages/nova/wsgi/nova-api.py', + } + end + end + + it_behaves_like 'apache serving nova with mod_wsgi' + end + end +end diff --git a/spec/classes/nova_wsgi_apache_placement_spec.rb b/spec/classes/nova_wsgi_apache_placement_spec.rb new file mode 100644 index 000000000..4d4fb7932 --- /dev/null +++ b/spec/classes/nova_wsgi_apache_placement_spec.rb @@ -0,0 +1,176 @@ +require 'spec_helper' + +describe 'nova::wsgi::apache_placement' do + + let :global_facts do + @default_facts.merge({ + :processorcount => 42, + :concat_basedir => '/var/lib/puppet/concat', + :fqdn => 'some.host.tld' + }) + end + + let :pre_condition do + "include nova + class { '::nova::keystone::authtoken': + password => 'secrete', + } + class { '::nova::api': + service_name => 'httpd', + }" + end + + shared_examples_for 'apache serving nova with mod_wsgi' do + it { is_expected.to contain_service('httpd').with_name(platform_params[:httpd_service_name]) } + it { is_expected.to contain_class('nova::params') } + it { is_expected.to contain_class('apache') } + it { is_expected.to contain_class('apache::mod::wsgi') } + + describe 'with default parameters' do + + let :pre_condition do + "include nova + class { '::nova::keystone::authtoken': + password => 'secrete', + } + class { '::nova::api': + service_name => 'httpd', + }" + end + + it { is_expected.to contain_package('nova-placement-api').with( + :name => "#{platform_params[:placement_package_name]}", + :ensure => 'present', + :tag => ['openstack', 'nova-package'], + )} + + it { is_expected.to contain_file("#{platform_params[:wsgi_script_path]}").with( + 'ensure' => 'directory', + 'owner' => 'nova', + 'group' => 'nova', + 'require' => 'Package[httpd]' + )} + + + it { is_expected.to contain_file('placement_wsgi').with( + 'ensure' => 'file', + 'path' => "#{platform_params[:wsgi_script_path]}/nova-placement-api", + 'source' => platform_params[:placement_wsgi_script_source], + 'owner' => 'nova', + 'group' => 'nova', + 'mode' => '0644' + )} + it { is_expected.to contain_file('placement_wsgi').that_requires("File[#{platform_params[:wsgi_script_path]}]") } + + it { is_expected.to contain_apache__vhost('placement_wsgi').with( + 'servername' => 'some.host.tld', + 'ip' => nil, + 'port' => '8778', + 'docroot' => "#{platform_params[:wsgi_script_path]}", + 'docroot_owner' => 'nova', + 'docroot_group' => 'nova', + 'ssl' => 'true', + 'wsgi_daemon_process' => 'placement-api', + 'wsgi_process_group' => 'placement-api', + 'wsgi_script_aliases' => { '/' => "#{platform_params[:wsgi_script_path]}/nova-placement-api" }, + 'require' => 'File[placement_wsgi]' + )} + it { is_expected.to contain_concat("#{platform_params[:httpd_ports_file]}") } + + it { is_expected.to contain_file('placement_wsgi').with( + 'ensure' => 'file', + 'path' => "#{platform_params[:wsgi_script_path]}/nova-placement-api", + 'source' => platform_params[:placement_wsgi_script_source], + 'owner' => 'nova', + 'group' => 'nova', + 'mode' => '0644' + )} + it { is_expected.to contain_file('placement_wsgi').that_requires("File[#{platform_params[:wsgi_script_path]}]") } + + it { is_expected.to contain_concat("#{platform_params[:httpd_ports_file]}") } + end + + describe 'when overriding parameters using different ports' do + let :pre_condition do + "include nova + class { '::nova::keystone::authtoken': + password => 'secrete', + } + class { '::nova::api': + service_name => 'httpd', + }" + end + + let :params do + { + :servername => 'dummy.host', + :bind_host => '10.42.51.1', + :api_port => 12345, + :ssl => false, + :workers => 37, + } + end + + it { is_expected.to contain_apache__vhost('placement_wsgi').with( + 'servername' => 'dummy.host', + 'ip' => '10.42.51.1', + 'port' => '12345', + 'docroot' => "#{platform_params[:wsgi_script_path]}", + 'docroot_owner' => 'nova', + 'docroot_group' => 'nova', + 'ssl' => 'false', + 'wsgi_daemon_process' => 'placement-api', + 'wsgi_process_group' => 'placement-api', + 'wsgi_script_aliases' => { '/' => "#{platform_params[:wsgi_script_path]}/nova-placement-api" }, + 'require' => 'File[placement_wsgi]' + )} + end + + describe 'when ::nova::api is missing in the composition layer' do + + let :pre_condition do + "include nova" + end + + it { is_expected.to raise_error Puppet::Error, /::nova::api class must be declared in composition layer./ } + 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 => 42, + :concat_basedir => '/var/lib/puppet/concat', + :fqdn => 'some.host.tld', + })) + end + + let(:platform_params) do + case facts[:osfamily] + when 'Debian' + { + :httpd_service_name => 'apache2', + :httpd_ports_file => '/etc/apache2/ports.conf', + :wsgi_script_path => '/usr/lib/cgi-bin/nova', + :placement_wsgi_script_source => '/usr/bin/nova-placement-api', + :placement_package_name => 'nova-placement-api', + } + when 'RedHat' + { + :httpd_service_name => 'httpd', + :httpd_ports_file => '/etc/httpd/conf/ports.conf', + :wsgi_script_path => '/var/www/cgi-bin/nova', + :placement_wsgi_script_source => '/usr/bin/nova-placement-api', + :placement_package_name => 'openstack-nova-placement-api', + } + end + end + + it_behaves_like 'apache serving nova with mod_wsgi' + end + end +end diff --git a/spec/classes/nova_wsgi_apache_spec.rb b/spec/classes/nova_wsgi_apache_spec.rb index 40be693a7..aa93cdd22 100644 --- a/spec/classes/nova_wsgi_apache_spec.rb +++ b/spec/classes/nova_wsgi_apache_spec.rb @@ -1,3 +1,4 @@ +# This class is deprecated, we'll remove the test in a future release. require 'spec_helper' describe 'nova::wsgi::apache' do @@ -13,7 +14,7 @@ describe 'nova::wsgi::apache' do end shared_examples_for 'apache serving nova with mod_wsgi' do - it { is_expected.to contain_service('httpd').with_name(platform_parameters[:httpd_service_name]) } + it { is_expected.to contain_service('httpd').with_name(platform_params[:httpd_service_name]) } it { is_expected.to contain_class('nova::params') } it { is_expected.to contain_class('apache') } it { is_expected.to contain_class('apache::mod::wsgi') } @@ -30,7 +31,7 @@ describe 'nova::wsgi::apache' do }" end - it { is_expected.to contain_file("#{platform_parameters[:wsgi_script_path]}").with( + it { is_expected.to contain_file("#{platform_params[:wsgi_script_path]}").with( 'ensure' => 'directory', 'owner' => 'nova', 'group' => 'nova', @@ -40,40 +41,40 @@ describe 'nova::wsgi::apache' do it { is_expected.to contain_file('nova_api_wsgi').with( 'ensure' => 'file', - 'path' => "#{platform_parameters[:wsgi_script_path]}/nova-api", - 'source' => platform_parameters[:api_wsgi_script_source], + 'path' => "#{platform_params[:wsgi_script_path]}/nova-api", + 'source' => platform_params[:api_wsgi_script_source], 'owner' => 'nova', 'group' => 'nova', 'mode' => '0644' )} - it { is_expected.to contain_file('nova_api_wsgi').that_requires("File[#{platform_parameters[:wsgi_script_path]}]") } + it { is_expected.to contain_file('nova_api_wsgi').that_requires("File[#{platform_params[:wsgi_script_path]}]") } it { is_expected.to contain_apache__vhost('nova_api_wsgi').with( 'servername' => 'some.host.tld', 'ip' => nil, 'port' => '8774', - 'docroot' => "#{platform_parameters[:wsgi_script_path]}", + 'docroot' => "#{platform_params[:wsgi_script_path]}", 'docroot_owner' => 'nova', 'docroot_group' => 'nova', 'ssl' => 'true', 'wsgi_daemon_process' => 'nova-api', 'wsgi_process_group' => 'nova-api', - 'wsgi_script_aliases' => { '/' => "#{platform_parameters[:wsgi_script_path]}/nova-api" }, + 'wsgi_script_aliases' => { '/' => "#{platform_params[:wsgi_script_path]}/nova-api" }, 'require' => 'File[nova_api_wsgi]' )} - it { is_expected.to contain_concat("#{platform_parameters[:httpd_ports_file]}") } + it { is_expected.to contain_concat("#{platform_params[:httpd_ports_file]}") } it { is_expected.to contain_file('nova_api_wsgi').with( 'ensure' => 'file', - 'path' => "#{platform_parameters[:wsgi_script_path]}/nova-api", - 'source' => platform_parameters[:api_wsgi_script_source], + 'path' => "#{platform_params[:wsgi_script_path]}/nova-api", + 'source' => platform_params[:api_wsgi_script_source], 'owner' => 'nova', 'group' => 'nova', 'mode' => '0644' )} - it { is_expected.to contain_file('nova_api_wsgi').that_requires("File[#{platform_parameters[:wsgi_script_path]}]") } + it { is_expected.to contain_file('nova_api_wsgi').that_requires("File[#{platform_params[:wsgi_script_path]}]") } - it { is_expected.to contain_concat("#{platform_parameters[:httpd_ports_file]}") } + it { is_expected.to contain_concat("#{platform_params[:httpd_ports_file]}") } end context 'when overriding parameters using different ports' do @@ -101,13 +102,13 @@ describe 'nova::wsgi::apache' do 'servername' => 'dummy.host', 'ip' => '10.42.51.1', 'port' => '12345', - 'docroot' => "#{platform_parameters[:wsgi_script_path]}", + 'docroot' => "#{platform_params[:wsgi_script_path]}", 'docroot_owner' => 'nova', 'docroot_group' => 'nova', 'ssl' => 'false', 'wsgi_daemon_process' => 'nova-api', 'wsgi_process_group' => 'nova-api', - 'wsgi_script_aliases' => { '/' => "#{platform_parameters[:wsgi_script_path]}/nova-api" }, + 'wsgi_script_aliases' => { '/' => "#{platform_params[:wsgi_script_path]}/nova-api" }, 'require' => 'File[nova_api_wsgi]' )} end @@ -131,7 +132,7 @@ describe 'nova::wsgi::apache' do facts.merge!(OSDefaults.get_facts({ :fqdn => 'some.host.tld'})) end - let (:platform_parameters) do + let (:platform_params) do case facts[:osfamily] when 'Debian' {