diff --git a/Berksfile b/Berksfile index e12874f2..0a718712 100644 --- a/Berksfile +++ b/Berksfile @@ -1,6 +1,18 @@ source 'https://supermarket.chef.io' -%w(client -common -image -identity -network).each do |cookbook| +solver :ruby, :required + +%w( + client + -common + -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 6aaa2f35..f5677661 100644 --- a/README.rst +++ b/README.rst @@ -36,6 +36,7 @@ Cookbooks The following cookbooks are dependencies: +- 'apache2', '~> 8.0' - 'openstackclient', '>= 0.1.0' - 'openstack-common', '>= 18.0.0' - 'openstack-identity', '>= 18.0.0' diff --git a/attributes/default.rb b/attributes/default.rb index 5e4839f5..23f34510 100644 --- a/attributes/default.rb +++ b/attributes/default.rb @@ -72,7 +72,7 @@ when 'rhel' # :pragma-foodcritic: ~FC024 - won't fix this 'compute_cert_packages' => ['openstack-nova-cert'], 'compute_cert_service' => 'openstack-nova-cert', 'mysql_service' => 'mysqld', - 'common_packages' => ['openstack-nova-common'], + 'common_packages' => ['openstack-nova-common', 'mod_wsgi'], 'iscsi_helper' => 'ietadm', 'volume_packages' => ['sysfsutils', 'sg3_utils', 'device-mapper-multipath'], 'package_overrides' => '', diff --git a/metadata.rb b/metadata.rb index 0860f633..0166469b 100644 --- a/metadata.rb +++ b/metadata.rb @@ -27,6 +27,7 @@ recipe 'openstack-compute::vncproxy', 'Installs/Configures nova vnc proxy' supports os end +depends 'apache2', '~> 8.0' depends 'openstack-common', '>= 18.0.0' depends 'openstack-identity', '>= 18.0.0' depends 'openstack-image', '>= 18.0.0' diff --git a/recipes/api-metadata.rb b/recipes/api-metadata.rb index a33c3a57..106eff8d 100644 --- a/recipes/api-metadata.rb +++ b/recipes/api-metadata.rb @@ -24,13 +24,7 @@ require 'uri' class ::Chef::Recipe include ::Openstack -end - -execute 'nova-metadata: set-selinux-permissive' do - command '/sbin/setenforce Permissive' - action :run - - only_if "[ ! -e /etc/httpd/conf/httpd.conf ] && [ -e /etc/redhat-release ] && [ $(/sbin/sestatus | grep -c '^Current mode:.*enforcing') -eq 1 ]" + include Apache2::Cookbook::Helpers end include_recipe 'openstack-compute::nova-common' @@ -49,7 +43,7 @@ template '/etc/nova/api-paste.ini' do owner node['openstack']['compute']['user'] group node['openstack']['compute']['group'] mode 0o0644 - notifies :run, 'execute[Clear nova-metadata apache restart]', :immediately + notifies :restart, 'service[apache2]' end service 'nova-api-metadata' do @@ -60,45 +54,45 @@ end bind_service = node['openstack']['bind_service']['all']['compute-metadata-api'] -web_app 'nova-metadata' do - template 'wsgi-template.conf.erb' - daemon_process 'nova-metadata' - server_host bind_service['host'] - server_port bind_service['port'] - server_entry '/usr/bin/nova-metadata-wsgi' - log_dir node['apache']['log_dir'] - run_dir node['apache']['run_dir'] - user node['openstack']['compute']['user'] - group node['openstack']['compute']['group'] - use_ssl node['openstack']['compute']['metadata']['ssl']['enabled'] - cert_file node['openstack']['compute']['metadata']['ssl']['certfile'] - chain_file node['openstack']['compute']['metadata']['ssl']['chainfile'] - key_file node['openstack']['compute']['metadata']['ssl']['keyfile'] - ca_certs_path node['openstack']['compute']['metadata']['ssl']['ca_certs_path'] - cert_required node['openstack']['compute']['metadata']['ssl']['cert_required'] - protocol node['openstack']['compute']['metadata']['ssl']['protocol'] - ciphers node['openstack']['compute']['metadata']['ssl']['ciphers'] +# 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') + +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 -# Hack until Apache cookbook has lwrp's for proper use of notify restart -# apache2 after keystone if completely configured. Whenever a nova -# 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/nova-metadata.conf") do - notifies :run, 'execute[Clear nova-metadata apache restart]', :immediately +apache2_module 'wsgi' +apache2_module 'ssl' if node['openstack']['compute']['metadata']['ssl']['enabled'] + +template "#{apache_dir}/sites-available/nova-metadata.conf" do + extend Apache2::Cookbook::Helpers + source 'wsgi-template.conf.erb' + variables( + daemon_process: 'nova-metadata', + server_host: bind_service['host'], + server_port: bind_service['port'], + server_entry: '/usr/bin/nova-metadata-wsgi', + log_dir: default_log_dir, + run_dir: lock_dir, + user: node['openstack']['compute']['user'], + group: node['openstack']['compute']['group'], + use_ssl: node['openstack']['compute']['metadata']['ssl']['enabled'], + cert_file: node['openstack']['compute']['metadata']['ssl']['certfile'], + chain_file: node['openstack']['compute']['metadata']['ssl']['chainfile'], + key_file: node['openstack']['compute']['metadata']['ssl']['keyfile'], + ca_certs_path: node['openstack']['compute']['metadata']['ssl']['ca_certs_path'], + cert_required: node['openstack']['compute']['metadata']['ssl']['cert_required'], + protocol: node['openstack']['compute']['metadata']['ssl']['protocol'], + ciphers: node['openstack']['compute']['metadata']['ssl']['ciphers'] + ) + notifies :restart, 'service[apache2]' end -execute 'nova-metadata apache restart' do - command "touch #{Chef::Config[:file_cache_path]}/nova-metadata-apache-restarted" - creates "#{Chef::Config[:file_cache_path]}/nova-metadata-apache-restarted" - notifies :run, 'execute[nova-metadata: restore-selinux-context]', :immediately +apache2_site 'nova-metadata' do notifies :restart, 'service[apache2]', :immediately end - -execute 'nova-metadata: restore-selinux-context' do - command 'restorecon -Rv /etc/httpd /etc/pki || :' - action :nothing - only_if { platform_family?('rhel') } -end diff --git a/recipes/api-os-compute.rb b/recipes/api-os-compute.rb index 5a7b133e..7f85fbe7 100644 --- a/recipes/api-os-compute.rb +++ b/recipes/api-os-compute.rb @@ -21,13 +21,7 @@ class ::Chef::Recipe include ::Openstack -end - -execute 'nova-api: set-selinux-permissive' do - command '/sbin/setenforce Permissive' - action :run - - only_if "[ ! -e /etc/httpd/conf/httpd.conf ] && [ -e /etc/redhat-release ] && [ $(/sbin/sestatus | grep -c '^Current mode:.*enforcing') -eq 1 ]" + include Apache2::Cookbook::Helpers end include_recipe 'openstack-compute::nova-common' @@ -49,7 +43,7 @@ template '/etc/nova/api-paste.ini' do owner nova_user group nova_group mode 0o0644 - notifies :run, 'execute[Clear nova-api apache restart]', :immediately + notifies :restart, 'service[apache2]' end execute 'nova-manage api_db sync' do @@ -68,47 +62,47 @@ end bind_service = node['openstack']['bind_service']['all']['compute-api'] -web_app 'nova-api' do - template 'wsgi-template.conf.erb' - daemon_process 'nova-api' - server_host bind_service['host'] - server_port bind_service['port'] - server_entry '/usr/bin/nova-api-wsgi' - log_dir node['apache']['log_dir'] - run_dir node['apache']['run_dir'] - user node['openstack']['compute']['user'] - group node['openstack']['compute']['group'] - use_ssl node['openstack']['compute']['api']['ssl']['enabled'] - cert_file node['openstack']['compute']['api']['ssl']['certfile'] - chain_file node['openstack']['compute']['api']['ssl']['chainfile'] - key_file node['openstack']['compute']['api']['ssl']['keyfile'] - ca_certs_path node['openstack']['compute']['api']['ssl']['ca_certs_path'] - cert_required node['openstack']['compute']['api']['ssl']['cert_required'] - protocol node['openstack']['compute']['api']['ssl']['protocol'] - ciphers node['openstack']['compute']['api']['ssl']['ciphers'] +# 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') + +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 -include_recipe 'openstack-compute::_nova_cell' +apache2_module 'wsgi' +apache2_module 'ssl' if node['openstack']['compute']['api']['ssl']['enabled'] -# Hack until Apache cookbook has lwrp's for proper use of notify restart -# apache2 after keystone if completely configured. Whenever a nova -# 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/nova-api.conf") do - notifies :run, 'execute[Clear nova-api apache restart]', :immediately +template "#{apache_dir}/sites-available/nova-api.conf" do + extend Apache2::Cookbook::Helpers + source 'wsgi-template.conf.erb' + variables( + daemon_process: 'nova-api', + server_host: bind_service['host'], + server_port: bind_service['port'], + server_entry: '/usr/bin/nova-api-wsgi', + log_dir: default_log_dir, + run_dir: lock_dir, + user: node['openstack']['compute']['user'], + group: node['openstack']['compute']['group'], + use_ssl: node['openstack']['compute']['api']['ssl']['enabled'], + cert_file: node['openstack']['compute']['api']['ssl']['certfile'], + chain_file: node['openstack']['compute']['api']['ssl']['chainfile'], + key_file: node['openstack']['compute']['api']['ssl']['keyfile'], + ca_certs_path: node['openstack']['compute']['api']['ssl']['ca_certs_path'], + cert_required: node['openstack']['compute']['api']['ssl']['cert_required'], + protocol: node['openstack']['compute']['api']['ssl']['protocol'], + ciphers: node['openstack']['compute']['api']['ssl']['ciphers'] + ) + notifies :restart, 'service[apache2]' end -execute 'nova-api apache restart' do - command "touch #{Chef::Config[:file_cache_path]}/nova-api-apache-restarted" - creates "#{Chef::Config[:file_cache_path]}/nova-api-apache-restarted" - notifies :run, 'execute[nova-api: restore-selinux-context]', :immediately +apache2_site 'nova-api' do notifies :restart, 'service[apache2]', :immediately end -execute 'nova-api: restore-selinux-context' do - command 'restorecon -Rv /etc/httpd /etc/pki || :' - action :nothing - only_if { platform_family?('rhel') } -end +include_recipe 'openstack-compute::_nova_cell' diff --git a/recipes/nova-common.rb b/recipes/nova-common.rb index 9f92e6d8..34aa435c 100644 --- a/recipes/nova-common.rb +++ b/recipes/nova-common.rb @@ -193,18 +193,13 @@ end # merge all config options and secrets to be used in nova.conf nova_conf_options = merge_config_options 'compute' -execute 'Clear nova-api apache restart' do - command "rm -f #{Chef::Config[:file_cache_path]}/nova-api-apache-restarted" - action :nothing -end - -execute 'Clear nova-metadata apache restart' do - command "rm -f #{Chef::Config[:file_cache_path]}/nova-metadata-apache-restarted" - action :nothing -end - -execute 'Clear nova-placement-api apache restart' do - command "rm -f #{Chef::Config[:file_cache_path]}/nova-placement-api-apache-restarted" +# 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 @@ -219,9 +214,7 @@ template '/etc/nova/nova.conf' do # with the glance_api_servers configuration option... service_config: nova_conf_options ) - notifies :run, 'execute[Clear nova-api apache restart]', :immediately - notifies :run, 'execute[Clear nova-metadata apache restart]', :immediately - notifies :run, 'execute[Clear nova-placement-api apache restart]', :immediately + notifies :restart, 'service[apache2]' end # delete all secrets saved in the attribute diff --git a/recipes/placement_api.rb b/recipes/placement_api.rb index 657c2023..076387f8 100644 --- a/recipes/placement_api.rb +++ b/recipes/placement_api.rb @@ -20,32 +20,15 @@ class ::Chef::Recipe include ::Openstack + include Apache2::Cookbook::Helpers end include_recipe 'openstack-compute::nova-common' # Create valid apache site configuration file before installing package bind_service = node['openstack']['bind_service']['all']['placement-api'] - -web_app 'nova-placement-api' do - template 'wsgi-template.conf.erb' - daemon_process 'placement-api' - server_host bind_service['host'] - server_port bind_service['port'] - server_entry '/usr/bin/nova-placement-api' - log_dir node['apache']['log_dir'] - run_dir node['apache']['run_dir'] - user node['openstack']['compute']['user'] - group node['openstack']['compute']['group'] - use_ssl node['openstack']['compute']['placement']['ssl']['enabled'] - cert_file node['openstack']['compute']['placement']['ssl']['certfile'] - chain_file node['openstack']['compute']['placement']['ssl']['chainfile'] - key_file node['openstack']['compute']['placement']['ssl']['keyfile'] - ca_certs_path node['openstack']['compute']['placement']['ssl']['ca_certs_path'] - cert_required node['openstack']['compute']['placement']['ssl']['cert_required'] - protocol node['openstack']['compute']['placement']['ssl']['protocol'] - ciphers node['openstack']['compute']['placement']['ssl']['ciphers'] -end +nova_user = node['openstack']['compute']['user'] +nova_group = node['openstack']['compute']['group'] platform_options = node['openstack']['compute']['platform'] @@ -56,14 +39,59 @@ platform_options['api_placement_packages'].each do |pkg| end end -service 'disable nova-placement-api service' do - service_name platform_options['api_placement_service'] +service platform_options['api_placement_service'] do supports status: true, restart: true action [:disable, :stop] end -nova_user = node['openstack']['compute']['user'] -nova_group = node['openstack']['compute']['group'] +apache2_site 'nova-placement-api' do + action :disable + only_if { platform_family?('debian') } +end + +# 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') + +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']['compute']['placement']['ssl']['enabled'] + +template "#{apache_dir}/sites-available/nova-placement.conf" do + extend Apache2::Cookbook::Helpers + source 'wsgi-template.conf.erb' + variables( + daemon_process: 'placement-api', + server_host: bind_service['host'], + server_port: bind_service['port'], + server_entry: '/usr/bin/nova-placement-api', + log_dir: default_log_dir, + run_dir: lock_dir, + user: nova_user, + group: nova_user, + use_ssl: node['openstack']['compute']['placement']['ssl']['enabled'], + cert_file: node['openstack']['compute']['placement']['ssl']['certfile'], + chain_file: node['openstack']['compute']['placement']['ssl']['chainfile'], + key_file: node['openstack']['compute']['placement']['ssl']['keyfile'], + ca_certs_path: node['openstack']['compute']['placement']['ssl']['ca_certs_path'], + cert_required: node['openstack']['compute']['placement']['ssl']['cert_required'], + protocol: node['openstack']['compute']['placement']['ssl']['protocol'], + ciphers: node['openstack']['compute']['placement']['ssl']['ciphers'] + ) + notifies :restart, 'service[apache2]' +end + +apache2_site 'nova-placement' do + notifies :restart, 'service[apache2]', :immediately +end + execute 'placement-api: nova-manage api_db sync' do timeout node['openstack']['compute']['dbsync_timeout'] user nova_user @@ -71,19 +99,3 @@ execute 'placement-api: nova-manage api_db sync' do command 'nova-manage api_db sync' action :run end - -# Hack until Apache cookbook has lwrp's for proper use of notify restart -# apache2 after keystone if completely configured. Whenever a nova -# 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/nova-placement-api.conf") do - notifies :run, 'execute[Clear nova-placement-api apache restart]', :immediately -end - -execute 'nova-placement-api apache restart' do - command "touch #{Chef::Config[:file_cache_path]}/nova-placement-api-apache-restarted" - creates "#{Chef::Config[:file_cache_path]}/nova-placement-api-apache-restarted" - notifies :restart, 'service[apache2]', :immediately -end diff --git a/spec/api-metadata-redhat_spec.rb b/spec/api-metadata-redhat_spec.rb index 487fd4cd..c8653baf 100644 --- a/spec/api-metadata-redhat_spec.rb +++ b/spec/api-metadata-redhat_spec.rb @@ -24,33 +24,5 @@ describe 'openstack-compute::api-metadata' do it 'stops metadata api now' do expect(chef_run).to stop_service 'nova-api-metadata' end - it do - expect(chef_run).to nothing_execute('Clear nova-metadata apache restart') - .with( - command: 'rm -f /var/chef/cache/nova-metadata-apache-restarted' - ) - end - %w( - /etc/nova/nova.conf - /etc/nova/api-paste.ini - /etc/httpd/sites-available/nova-metadata.conf - ).each do |f| - it "#{f} notifies execute[Clear nova-metadata apache restart]" do - expect(chef_run.template(f)).to notify('execute[Clear nova-metadata apache restart]').to(:run).immediately - end - end - it do - expect(chef_run).to run_execute('nova-metadata apache restart') - .with( - command: 'touch /var/chef/cache/nova-metadata-apache-restarted', - creates: '/var/chef/cache/nova-metadata-apache-restarted' - ) - end - it do - expect(chef_run.execute('nova-metadata apache restart')).to notify('execute[nova-metadata: restore-selinux-context]').to(:run).immediately - end - it do - expect(chef_run.execute('nova-metadata apache restart')).to notify('service[apache2]').to(:restart).immediately - end end end diff --git a/spec/api-metadata_spec.rb b/spec/api-metadata_spec.rb index 320df18c..5690f183 100644 --- a/spec/api-metadata_spec.rb +++ b/spec/api-metadata_spec.rb @@ -16,42 +16,144 @@ describe 'openstack-compute::api-metadata' do it 'upgrades metadata api packages' do expect(chef_run).to upgrade_package 'nova-api-metadata' + expect(chef_run).to upgrade_package 'python3-nova' end - it 'disables metadata api on boot' do + it do expect(chef_run).to disable_service 'nova-api-metadata' - end - - it 'stop metadata api now' do expect(chef_run).to stop_service 'nova-api-metadata' end + it do - expect(chef_run).to nothing_execute('Clear nova-metadata apache restart') - .with( - command: 'rm -f /var/chef/cache/nova-metadata-apache-restarted' - ) + expect(chef_run).to install_apache2_install('openstack').with(listen: '127.0.0.1:8775') end - %w( - /etc/nova/nova.conf - /etc/nova/api-paste.ini - /etc/apache2/sites-available/nova-metadata.conf - ).each do |f| - it "#{f} notifies execute[Clear nova-metadata apache restart]" do - expect(chef_run.template(f)).to notify('execute[Clear nova-metadata apache restart]').to(:run).immediately + + it do + expect(chef_run).to enable_apache2_module('wsgi') + end + + it do + expect(chef_run).to_not enable_apache2_module('ssl') + end + + it do + expect(chef_run).to create_template('/etc/apache2/sites-available/nova-metadata.conf').with( + source: 'wsgi-template.conf.erb', + variables: { + ca_certs_path: '', + cert_file: '', + cert_required: false, + chain_file: '', + ciphers: '', + daemon_process: 'nova-metadata', + group: 'nova', + key_file: '', + log_dir: '/var/log/apache2', + protocol: '', + run_dir: '/var/lock/apache2', + server_entry: '/usr/bin/nova-metadata-wsgi', + server_host: '127.0.0.1', + server_port: '8775', + user: 'nova', + use_ssl: false, + } + ) + end + [ + /$/, + /WSGIDaemonProcess nova-metadata processes=2 threads=10 user=nova group=nova display-name=%{GROUP}$/, + /WSGIProcessGroup nova-metadata$/, + %r{WSGIScriptAlias / /usr/bin/nova-metadata-wsgi$}, + /WSGIApplicationGroup %{GLOBAL}$/, + %r{ErrorLog /var/log/apache2/nova-metadata_error.log$}, + %r{CustomLog /var/log/apache2/nova-metadata_access.log combined$}, + %r{WSGISocketPrefix /var/lock/apache2$}, + ].each do |line| + it do + expect(chef_run).to render_file('/etc/apache2/sites-available/nova-metadata.conf').with_content(line) end end - it do - expect(chef_run).to run_execute('nova-metadata apache restart') - .with( - command: 'touch /var/chef/cache/nova-metadata-apache-restarted', - creates: '/var/chef/cache/nova-metadata-apache-restarted' - ) + + [ + /SSLEngine On$/, + /SSLCertificateFile/, + /SSLCertificateKeyFile/, + /SSLCACertificatePath/, + /SSLCertificateChainFile/, + /SSLProtocol/, + /SSLCipherSuite/, + /SSLVerifyClient require/, + ].each do |line| + it do + expect(chef_run).to_not render_file('/etc/apache2/sites-available/nova-metadata.conf').with_content(line) + end end - it do - expect(chef_run.execute('nova-metadata apache restart')).to notify('execute[nova-metadata: restore-selinux-context]').to(:run).immediately + + context 'Enable SSL' do + cached(:chef_run) do + node.override['openstack']['compute']['metadata']['ssl']['enabled'] = true + node.override['openstack']['compute']['metadata']['ssl']['certfile'] = 'ssl.cert' + node.override['openstack']['compute']['metadata']['ssl']['keyfile'] = 'ssl.key' + node.override['openstack']['compute']['metadata']['ssl']['ca_certs_path'] = 'ca_certs_path' + node.override['openstack']['compute']['metadata']['ssl']['protocol'] = 'ssl_protocol_value' + runner.converge(described_recipe) + end + + it do + expect(chef_run).to enable_apache2_module('ssl') + end + + [ + /SSLEngine On$/, + /SSLCertificateFile ssl.cert$/, + /SSLCertificateKeyFile ssl.key$/, + /SSLCACertificatePath ca_certs_path$/, + /SSLProtocol ssl_protocol_value$/, + ].each do |line| + it do + expect(chef_run).to render_file('/etc/apache2/sites-available/nova-metadata.conf').with_content(line) + end + end + [ + /SSLCipherSuite/, + /SSLCertificateChainFile/, + /SSLVerifyClient require/, + ].each do |line| + it do + expect(chef_run).to_not render_file('/etc/apache2/sites-available/nova-metadata.conf').with_content(line) + end + end + context 'Enable chainfile, ciphers & cert_required' do + cached(:chef_run) do + node.override['openstack']['compute']['metadata']['ssl']['enabled'] = true + node.override['openstack']['compute']['metadata']['ssl']['ciphers'] = 'ssl_ciphers_value' + node.override['openstack']['compute']['metadata']['ssl']['chainfile'] = 'chainfile' + node.override['openstack']['compute']['metadata']['ssl']['cert_required'] = true + runner.converge(described_recipe) + end + [ + /SSLCipherSuite ssl_ciphers_value$/, + /SSLCertificateChainFile chainfile$/, + /SSLVerifyClient require/, + ].each do |line| + it do + expect(chef_run).to render_file('/etc/apache2/sites-available/nova-metadata.conf').with_content(line) + end + end + end end + it do - expect(chef_run.execute('nova-metadata apache restart')).to notify('service[apache2]').to(:restart).immediately + expect(chef_run.template('/etc/apache2/sites-available/nova-metadata.conf')).to \ + notify('service[apache2]').to(:restart) + end + + it do + expect(chef_run).to enable_apache2_site('nova-metadata') + end + + it do + expect(chef_run.apache2_site('nova-metadata')).to notify('service[apache2]').to(:restart).immediately end end end diff --git a/spec/api-os-compute-redhat_spec.rb b/spec/api-os-compute-redhat_spec.rb index c6d3eeaa..eaeb0c6e 100644 --- a/spec/api-os-compute-redhat_spec.rb +++ b/spec/api-os-compute-redhat_spec.rb @@ -34,33 +34,5 @@ describe 'openstack-compute::api-os-compute' do it 'stops openstack api now' do expect(chef_run).to stop_service 'openstack-nova-api' end - it do - expect(chef_run).to nothing_execute('Clear nova-api apache restart') - .with( - command: 'rm -f /var/chef/cache/nova-api-apache-restarted' - ) - end - %w( - /etc/nova/nova.conf - /etc/nova/api-paste.ini - /etc/httpd/sites-available/nova-api.conf - ).each do |f| - it "#{f} notifies execute[Clear nova-api apache restart]" do - expect(chef_run.template(f)).to notify('execute[Clear nova-api apache restart]').to(:run).immediately - end - end - it do - expect(chef_run).to run_execute('nova-api apache restart') - .with( - command: 'touch /var/chef/cache/nova-api-apache-restarted', - creates: '/var/chef/cache/nova-api-apache-restarted' - ) - end - it do - expect(chef_run.execute('nova-api apache restart')).to notify('execute[nova-api: restore-selinux-context]').to(:run).immediately - end - it do - expect(chef_run.execute('nova-api apache restart')).to notify('service[apache2]').to(:restart).immediately - end end end diff --git a/spec/api-os-compute_spec.rb b/spec/api-os-compute_spec.rb index 620e5505..640ffa82 100644 --- a/spec/api-os-compute_spec.rb +++ b/spec/api-os-compute_spec.rb @@ -26,42 +26,143 @@ describe 'openstack-compute::api-os-compute' do it 'upgrades openstack api packages' do expect(chef_run).to upgrade_package 'nova-api' + expect(chef_run).to upgrade_package 'python3-nova' end - it 'disables openstack api on boot' do + it do expect(chef_run).to disable_service 'nova-api-os-compute' - end - - it 'stops openstack api now' do expect(chef_run).to stop_service 'nova-api-os-compute' end it do - expect(chef_run).to nothing_execute('Clear nova-api apache restart') - .with( - command: 'rm -f /var/chef/cache/nova-api-apache-restarted' - ) + expect(chef_run).to install_apache2_install('openstack').with(listen: '127.0.0.1:8774') end - %w( - /etc/nova/nova.conf - /etc/nova/api-paste.ini - /etc/apache2/sites-available/nova-api.conf - ).each do |f| - it "#{f} notifies execute[Clear nova-api apache restart]" do - expect(chef_run.template(f)).to notify('execute[Clear nova-api apache restart]').to(:run).immediately + + it do + expect(chef_run).to enable_apache2_module('wsgi') + end + + it do + expect(chef_run).to_not enable_apache2_module('ssl') + end + + it do + expect(chef_run).to create_template('/etc/apache2/sites-available/nova-api.conf').with( + source: 'wsgi-template.conf.erb', + variables: { + ca_certs_path: '', + cert_file: '', + cert_required: false, + chain_file: '', + ciphers: '', + daemon_process: 'nova-api', + group: 'nova', + key_file: '', + log_dir: '/var/log/apache2', + protocol: '', + run_dir: '/var/lock/apache2', + server_entry: '/usr/bin/nova-api-wsgi', + server_host: '127.0.0.1', + server_port: '8774', + user: 'nova', + use_ssl: false, + } + ) + end + [ + /$/, + /WSGIDaemonProcess nova-api processes=2 threads=10 user=nova group=nova display-name=%{GROUP}$/, + /WSGIProcessGroup nova-api$/, + %r{WSGIScriptAlias / /usr/bin/nova-api-wsgi$}, + /WSGIApplicationGroup %{GLOBAL}$/, + %r{ErrorLog /var/log/apache2/nova-api_error.log$}, + %r{CustomLog /var/log/apache2/nova-api_access.log combined$}, + %r{WSGISocketPrefix /var/lock/apache2$}, + ].each do |line| + it do + expect(chef_run).to render_file('/etc/apache2/sites-available/nova-api.conf').with_content(line) end end - it do - expect(chef_run).to run_execute('nova-api apache restart') - .with( - command: 'touch /var/chef/cache/nova-api-apache-restarted', - creates: '/var/chef/cache/nova-api-apache-restarted' - ) + + [ + /SSLEngine On$/, + /SSLCertificateFile/, + /SSLCertificateKeyFile/, + /SSLCACertificatePath/, + /SSLCertificateChainFile/, + /SSLProtocol/, + /SSLCipherSuite/, + /SSLVerifyClient require/, + ].each do |line| + it do + expect(chef_run).to_not render_file('/etc/apache2/sites-available/nova-api.conf').with_content(line) + end end - it do - expect(chef_run.execute('nova-api apache restart')).to notify('execute[nova-api: restore-selinux-context]').to(:run).immediately + + context 'Enable SSL' do + cached(:chef_run) do + node.override['openstack']['compute']['api']['ssl']['enabled'] = true + node.override['openstack']['compute']['api']['ssl']['certfile'] = 'ssl.cert' + node.override['openstack']['compute']['api']['ssl']['keyfile'] = 'ssl.key' + node.override['openstack']['compute']['api']['ssl']['ca_certs_path'] = 'ca_certs_path' + node.override['openstack']['compute']['api']['ssl']['protocol'] = 'ssl_protocol_value' + runner.converge(described_recipe) + end + + it do + expect(chef_run).to enable_apache2_module('ssl') + end + + [ + /SSLEngine On$/, + /SSLCertificateFile ssl.cert$/, + /SSLCertificateKeyFile ssl.key$/, + /SSLCACertificatePath ca_certs_path$/, + /SSLProtocol ssl_protocol_value$/, + ].each do |line| + it do + expect(chef_run).to render_file('/etc/apache2/sites-available/nova-api.conf').with_content(line) + end + end + [ + /SSLCipherSuite/, + /SSLCertificateChainFile/, + /SSLVerifyClient require/, + ].each do |line| + it do + expect(chef_run).to_not render_file('/etc/apache2/sites-available/nova-api.conf').with_content(line) + end + end + context 'Enable chainfile, ciphers & cert_required' do + cached(:chef_run) do + node.override['openstack']['compute']['api']['ssl']['enabled'] = true + node.override['openstack']['compute']['api']['ssl']['ciphers'] = 'ssl_ciphers_value' + node.override['openstack']['compute']['api']['ssl']['chainfile'] = 'chainfile' + node.override['openstack']['compute']['api']['ssl']['cert_required'] = true + runner.converge(described_recipe) + end + [ + /SSLCipherSuite ssl_ciphers_value$/, + /SSLCertificateChainFile chainfile$/, + /SSLVerifyClient require/, + ].each do |line| + it do + expect(chef_run).to render_file('/etc/apache2/sites-available/nova-api.conf').with_content(line) + end + end + end end + it do - expect(chef_run.execute('nova-api apache restart')).to notify('service[apache2]').to(:restart).immediately + expect(chef_run.template('/etc/apache2/sites-available/nova-api.conf')).to \ + notify('service[apache2]').to(:restart) + end + + it do + expect(chef_run).to enable_apache2_site('nova-api') + end + + it do + expect(chef_run.apache2_site('nova-api')).to notify('service[apache2]').to(:restart).immediately end end end diff --git a/spec/placement_api-redhat_spec.rb b/spec/placement_api-redhat_spec.rb new file mode 100644 index 00000000..3a4faa9d --- /dev/null +++ b/spec/placement_api-redhat_spec.rb @@ -0,0 +1,29 @@ +# encoding: UTF-8 + +require_relative 'spec_helper' + +describe 'openstack-compute::placement_api' do + describe 'redhat' do + let(:runner) { ChefSpec::SoloRunner.new(REDHAT_OPTS) } + let(:node) { runner.node } + cached(:chef_run) { runner.converge(described_recipe) } + + include_context 'compute_stubs' + include_examples 'expect_runs_nova_common_recipe' + include_examples 'expect_creates_nova_state_dir' + include_examples 'expect_creates_nova_lock_dir' + + it 'upgrades placement packages' do + expect(chef_run).to upgrade_package 'openstack-nova-placement-api' + end + + it do + expect(chef_run).to disable_service 'openstack-nova-placement-api' + expect(chef_run).to stop_service 'openstack-nova-placement-api' + end + + it do + expect(chef_run).to_not disable_apache2_site('nova-placement-api') + end + end +end diff --git a/spec/placement_api_spec.rb b/spec/placement_api_spec.rb index 9818dcb9..a0e4ee63 100644 --- a/spec/placement_api_spec.rb +++ b/spec/placement_api_spec.rb @@ -14,8 +14,10 @@ describe 'openstack-compute::placement_api' do expect(chef_run).to include_recipe 'openstack-compute::nova-common' end - it 'upgrades package nova-placement-api' do + it 'upgrades placement packages' do expect(chef_run).to upgrade_package 'nova-placement-api' + expect(chef_run).to upgrade_package 'python3-nova' + expect(chef_run).to upgrade_package 'libapache2-mod-wsgi-py3' end it 'executes placement-api: nova-manage api_db sync' do @@ -27,32 +29,145 @@ describe 'openstack-compute::placement_api' do ) end - it 'disables nova-placement-api service' do - expect(chef_run).to disable_service 'disable nova-placement-api service' - end it do - expect(chef_run).to nothing_execute('Clear nova-placement-api apache restart') - .with( - command: 'rm -f /var/chef/cache/nova-placement-api-apache-restarted' - ) + expect(chef_run).to disable_service 'nova-placement-api' + expect(chef_run).to stop_service 'nova-placement-api' end - %w( - /etc/nova/nova.conf - /etc/apache2/sites-available/nova-placement-api.conf - ).each do |f| - it "#{f} notifies execute[Clear nova-placement-api apache restart]" do - expect(chef_run.template(f)).to notify('execute[Clear nova-placement-api apache restart]').to(:run).immediately + + it do + expect(chef_run).to disable_apache2_site('nova-placement-api') + end + + it do + expect(chef_run).to install_apache2_install('openstack').with(listen: '127.0.0.1:8778') + end + + it do + expect(chef_run).to enable_apache2_module('wsgi') + end + + it do + expect(chef_run).to_not enable_apache2_module('ssl') + end + + it do + expect(chef_run).to create_template('/etc/apache2/sites-available/nova-placement.conf').with( + source: 'wsgi-template.conf.erb', + variables: { + ca_certs_path: '', + cert_file: '', + cert_required: false, + chain_file: '', + ciphers: '', + daemon_process: 'placement-api', + group: 'nova', + key_file: '', + log_dir: '/var/log/apache2', + protocol: '', + run_dir: '/var/lock/apache2', + server_entry: '/usr/bin/nova-placement-api', + server_host: '127.0.0.1', + server_port: '8778', + user: 'nova', + use_ssl: false, + } + ) + end + [ + /$/, + /WSGIDaemonProcess placement-api processes=2 threads=10 user=nova group=nova display-name=%{GROUP}$/, + /WSGIProcessGroup placement-api$/, + %r{WSGIScriptAlias / /usr/bin/nova-placement-api$}, + /WSGIApplicationGroup %{GLOBAL}$/, + %r{ErrorLog /var/log/apache2/placement-api_error.log$}, + %r{CustomLog /var/log/apache2/placement-api_access.log combined$}, + %r{WSGISocketPrefix /var/lock/apache2$}, + ].each do |line| + it do + expect(chef_run).to render_file('/etc/apache2/sites-available/nova-placement.conf').with_content(line) end end - it do - expect(chef_run).to run_execute('nova-placement-api apache restart') - .with( - command: 'touch /var/chef/cache/nova-placement-api-apache-restarted', - creates: '/var/chef/cache/nova-placement-api-apache-restarted' - ) + + [ + /SSLEngine On$/, + /SSLCertificateFile/, + /SSLCertificateKeyFile/, + /SSLCACertificatePath/, + /SSLCertificateChainFile/, + /SSLProtocol/, + /SSLCipherSuite/, + /SSLVerifyClient require/, + ].each do |line| + it do + expect(chef_run).to_not render_file('/etc/apache2/sites-available/nova-placement.conf').with_content(line) + end end + + context 'Enable SSL' do + cached(:chef_run) do + node.override['openstack']['compute']['placement']['ssl']['enabled'] = true + node.override['openstack']['compute']['placement']['ssl']['certfile'] = 'ssl.cert' + node.override['openstack']['compute']['placement']['ssl']['keyfile'] = 'ssl.key' + node.override['openstack']['compute']['placement']['ssl']['ca_certs_path'] = 'ca_certs_path' + node.override['openstack']['compute']['placement']['ssl']['protocol'] = 'ssl_protocol_value' + runner.converge(described_recipe) + end + + it do + expect(chef_run).to enable_apache2_module('ssl') + end + + [ + /SSLEngine On$/, + /SSLCertificateFile ssl.cert$/, + /SSLCertificateKeyFile ssl.key$/, + /SSLCACertificatePath ca_certs_path$/, + /SSLProtocol ssl_protocol_value$/, + ].each do |line| + it do + expect(chef_run).to render_file('/etc/apache2/sites-available/nova-placement.conf').with_content(line) + end + end + [ + /SSLCipherSuite/, + /SSLCertificateChainFile/, + /SSLVerifyClient require/, + ].each do |line| + it do + expect(chef_run).to_not render_file('/etc/apache2/sites-available/nova-placement.conf').with_content(line) + end + end + context 'Enable chainfile, ciphers & cert_required' do + cached(:chef_run) do + node.override['openstack']['compute']['placement']['ssl']['enabled'] = true + node.override['openstack']['compute']['placement']['ssl']['ciphers'] = 'ssl_ciphers_value' + node.override['openstack']['compute']['placement']['ssl']['chainfile'] = 'chainfile' + node.override['openstack']['compute']['placement']['ssl']['cert_required'] = true + runner.converge(described_recipe) + end + [ + /SSLCipherSuite ssl_ciphers_value$/, + /SSLCertificateChainFile chainfile$/, + /SSLVerifyClient require/, + ].each do |line| + it do + expect(chef_run).to render_file('/etc/apache2/sites-available/nova-placement.conf').with_content(line) + end + end + end + end + it do - expect(chef_run.execute('nova-placement-api apache restart')).to notify('service[apache2]').to(:restart).immediately + expect(chef_run.template('/etc/apache2/sites-available/nova-placement.conf')).to \ + notify('service[apache2]').to(:restart) + end + + it do + expect(chef_run).to enable_apache2_site('nova-placement') + end + + it do + expect(chef_run.apache2_site('nova-placement')).to notify('service[apache2]').to(:restart).immediately end end end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 2761bea0..476b437b 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -93,6 +93,38 @@ shared_context 'compute_stubs' do stub_command('nova-manage cell_v2 list_cells | grep -q cell1').and_return(false) stub_command('nova-manage cell_v2 discover_hosts').and_return(true) stub_command("[ ! -e /etc/httpd/conf/httpd.conf ] && [ -e /etc/redhat-release ] && [ $(/sbin/sestatus | grep -c '^Current mode:.*enforcing') -eq 1 ]").and_return(true) + # 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(:memcached_servers) + .and_return([]) + 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('test-passes') end end diff --git a/templates/default/wsgi-template.conf.erb b/templates/default/wsgi-template.conf.erb index 97e9c7b7..aa083a65 100644 --- a/templates/default/wsgi-template.conf.erb +++ b/templates/default/wsgi-template.conf.erb @@ -1,11 +1,9 @@ <%= node['openstack']['compute']['custom_template_banner'] %> -Listen <%= @params[:server_host] %>:<%= @params[:server_port] %> - -:<%= @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 @@ -14,29 +12,25 @@ Listen <%= @params[:server_host] %>:<%= @params[:server_port] %> 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] %> + SSLCertificateFile <%= @cert_file %> + SSLCertificateKeyFile <%= @key_file %> + SSLCACertificatePath <%= @ca_certs_path %> +<% unless @chain_file.empty? %> + SSLCertificateChainFile <%= @chain_file %> <% end -%> - SSLProtocol <%= @params[:protocol] %> -<% if @params[:ciphers] -%> - SSLCipherSuite <%= @params[:ciphers] %> + SSLProtocol <%= @protocol %> +<% unless @ciphers.empty? -%> + SSLCipherSuite <%= @ciphers %> <% end -%> -<% if @params[:cert_required] -%> +<% if @cert_required -%> SSLVerifyClient require <% end -%> <% end -%> -WSGISocketPrefix <%= @params[:run_dir] -%> - +WSGISocketPrefix <%= @run_dir -%>