diff --git a/Berksfile b/Berksfile index 54b6b35..5972ca9 100644 --- a/Berksfile +++ b/Berksfile @@ -1,6 +1,19 @@ source 'https://supermarket.chef.io' -%w(-common -compute -identity -image -network client).each do |cookbook| +solver :ruby, :required + +%w( + client + -common + -compute + -dns + -identity + -image + -integration-test + -network + -ops-database + -ops-messaging +).each do |cookbook| if Dir.exist?("../cookbook-openstack#{cookbook}") cookbook "openstack#{cookbook}", path: "../cookbook-openstack#{cookbook}" else diff --git a/README.rst b/README.rst index 4347bef..9ee877b 100644 --- a/README.rst +++ b/README.rst @@ -76,12 +76,6 @@ aodh - Installs aodh service -collector ---------- - -- Installs collector package and service. If the NoSQL database is used - for metering service, ``ceilometer-upgrade`` will not be executed. - common ------ diff --git a/attributes/default.rb b/attributes/default.rb index a2f0889..9f8bfd0 100644 --- a/attributes/default.rb +++ b/attributes/default.rb @@ -125,53 +125,80 @@ end case node['platform_family'] when 'rhel' default['openstack']['telemetry']['platform'] = { - 'common_packages' => ['openstack-ceilometer-common'], - 'gnocchi_packages' => ['openstack-gnocchi-api', 'openstack-gnocchi-metricd'], + 'common_packages' => %w(openstack-ceilometer-common mod_wsgi), + 'gnocchi_packages' => %w(openstack-gnocchi-api openstack-gnocchi-metricd), 'gnocchi-api_service' => 'openstack-gnocchi-api', 'gnocchi-metricd_service' => 'gnocchi-metricd', - 'agent_central_packages' => ['openstack-ceilometer-central'], + 'agent_central_packages' => %w(openstack-ceilometer-central), 'agent_central_service' => 'openstack-ceilometer-central', - 'agent_compute_packages' => ['openstack-ceilometer-compute'], + 'agent_compute_packages' => %w(openstack-ceilometer-compute), 'agent_compute_service' => 'openstack-ceilometer-compute', - 'agent_notification_packages' => ['openstack-ceilometer-collector'], + 'agent_notification_packages' => %w(openstack-ceilometer-collector openstack-ceilometer-notification), 'agent_notification_service' => 'openstack-ceilometer-notification', 'ceilometer-api_wsgi_file' => '/usr/lib/python2.7/site-packages/ceilometer/api/app.wsgi', - 'gnocchi-api_wsgi_file' => '/usr/share/gnocchi-common/app.wsgi', - 'collector_packages' => ['openstack-ceilometer-collector'], - 'collector_service' => 'openstack-ceilometer-collector', + 'gnocchi-api_wsgi_file' => '/usr/lib/python2.7/site-packages/gnocchi/rest/wsgi.py', 'package_overrides' => '', } default['openstack']['aodh']['platform'] = { - 'aodh_packages' => ['openstack-aodh', 'openstack-aodh-api', 'openstack-aodh-evaluator', - 'openstack-aodh-expirer', 'openstack-aodh-listener', 'openstack-aodh-notifier', - 'python-aodhclient'], - 'aodh_services' => ['openstack-aodh-evaluator', 'openstack-aodh-notifier', 'openstack-aodh-listener'], - 'aodh-api_wsgi_file' => '/usr/share/aodh/app.wsgi', + 'aodh_packages' => + %w( + openstack-aodh-api + openstack-aodh-evaluator + openstack-aodh-expirer + openstack-aodh-listener + openstack-aodh-notifier + python-aodhclient + ), + 'aodh_services' => + %w( + openstack-aodh-evaluator + openstack-aodh-notifier + openstack-aodh-listener + ), + 'aodh-api_wsgi_file' => '/usr/lib/python2.7/site-packages/aodh/api/app.wsgi', } when 'debian' default['openstack']['telemetry']['platform'] = { - 'common_packages' => ['ceilometer-common', 'python3-ceilometer'], - 'gnocchi_packages' => ['python3-gnocchi', 'gnocchi-common', 'gnocchi-api', 'gnocchi-metricd', 'python3-gnocchiclient'], + 'common_packages' => %w(ceilometer-common python3-ceilometer), + 'gnocchi_packages' => + %w( + gnocchi-api + gnocchi-common + gnocchi-metricd + python3-gnocchi + python3-gnocchiclient + ), 'gnocchi-api_service' => 'gnocchi-api', 'gnocchi-metricd_service' => 'gnocchi-metricd', - 'agent_central_packages' => ['ceilometer-agent-central'], + 'agent_central_packages' => %w(ceilometer-agent-central), 'agent_central_service' => 'ceilometer-agent-central', - 'agent_compute_packages' => ['ceilometer-agent-compute'], + 'agent_compute_packages' => %w(ceilometer-agent-compute), 'agent_compute_service' => 'ceilometer-agent-compute', - 'agent_notification_packages' => ['ceilometer-agent-notification'], + 'agent_notification_packages' => %w(ceilometer-agent-notification), 'agent_notification_service' => 'ceilometer-agent-notification', 'ceilometer-api_wsgi_file' => '/usr/lib/python3/dist-packages/ceilometer/api/app.wsgi', 'gnocchi-api_wsgi_file' => '/usr/lib/python3/dist-packages/gnocchi/rest/wsgi.py', - 'collector_packages' => ['ceilometer-collector', 'python3-mysqldb'], - 'collector_service' => 'ceilometer-collector', 'package_overrides' => '', } default['openstack']['aodh']['platform'] = { - 'aodh_packages' => ['aodh-api', 'aodh-evaluator', 'aodh-expirer', 'aodh-listener', 'aodh-notifier', 'python3-ceilometerclient'], - 'aodh_services' => ['aodh-evaluator', 'aodh-notifier', 'aodh-listener'], + 'aodh_packages' => + %w( + aodh-api + aodh-evaluator + aodh-expirer + aodh-listener + aodh-notifier + python3-ceilometerclient + ), + 'aodh_services' => + %w( + aodh-evaluator + aodh-notifier + aodh-listener + ), 'aodh-api_wsgi_file' => '/usr/share/aodh/app.wsgi' # this file come with aodh-common which aodh-api depends on } end diff --git a/metadata.rb b/metadata.rb index e47472a..97e586c 100644 --- a/metadata.rb +++ b/metadata.rb @@ -10,7 +10,6 @@ recipe 'openstack-telemetry::agent-compute', 'Installs agent compute service.' recipe 'openstack-telemetry::agent-notification', 'Installs the agent notification service.' recipe 'openstack-telemetry::aodh', 'Installs aodh service' recipe 'openstack-telemetry::api', 'Installs API service.' -recipe 'openstack-telemetry::collector', 'Installs collector service. If the NoSQL database is used for metering service, ceilometer-upgrade will not be executed.' recipe 'openstack-telemetry::common', 'Common metering configuration.' recipe 'openstack-telemetry::gnocchi_configure', 'Configure Gnocchi' recipe 'openstack-telemetry::gnocchi_install', 'Installs and starts the Gnocchi service' @@ -20,7 +19,7 @@ recipe 'openstack-telemetry::identity_registration', 'Registers the endpoints, t supports os end -depends 'apache2' +depends 'apache2', '~> 8.0' depends 'openstackclient' depends 'openstack-common', '>= 18.0.0' depends 'openstack-identity', '>= 18.0.0' diff --git a/recipes/aodh.rb b/recipes/aodh.rb index 0fbaa2b..77474ac 100644 --- a/recipes/aodh.rb +++ b/recipes/aodh.rb @@ -19,8 +19,11 @@ # load the methods defined in cookbook-openstack-common libraries class ::Chef::Recipe include ::Openstack + include Apache2::Cookbook::Helpers end +include_recipe 'openstack-telemetry::common' + platform = node['openstack']['aodh']['platform'] platform['aodh_packages'].each do |pkg| package pkg do @@ -52,7 +55,7 @@ auth_url = ::URI.decode identity_public_endpoint.to_s node.default['openstack']['aodh']['conf'].tap do |conf| conf['api']['host'] = bind_service_address - conf['api']['port'] = bind_service.port + conf['api']['port'] = bind_service['port'] conf['keystone_authtoken']['auth_url'] = auth_url conf['service_credentials']['auth_url'] = auth_url conf['keystone_authtoken']['memcache_servers'] = memcached_servers.join ',' @@ -77,31 +80,34 @@ template node['openstack']['aodh']['conf_file'] do variables( service_config: aodh_conf_options ) + notifies :restart, 'service[apache2]' end execute 'run aodh-dbsync' do command 'aodh-dbsync ' user node['openstack']['aodh']['user'] + group node['openstack']['aodh']['group'] end #### Start of Apache specific work -# configure attributes for apache2 cookbook to align with openstack settings -apache_listen = Array(node['apache']['listen']) # include already defined listen attributes -# Remove the default apache2 cookbook port, as that is also the default for horizon, but with -# a different address syntax. *:80 vs 0.0.0.0:80 -apache_listen -= ['*:80'] -apache_listen += ["#{bind_service_address}:#{bind_service.port}"] -node.normal['apache']['listen'] = apache_listen.uniq +# Finds and appends the listen port to the apache2_install[openstack] +# resource which is defined in openstack-identity::server-apache. +apache_resource = find_resource(:apache2_install, 'openstack') -# include the apache2 default recipe and the recipes for mod_wsgi -include_recipe 'apache2' -include_recipe 'apache2::mod_wsgi' -# include the apache2 mod_ssl recipe if ssl is enabled for identity -include_recipe 'apache2::mod_ssl' if node['openstack']['aodh']['ssl']['enabled'] +if apache_resource + apache_resource.listen = [apache_resource.listen, "#{bind_service['host']}:#{bind_service['port']}"].flatten +else + apache2_install 'openstack' do + listen "#{bind_service['host']}:#{bind_service['port']}" + end +end + +apache2_module 'wsgi' +apache2_module 'ssl' if node['openstack']['aodh']['ssl']['enabled'] # create the aodh-api apache directory -aodh_apache_dir = "#{node['apache']['docroot_dir']}/aodh" +aodh_apache_dir = "#{default_docroot_dir}/aodh" directory aodh_apache_dir do owner 'root' group 'root' @@ -118,25 +124,32 @@ file aodh_server_entry do mode 0o0755 end -web_app 'aodh-api' do - template 'wsgi-template.conf.erb' - daemon_process 'aodh-api' - server_host bind_service.host - server_port bind_service.port - server_entry aodh_server_entry - run_dir node['apache']['run_dir'] - log_dir node['apache']['log_dir'] - log_debug node['openstack']['aodh']['debug'] - user node['openstack']['aodh']['user'] - group node['openstack']['aodh']['group'] - use_ssl node['openstack']['aodh']['ssl']['enabled'] - cert_file node['openstack']['aodh']['ssl']['certfile'] - chain_file node['openstack']['aodh']['ssl']['chainfile'] - key_file node['openstack']['aodh']['ssl']['keyfile'] - ca_certs_path node['openstack']['aodh']['ssl']['ca_certs_path'] - cert_required node['openstack']['aodh']['ssl']['cert_required'] - protocol node['openstack']['aodh']['ssl']['protocol'] - ciphers node['openstack']['aodh']['ssl']['ciphers'] +template "#{apache_dir}/sites-available/aodh-api.conf" do + extend Apache2::Cookbook::Helpers + source 'wsgi-template.conf.erb' + variables( + daemon_process: 'aodh-api', + server_host: bind_service['host'], + server_port: bind_service['port'], + server_entry: aodh_server_entry, + run_dir: lock_dir, + log_dir: default_log_dir, + user: node['openstack']['aodh']['user'], + group: node['openstack']['aodh']['group'], + use_ssl: node['openstack']['aodh']['ssl']['enabled'], + cert_file: node['openstack']['aodh']['ssl']['certfile'], + chain_file: node['openstack']['aodh']['ssl']['chainfile'], + key_file: node['openstack']['aodh']['ssl']['keyfile'], + ca_certs_path: node['openstack']['aodh']['ssl']['ca_certs_path'], + cert_required: node['openstack']['aodh']['ssl']['cert_required'], + protocol: node['openstack']['aodh']['ssl']['protocol'], + ciphers: node['openstack']['aodh']['ssl']['ciphers'] + ) + notifies :restart, 'service[apache2]' +end + +apache2_site 'aodh-api' do + notifies :restart, 'service[apache2]', :immediately end platform['aodh_services'].each do |aodh_service| diff --git a/recipes/collector.rb b/recipes/collector.rb deleted file mode 100644 index 7548474..0000000 --- a/recipes/collector.rb +++ /dev/null @@ -1,37 +0,0 @@ -# encoding: UTF-8 -# -# Cookbook Name:: openstack-telemetry -# Recipe:: collector -# -# Copyright 2013, AT&T Services, Inc. -# Copyright 2013, Craig Tracey -# Copyright 2013, SUSE Linux GmbH -# -# 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. -# - -include_recipe 'openstack-telemetry::common' - -platform = node['openstack']['telemetry']['platform'] -platform['collector_packages'].each do |pkg| - package pkg do - options platform['package_overrides'] - action :upgrade - end -end - -service 'ceilometer-collector' do - service_name platform['collector_service'] - subscribes :restart, "template[#{node['openstack']['telemetry']['conf_file']}]" - action [:enable, :start] -end diff --git a/recipes/common.rb b/recipes/common.rb index 9b9e52a..bb5220f 100644 --- a/recipes/common.rb +++ b/recipes/common.rb @@ -22,6 +22,7 @@ class ::Chef::Recipe include ::Openstack + include Apache2::Cookbook::Helpers end if node['openstack']['telemetry']['syslog']['use'] @@ -78,7 +79,7 @@ directory node['openstack']['telemetry']['conf_dir'] do action :create end -directory "#{node['apache']['run_dir']}/ceilometer" do +directory "#{lock_dir}/ceilometer" do owner node['openstack']['telemetry']['user'] group node['openstack']['telemetry']['group'] mode 0o0750 @@ -89,6 +90,16 @@ end # merge all config options and secrets to be used in the ceilometer.conf ceilometer_conf_options = merge_config_options 'telemetry' +# service['apache2'] is defined in the apache2_default_install resource +# but other resources are currently unable to reference it. To work +# around this issue, define the following helper in your cookbook: +service 'apache2' do + extend Apache2::Cookbook::Helpers + service_name lazy { apache_platform_service_name } + supports restart: true, status: true, reload: true + action :nothing +end + template node['openstack']['telemetry']['conf_file'] do source 'openstack-service.conf.erb' cookbook 'openstack-common' diff --git a/recipes/gnocchi_configure.rb b/recipes/gnocchi_configure.rb index db8712d..84614bf 100644 --- a/recipes/gnocchi_configure.rb +++ b/recipes/gnocchi_configure.rb @@ -17,7 +17,11 @@ # class ::Chef::Recipe include ::Openstack + include Apache2::Cookbook::Helpers end + +include_recipe 'openstack-telemetry::common' + platform = node['openstack']['telemetry']['platform'] db_user = node['openstack']['db']['telemetry_metric']['username'] db_pass = get_password 'db', 'gnocchi' @@ -43,12 +47,6 @@ node.default['openstack']['telemetry_metric']['conf'].tap do |conf| conf['keystone_authtoken']['auth_url'] = auth_url end -# Clear lock file when notified -execute 'Clear gnocchi apache restart' do - command "rm -f #{Chef::Config[:file_cache_path]}/gnocchi-apache-restarted" - action :nothing -end - # merge all config options and secrets to be used in the gnocchi.conf gnocchi_conf_options = merge_config_options 'telemetry_metric' template node['openstack']['telemetry_metric']['conf_file'] do @@ -60,7 +58,7 @@ template node['openstack']['telemetry_metric']['conf_file'] do variables( service_config: gnocchi_conf_options ) - notifies :run, 'execute[Clear gnocchi apache restart]', :immediately + notifies :restart, 'service[apache2]' end # drop gnocchi_resources.yaml to ceilometer folder (current workaround since not @@ -110,26 +108,28 @@ end execute 'run gnocchi-upgrade' do command "gnocchi-upgrade #{node['openstack']['telemetry_metric']['gnocchi-upgrade-options']}" user node['openstack']['telemetry_metric']['user'] + group node['openstack']['telemetry_metric']['group'] end #### Start of Apache specific work -# configure attributes for apache2 cookbook to align with openstack settings -apache_listen = Array(node['apache']['listen']) # include already defined listen attributes -# Remove the default apache2 cookbook port, as that is also the default for horizon, but with -# a different address syntax. *:80 vs 0.0.0.0:80 -apache_listen -= ['*:80'] -apache_listen += ["#{bind_service_address}:#{bind_service['port']}"] -node.normal['apache']['listen'] = apache_listen.uniq +# Finds and appends the listen port to the apache2_install[openstack] +# resource which is defined in openstack-identity::server-apache. +apache_resource = find_resource(:apache2_install, 'openstack') -# include the apache2 default recipe and the recipes for mod_wsgi -include_recipe 'apache2' -include_recipe 'apache2::mod_wsgi' -# include the apache2 mod_ssl recipe if ssl is enabled for identity -include_recipe 'apache2::mod_ssl' if node['openstack']['identity']['ssl']['enabled'] +if apache_resource + apache_resource.listen = [apache_resource.listen, "#{bind_service['host']}:#{bind_service['port']}"].flatten +else + apache2_install 'openstack' do + listen "#{bind_service['host']}:#{bind_service['port']}" + end +end + +apache2_module 'wsgi' +apache2_module 'ssl' if node['openstack']['telemetry_metric']['ssl']['enabled'] # create the gnocchi-api apache directory -gnocchi_apache_dir = "#{node['apache']['docroot_dir']}/gnocchi" +gnocchi_apache_dir = "#{default_docroot_dir}/gnocchi" directory gnocchi_apache_dir do owner 'root' group 'root' @@ -146,53 +146,35 @@ file gnocchi_server_entry do mode 0o0755 end -web_app 'gnocchi-api' do - template 'wsgi-template.conf.erb' - daemon_process 'gnocchi-api' - server_host bind_service['host'] - server_port bind_service['port'] - server_entry gnocchi_server_entry - run_dir node['apache']['run_dir'] - log_dir node['apache']['log_dir'] - log_debug node['openstack']['telemetry_metric']['debug'] - user node['openstack']['telemetry_metric']['user'] - group node['openstack']['telemetry_metric']['group'] - use_ssl node['openstack']['telemetry_metric']['ssl']['enabled'] - cert_file node['openstack']['telemetry_metric']['ssl']['certfile'] - chain_file node['openstack']['telemetry_metric']['ssl']['chainfile'] - key_file node['openstack']['telemetry_metric']['ssl']['keyfile'] - ca_certs_path node['openstack']['telemetry_metric']['ssl']['ca_certs_path'] - cert_required node['openstack']['telemetry_metric']['ssl']['cert_required'] - protocol node['openstack']['telemetry_metric']['ssl']['protocol'] - ciphers node['openstack']['telemetry_metric']['ssl']['ciphers'] +template "#{apache_dir}/sites-available/gnocchi-api.conf" do + extend Apache2::Cookbook::Helpers + source 'wsgi-template.conf.erb' + variables( + daemon_process: 'gnocchi-api', + server_host: bind_service['host'], + server_port: bind_service['port'], + server_entry: gnocchi_server_entry, + run_dir: lock_dir, + log_dir: default_log_dir, + log_debug: node['openstack']['telemetry_metric']['debug'], + user: node['openstack']['telemetry_metric']['user'], + group: node['openstack']['telemetry_metric']['group'], + use_ssl: node['openstack']['telemetry_metric']['ssl']['enabled'], + cert_file: node['openstack']['telemetry_metric']['ssl']['certfile'], + chain_file: node['openstack']['telemetry_metric']['ssl']['chainfile'], + key_file: node['openstack']['telemetry_metric']['ssl']['keyfile'], + ca_certs_path: node['openstack']['telemetry_metric']['ssl']['ca_certs_path'], + cert_required: node['openstack']['telemetry_metric']['ssl']['cert_required'], + protocol: node['openstack']['telemetry_metric']['ssl']['protocol'], + ciphers: node['openstack']['telemetry_metric']['ssl']['ciphers'] + ) + notifies :restart, 'service[apache2]' end -# Hack until Apache cookbook has lwrp's for proper use of notify restart -# apache2 after gnocchi-api if completely configured. Whenever a gnocchi -# config is updated, have it notify the resource which clears the lock -# so the service can be restarted. -# TODO(ramereth): This should be removed once this cookbook is updated -# to use the newer apache2 cookbook which uses proper resources. -edit_resource(:template, "#{node['apache']['dir']}/sites-available/gnocchi-api.conf") do - notifies :run, 'execute[Clear gnocchi apache restart]', :immediately -end - -# Only restart gnocchi apache during the initial install. This causes -# monitoring and service issues while the service is restarted so we -# should minimize the amount of times we restart apache. -execute 'gnocchi apache restart' do - command "touch #{Chef::Config[:file_cache_path]}/gnocchi-apache-restarted" - creates "#{Chef::Config[:file_cache_path]}/gnocchi-apache-restarted" - notifies :run, 'execute[restore-selinux-context-gnocchi]', :immediately +apache2_site 'gnocchi-api' do notifies :restart, 'service[apache2]', :immediately end -execute 'restore-selinux-context-gnocchi' do - command 'restorecon -Rv /etc/httpd /etc/pki || :' - action :nothing - only_if { platform_family?('rhel') } -end - service 'gnocchi-metricd' do service_name platform['gnocchi-metricd_service'] subscribes :restart, "template[#{node['openstack']['telemetry_metric']['conf_file']}]" diff --git a/spec/aodh-rhel_spec.rb b/spec/aodh-rhel_spec.rb new file mode 100644 index 0000000..5761e4e --- /dev/null +++ b/spec/aodh-rhel_spec.rb @@ -0,0 +1,34 @@ +# encoding: UTF-8 + +require_relative 'spec_helper' + +describe 'openstack-telemetry::aodh' do + describe 'rhel' do + let(:runner) { ChefSpec::SoloRunner.new(REDHAT_OPTS) } + let(:node) { runner.node } + cached(:chef_run) { runner.converge(described_recipe) } + + include_context 'telemetry-stubs' + + it 'installs the aodh packages' do + expect(chef_run).to upgrade_package('openstack-aodh-api') + expect(chef_run).to upgrade_package('openstack-aodh-evaluator') + expect(chef_run).to upgrade_package('openstack-aodh-expirer') + expect(chef_run).to upgrade_package('openstack-aodh-listener') + expect(chef_run).to upgrade_package('openstack-aodh-notifier') + expect(chef_run).to upgrade_package('python-aodhclient') + end + + it 'starts aodh services' do + expect(chef_run).to start_service('openstack-aodh-evaluator') + expect(chef_run).to start_service('openstack-aodh-notifier') + expect(chef_run).to start_service('openstack-aodh-listener') + end + + it 'subscribes to /etc/aodh/aodh.conf' do + expect(chef_run.service('openstack-aodh-evaluator')).to subscribe_to('template[/etc/aodh/aodh.conf]') + expect(chef_run.service('openstack-aodh-notifier')).to subscribe_to('template[/etc/aodh/aodh.conf]') + expect(chef_run.service('openstack-aodh-listener')).to subscribe_to('template[/etc/aodh/aodh.conf]') + end + end +end diff --git a/spec/aodh_spec.rb b/spec/aodh_spec.rb new file mode 100644 index 0000000..4a02fcd --- /dev/null +++ b/spec/aodh_spec.rb @@ -0,0 +1,274 @@ +require_relative 'spec_helper' + +describe 'openstack-telemetry::aodh' do + describe 'ubuntu' do + let(:runner) { ChefSpec::SoloRunner.new(UBUNTU_OPTS) } + let(:node) { runner.node } + cached(:chef_run) { runner.converge(described_recipe) } + + include_context 'telemetry-stubs' + + it 'installs aodh packages' do + expect(chef_run).to upgrade_package('aodh-api') + expect(chef_run).to upgrade_package('aodh-evaluator') + expect(chef_run).to upgrade_package('aodh-expirer') + expect(chef_run).to upgrade_package('aodh-listener') + expect(chef_run).to upgrade_package('aodh-notifier') + expect(chef_run).to upgrade_package('python3-ceilometerclient') + end + + it do + expect(chef_run).to install_apache2_install('openstack').with(listen: '127.0.0.1:8042') + end + + it do + expect(chef_run).to enable_apache2_module('wsgi') + end + + it do + expect(chef_run).to_not enable_apache2_module('ssl') + end + + describe 'aodh.conf' do + let(:file) { chef_run.template('/etc/aodh/aodh.conf') } + + it do + expect(chef_run).to create_directory('/etc/aodh') + end + + it do + expect(chef_run).to create_template(file.name).with( + source: 'openstack-service.conf.erb', + cookbook: 'openstack-common', + user: 'aodh', + group: 'aodh', + mode: 0o640, + variables: { + service_config: { + 'DEFAULT' => { + 'transport_url' => 'rabbit://guest:mypass@127.0.0.1:5672' }, + 'api' => { + 'host' => '127.0.0.1', + 'port' => 8042, + }, + 'database' => { + 'connection' => 'mysql+pymysql://aodh:aodh-dbpass@127.0.0.1:3306/aodh?charset=utf8' }, + 'keystone_authtoken' => { + 'auth_type' => 'v3password', + 'auth_url' => 'http://127.0.0.1:5000/v3', + 'memcache_servers' => '', + 'password' => 'aodh-pass', + 'project_domain_name' => 'Default', + 'project_name' => 'service', + 'region_name' => 'RegionOne', + 'user_domain_name' => 'Default', + 'username' => 'aodh', + }, + 'service_credentials' => { + 'auth_type' => 'v3password', + 'auth_url' => 'http://127.0.0.1:5000/v3', + 'interface' => 'internal', + 'password' => 'aodh-pass', + 'project_domain_name' => 'Default', + 'project_name' => 'service', + 'region_name' => 'RegionOne', + 'user_domain_name' => 'Default', + 'username' => 'aodh', + }, + }, + } + ) + end + + it do + [ + /^username = aodh$/, + /^user_domain_name = Default$/, + /^project_name = service$/, + /^project_domain_name = Default$/, + /^auth_type = v3password$/, + /^region_name = RegionOne$/, + %r{auth_url = http://127\.0\.0\.1:5000/v3}, + /^password = aodh-pass$/, + ].each do |line| + expect(chef_run).to render_config_file(file.name) + .with_section_content('keystone_authtoken', line) + end + end + + it do + [ + /^host = 127\.0\.0\.1$/, + /^port = 8042$/, + ].each do |line| + expect(chef_run).to render_config_file(file.name) + .with_section_content('api', line) + end + end + + it do + expect(chef_run).to render_config_file(file.name) + .with_section_content( + 'database', + %(connection = mysql+pymysql://aodh:aodh-dbpass@127.0.0.1:3306/aodh?charset=utf8) + ) + end + end + + it do + expect(chef_run).to run_execute('run aodh-dbsync') + .with( + command: 'aodh-dbsync ', + user: 'aodh' + ) + end + + it 'creates directory /var/www/html/aodh' do + expect(chef_run).to create_directory('/var/www/html/aodh').with( + user: 'root', + group: 'root', + mode: 0o0755 + ) + end + + it 'creates wsgi file' do + expect(chef_run).to create_file('/var/www/html/aodh/app').with( + user: 'root', + group: 'root', + mode: 0o0755 + ) + end + + describe 'apache wsgi' do + file = '/etc/apache2/sites-available/aodh-api.conf' + it "creates #{file}" do + expect(chef_run).to create_template(file).with( + source: 'wsgi-template.conf.erb', + variables: { + ca_certs_path: '/etc/ceilometer/ssl/certs/', + cert_file: '/etc/ceilometer/ssl/certs/sslcert.pem', + cert_required: false, + chain_file: nil, + ciphers: nil, + daemon_process: 'aodh-api', + group: 'aodh', + key_file: '/etc/ceilometer/ssl/private/sslkey.pem', + log_dir: '/var/log/apache2', + protocol: 'All -SSLv2 -SSLv3', + run_dir: '/var/lock/apache2', + server_entry: '/var/www/html/aodh/app', + server_host: '127.0.0.1', + server_port: 8042, + user: 'aodh', + use_ssl: false, + } + ) + end + + context "configures #{file} common lines" do + cached(:chef_run) do + node.override['openstack']['telemetry_metric']['custom_template_banner'] = 'custom_template_banner_value' + runner.converge(described_recipe) + end + [ + /^$/, + /WSGIDaemonProcess aodh-api processes=2 threads=10 user=aodh group=aodh display-name=%{GROUP}$/, + /WSGIProcessGroup aodh-api$/, + %r{WSGIScriptAlias / /var/www/html/aodh/app$}, + %r{^WSGISocketPrefix /var/lock/apache2$}, + %r{ErrorLog /var/log/apache2/aodh-api_error.log$}, + %r{CustomLog /var/log/apache2/aodh-api_access.log combined$}, + ].each do |line| + it do + expect(chef_run).to render_file(file).with_content(line) + end + end + end + + it "does not configure #{file} triggered common lines" do + [ + /LogLevel/, + /SSL/, + ].each do |line| + expect(chef_run).not_to render_file(file).with_content(line) + end + end + context 'Enable SSL' do + cached(:chef_run) do + node.override['openstack']['aodh']['ssl']['enabled'] = true + runner.converge(described_recipe) + end + + it do + expect(chef_run).to enable_apache2_module('ssl') + end + + it "configures #{file} common ssl lines" do + [ + /SSLEngine On$/, + %r{SSLCertificateFile /etc/ceilometer/ssl/certs/sslcert.pem$}, + %r{SSLCertificateKeyFile /etc/ceilometer/ssl/private/sslkey.pem$}, + %r{SSLCACertificatePath /etc/ceilometer/ssl/certs/$}, + /SSLProtocol All -SSLv2 -SSLv3$/, + ].each do |line| + expect(chef_run).to render_file(file).with_content(line) + end + end + it "does not configure #{file} common ssl lines" do + [ + /SSLCertificateChainFile/, + /SSLCipherSuite/, + /SSLVerifyClient require/, + ].each do |line| + expect(chef_run).not_to render_file(file).with_content(line) + end + end + context 'Enable chainfile, ciphers, cert_required' do + cached(:chef_run) do + node.override['openstack']['aodh']['ssl']['enabled'] = true + node.override['openstack']['aodh']['ssl']['chainfile'] = + '/etc/ceilometer/ssl/certs/chainfile.pem' + node.override['openstack']['aodh']['ssl']['ciphers'] = 'ciphers_value' + node.override['openstack']['aodh']['ssl']['cert_required'] = true + runner.converge(described_recipe) + end + it "configures #{file} chainfile when set" do + expect(chef_run).to render_file(file) + .with_content(%r{SSLCertificateChainFile /etc/ceilometer/ssl/certs/chainfile.pem$}) + end + it "configures #{file} ciphers when set" do + expect(chef_run).to render_file(file) + .with_content(/SSLCipherSuite ciphers_value$/) + end + it "configures #{file} cert_required set" do + expect(chef_run).to render_file(file) + .with_content(/SSLVerifyClient require$/) + end + end + end + + describe 'restart apache' do + it do + expect(chef_run.template('/etc/apache2/sites-available/aodh-api.conf')).to \ + notify('service[apache2]').to(:restart) + end + it do + expect(chef_run.apache2_site('aodh-api')).to notify('service[apache2]').to(:restart).immediately + end + end + %w( + aodh-evaluator + aodh-notifier + aodh-listener + ).each do |aodh_service| + it do + expect(chef_run).to start_service(aodh_service).with(service_name: aodh_service) + expect(chef_run).to enable_service(aodh_service).with(service_name: aodh_service) + end + it do + expect(chef_run.service(aodh_service)).to subscribe_to('template[/etc/aodh/aodh.conf]') + end + end + end + end +end diff --git a/spec/collector-rhel_spec.rb b/spec/collector-rhel_spec.rb deleted file mode 100644 index 59424fd..0000000 --- a/spec/collector-rhel_spec.rb +++ /dev/null @@ -1,22 +0,0 @@ -# encoding: UTF-8 - -require_relative 'spec_helper' - -describe 'openstack-telemetry::collector' do - describe 'rhel' do - let(:runner) { ChefSpec::SoloRunner.new(REDHAT_OPTS) } - let(:node) { runner.node } - cached(:chef_run) { runner.converge(described_recipe) } - - include_context 'telemetry-stubs' - include_examples 'expect-runs-common-recipe' - - it 'installs the collector package' do - expect(chef_run).to upgrade_package('openstack-ceilometer-collector') - end - - it 'starts collector service' do - expect(chef_run).to start_service('openstack-ceilometer-collector') - end - end -end diff --git a/spec/collector_spec.rb b/spec/collector_spec.rb deleted file mode 100644 index 1d58b54..0000000 --- a/spec/collector_spec.rb +++ /dev/null @@ -1,37 +0,0 @@ -# encoding: UTF-8 - -require_relative 'spec_helper' - -describe 'openstack-telemetry::collector' do - describe 'ubuntu' do - let(:runner) { ChefSpec::SoloRunner.new(UBUNTU_OPTS) } - let(:node) { runner.node } - cached(:chef_run) { runner.converge(described_recipe) } - - include_context 'telemetry-stubs' - include_examples 'expect-runs-common-recipe' - - it do - expect(chef_run).to upgrade_package 'ceilometer-collector' - end - - it do - expect(chef_run).to upgrade_package('python3-mysqldb') - end - - it do - expect(chef_run).to enable_service('ceilometer-collector') - end - - it do - expect(chef_run).to start_service('ceilometer-collector') - end - - describe 'ceilometer-collector' do - it 'subscribes to its config file' do - expect(chef_run.service('ceilometer-collector')).to \ - subscribe_to('template[/etc/ceilometer/ceilometer.conf]').delayed - end - end - end -end diff --git a/spec/common-rhel_spec.rb b/spec/common-rhel_spec.rb index b2e66a3..ff9f3f0 100644 --- a/spec/common-rhel_spec.rb +++ b/spec/common-rhel_spec.rb @@ -16,6 +16,7 @@ describe 'openstack-telemetry::common' do it 'installs the common package' do expect(chef_run).to upgrade_package 'openstack-ceilometer-common' + expect(chef_run).to upgrade_package 'mod_wsgi' end end end diff --git a/spec/gnocchi_configure-rhel_spec.rb b/spec/gnocchi_configure-rhel_spec.rb index b45d203..6b22a63 100644 --- a/spec/gnocchi_configure-rhel_spec.rb +++ b/spec/gnocchi_configure-rhel_spec.rb @@ -19,10 +19,5 @@ describe 'openstack-telemetry::gnocchi_configure' do mode: 0o0640 ) end - - it do - expect(chef_run).to nothing_execute('restore-selinux-context-gnocchi') - .with(command: 'restorecon -Rv /etc/httpd /etc/pki || :') - end end end diff --git a/spec/gnocchi_configure_spec.rb b/spec/gnocchi_configure_spec.rb index f2d9ab2..2536175 100644 --- a/spec/gnocchi_configure_spec.rb +++ b/spec/gnocchi_configure_spec.rb @@ -8,6 +8,18 @@ describe 'openstack-telemetry::gnocchi_configure' do include_context 'telemetry-stubs' + it do + expect(chef_run).to install_apache2_install('openstack').with(listen: '127.0.0.1:8041') + end + + it do + expect(chef_run).to enable_apache2_module('wsgi') + end + + it do + expect(chef_run).to_not enable_apache2_module('ssl') + end + describe 'gnocchi.conf' do let(:file) { chef_run.template('/etc/gnocchi/gnocchi.conf') } @@ -135,24 +147,6 @@ describe 'openstack-telemetry::gnocchi_configure' do expect(chef_run).to start_service('gnocchi-metricd') end - describe 'apache recipes' do - it 'include apache recipes' do - expect(chef_run).to include_recipe('apache2') - expect(chef_run).to include_recipe('apache2::mod_wsgi') - expect(chef_run).not_to include_recipe('apache2::mod_ssl') - end - - context 'include apache recipes' do - cached(:chef_run) do - node.override['openstack']['identity']['ssl']['enabled'] = true - runner.converge(described_recipe) - end - it do - expect(chef_run).to include_recipe('apache2::mod_ssl') - end - end - end - it 'creates directory /var/www/html/gnocchi' do expect(chef_run).to create_directory('/var/www/html/gnocchi').with( user: 'root', @@ -173,9 +167,26 @@ describe 'openstack-telemetry::gnocchi_configure' do file = '/etc/apache2/sites-available/gnocchi-api.conf' it "creates #{file}" do expect(chef_run).to create_template(file).with( - user: 'root', - group: 'root', - mode: '0644' + source: 'wsgi-template.conf.erb', + variables: { + ca_certs_path: '/etc/ceilometer/ssl/certs/', + cert_file: '/etc/ceilometer/ssl/certs/sslcert.pem', + cert_required: false, + chain_file: nil, + ciphers: nil, + daemon_process: 'gnocchi-api', + group: 'gnocchi', + key_file: '/etc/ceilometer/ssl/private/sslkey.pem', + log_debug: nil, + log_dir: '/var/log/apache2', + protocol: 'All -SSLv2 -SSLv3', + run_dir: '/var/lock/apache2', + server_entry: '/var/www/html/gnocchi/app', + server_host: '127.0.0.1', + server_port: 8041, + user: 'gnocchi', + use_ssl: false, + } ) end @@ -185,10 +196,13 @@ describe 'openstack-telemetry::gnocchi_configure' do runner.converge(described_recipe) end [ - /user=gnocchi/, - /group=gnocchi/, - %r{^ ErrorLog /var/log/apache2/gnocchi-api_error.log$}, - %r{^ CustomLog /var/log/apache2/gnocchi-api_access.log combined$}, + /^$/, + /WSGIDaemonProcess gnocchi-api processes=2 threads=10 user=gnocchi group=gnocchi display-name=%{GROUP}$/, + /WSGIProcessGroup gnocchi-api$/, + %r{WSGIScriptAlias / /var/www/html/gnocchi/app$}, + %r{^WSGISocketPrefix /var/lock/apache2$}, + %r{ErrorLog /var/log/apache2/gnocchi-api_error.log$}, + %r{CustomLog /var/log/apache2/gnocchi-api_access.log combined$}, ].each do |line| it do expect(chef_run).to render_file(file).with_content(line) @@ -198,8 +212,8 @@ describe 'openstack-telemetry::gnocchi_configure' do it "does not configure #{file} triggered common lines" do [ - /^ LogLevel/, - /^ SSL/, + /LogLevel/, + /SSL/, ].each do |line| expect(chef_run).not_to render_file(file).with_content(line) end @@ -209,22 +223,25 @@ describe 'openstack-telemetry::gnocchi_configure' do node.override['openstack']['telemetry_metric']['ssl']['enabled'] = true runner.converge(described_recipe) end + it do + expect(chef_run).to enable_apache2_module('ssl') + end it "configures #{file} common ssl lines" do [ - /^ SSLEngine On$/, - %r{^ SSLCertificateFile /etc/ceilometer/ssl/certs/sslcert.pem$}, - %r{^ SSLCertificateKeyFile /etc/ceilometer/ssl/private/sslkey.pem$}, - %r{^ SSLCACertificatePath /etc/ceilometer/ssl/certs/$}, - /^ SSLProtocol All -SSLv2 -SSLv3$/, + /SSLEngine On$/, + %r{SSLCertificateFile /etc/ceilometer/ssl/certs/sslcert.pem$}, + %r{SSLCertificateKeyFile /etc/ceilometer/ssl/private/sslkey.pem$}, + %r{SSLCACertificatePath /etc/ceilometer/ssl/certs/$}, + /SSLProtocol All -SSLv2 -SSLv3$/, ].each do |line| expect(chef_run).to render_file(file).with_content(line) end end it "does not configure #{file} common ssl lines" do [ - /^ SSLCertificateChainFile/, - /^ SSLCipherSuite/, - /^ SSLVerifyClient require/, + /SSLCertificateChainFile/, + /SSLCipherSuite/, + /SSLVerifyClient require/, ].each do |line| expect(chef_run).not_to render_file(file).with_content(line) end @@ -240,61 +257,26 @@ describe 'openstack-telemetry::gnocchi_configure' do end it "configures #{file} chainfile when set" do expect(chef_run).to render_file(file) - .with_content(%r{^ SSLCertificateChainFile /etc/ceilometer/ssl/certs/chainfile.pem$}) + .with_content(%r{SSLCertificateChainFile /etc/ceilometer/ssl/certs/chainfile.pem$}) end it "configures #{file} ciphers when set" do expect(chef_run).to render_file(file) - .with_content(/^ SSLCipherSuite ciphers_value$/) + .with_content(/SSLCipherSuite ciphers_value$/) end it "configures #{file} cert_required set" do expect(chef_run).to render_file(file) - .with_content(/^ SSLVerifyClient require$/) - end - end - end - - describe 'gnocchi-api WSGI app' do - it 'configures required lines' do - [ - /^$/, - /^ WSGIDaemonProcess gnocchi-api/, - /^ WSGIProcessGroup gnocchi-api$/, - %r{^ WSGIScriptAlias / /var/www/html/gnocchi/app$}, - ].each do |line| - expect(chef_run).to render_file('/etc/apache2/sites-available/gnocchi-api.conf').with_content(line) + .with_content(/SSLVerifyClient require$/) end end end describe 'restart apache' do it do - expect(chef_run).to nothing_execute('Clear gnocchi apache restart') - .with( - command: 'rm -f /var/chef/cache/gnocchi-apache-restarted' - ) - end - %w( - /etc/gnocchi/gnocchi.conf - /etc/apache2/sites-available/gnocchi-api.conf - ).each do |f| - it "#{f} notifies execute[Clear gnocchi apache restart]" do - expect(chef_run.template(f)).to notify('execute[Clear gnocchi apache restart]').to(:run).immediately - end + expect(chef_run.template('/etc/apache2/sites-available/gnocchi-api.conf')).to \ + notify('service[apache2]').to(:restart) end it do - expect(chef_run).to run_execute('gnocchi apache restart') - .with( - command: 'touch /var/chef/cache/gnocchi-apache-restarted', - creates: '/var/chef/cache/gnocchi-apache-restarted' - ) - end - it do - expect(chef_run.execute('gnocchi apache restart')).to \ - notify('execute[restore-selinux-context-gnocchi]').to(:run).immediately - end - it do - expect(chef_run.execute('gnocchi apache restart')).to \ - notify('service[apache2]').to(:restart).immediately + expect(chef_run.apache2_site('gnocchi-api')).to notify('service[apache2]').to(:restart).immediately end end end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index a11ba73..cf47c89 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -30,6 +30,9 @@ shared_context 'telemetry-stubs' do allow_any_instance_of(Chef::Recipe).to receive(:get_password) .with('db', 'gnocchi') .and_return('gnocchi-dbpass') + allow_any_instance_of(Chef::Recipe).to receive(:get_password) + .with('db', 'aodh') + .and_return('aodh-dbpass') allow_any_instance_of(Chef::Recipe).to receive(:get_password) .with('service', 'openstack-telemetry') .and_return('ceilometer-pass') @@ -48,9 +51,41 @@ shared_context 'telemetry-stubs' do allow_any_instance_of(Chef::Recipe).to receive(:rabbit_transport_url) .with('telemetry') .and_return('rabbit://guest:mypass@127.0.0.1:5672') + allow_any_instance_of(Chef::Recipe).to receive(:rabbit_transport_url) + .with('aodh') + .and_return('rabbit://guest:mypass@127.0.0.1:5672') allow(Chef::Application).to receive(:fatal!) stub_command('/usr/sbin/apache2 -t') stub_command('/usr/sbin/httpd -t') + # identity stubs + allow_any_instance_of(Chef::Recipe).to receive(:secret) + .with('secrets', 'credential_key0') + .and_return('thisiscredentialkey0') + allow_any_instance_of(Chef::Recipe).to receive(:secret) + .with('secrets', 'credential_key1') + .and_return('thisiscredentialkey1') + allow_any_instance_of(Chef::Recipe).to receive(:secret) + .with('secrets', 'fernet_key0') .and_return('thisisfernetkey0') + allow_any_instance_of(Chef::Recipe).to receive(:secret) + .with('secrets', 'fernet_key1') + .and_return('thisisfernetkey1') + allow_any_instance_of(Chef::Recipe).to receive(:search_for) + .with('os-identity').and_return( + [{ + 'openstack' => { + 'identity' => { + 'admin_tenant_name' => 'admin', + 'admin_user' => 'admin', + }, + }, + }] + ) + allow_any_instance_of(Chef::Recipe).to receive(:rabbit_transport_url) + .with('identity') + .and_return('rabbit://openstack:mypass@127.0.0.1:5672') + allow_any_instance_of(Chef::Recipe).to receive(:get_password) + .with('db', 'keystone') + .and_return('keystone-dbpass') end end diff --git a/templates/wsgi-template.conf.erb b/templates/wsgi-template.conf.erb index 4623b3a..b502afc 100644 --- a/templates/wsgi-template.conf.erb +++ b/templates/wsgi-template.conf.erb @@ -1,35 +1,32 @@ <%= node["openstack"]["telemetry"]["custom_template_banner"] %> -:<%= @params[:server_port] %>> - WSGIDaemonProcess <%= @params[:daemon_process] %> processes=2 threads=10 user=<%= @params[:user] %> group=<%= @params[:group] %> display-name=%{GROUP} - WSGIProcessGroup <%= @params[:daemon_process] %> - WSGIScriptAlias / <%= @params[:server_entry] %> +:<%= @server_port %>> + WSGIDaemonProcess <%= @daemon_process %> processes=2 threads=10 user=<%= @user %> group=<%= @group %> display-name=%{GROUP} + WSGIProcessGroup <%= @daemon_process %> + WSGIScriptAlias / <%= @server_entry %> WSGIApplicationGroup %{GLOBAL} WSGIPassAuthorization On ErrorLogFormat "%{cu}t %M" - ErrorLog <%= @params[:log_dir] %>/<%= @params[:daemon_process] %>_error.log - CustomLog <%= @params[:log_dir] %>/<%= @params[:daemon_process] %>_access.log combined - <% if [true, 'true', 'True'].include?(@params[:log_debug]) -%> - LogLevel debug - <% end -%> + ErrorLog <%= @log_dir %>/<%= @daemon_process %>_error.log + CustomLog <%= @log_dir %>/<%= @daemon_process %>_access.log combined + <% if @use_ssl -%> - <% if @params[:use_ssl] -%> - SSLEngine On - SSLCertificateFile <%= @params[:cert_file] %> - SSLCertificateKeyFile <%= @params[:key_file] %> - SSLCACertificatePath <%= @params[:ca_certs_path] %> - <% if @params[:chain_file] %> - SSLCertificateChainFile <%= @params[:chain_file] %> - <% end -%> - SSLProtocol <%= @params[:protocol] %> - <% if @params[:ciphers] -%> - SSLCipherSuite <%= @params[:ciphers] %> - <% end -%> - <% if @params[:cert_required] -%> - SSLVerifyClient require - <% end -%> + SSLEngine On + SSLCertificateFile <%= @cert_file %> + SSLCertificateKeyFile <%= @key_file %> + SSLCACertificatePath <%= @ca_certs_path %> + <% if @chain_file %> + SSLCertificateChainFile <%= @chain_file %> + <% end -%> + SSLProtocol <%= @protocol %> + <% if @ciphers -%> + SSLCipherSuite <%= @ciphers %> + <% end -%> + <% if @cert_required -%> + SSLVerifyClient require + <% end -%> <% end -%> -WSGISocketPrefix <%= @params[:run_dir] %> +WSGISocketPrefix <%= @run_dir %>