Add recipe to deploy Compute service placement-api

The placement-api has been added by nova for the Newton cycle, it has
become mandatory for Ocata.

It is deployed as a wsgi app similar to what we have for keystone and
gnocchi already.

Change-Id: I1d1f1cc7046cb30a91894a0c884bc861d7f3dd95
This commit is contained in:
Jens Rosenboom 2017-02-21 16:53:04 +01:00
parent 206df1c452
commit dc339a859d
13 changed files with 317 additions and 49 deletions

View File

@ -1,6 +1,6 @@
# This configuration was generated by
# `rubocop --auto-gen-config`
# on 2017-02-23 16:58:25 +0100 using RuboCop version 0.39.0.
# on 2017-03-06 14:33:48 +0000 using RuboCop version 0.39.0.
# The point is for the user to remove these configuration records
# one by one as the offenses are removed from the code base.
# Note that changes in the inspected code, or installation of new
@ -15,7 +15,7 @@ Metrics/AbcSize:
Metrics/MethodLength:
Max: 19
# Offense count: 7
# Offense count: 8
# Configuration parameters: EnforcedStyle, SupportedStyles.
# SupportedStyles: nested, compact
Style/ClassAndModuleChildren:
@ -27,8 +27,9 @@ Style/ClassAndModuleChildren:
- 'recipes/libvirt_rbd.rb'
- 'recipes/nova-common.rb'
- 'recipes/nova-setup.rb'
- 'recipes/placement_api.rb'
# Offense count: 6
# Offense count: 7
Style/Documentation:
Exclude:
- 'spec/**/*'
@ -39,6 +40,7 @@ Style/Documentation:
- 'recipes/identity_registration.rb'
- 'recipes/libvirt_rbd.rb'
- 'recipes/nova-setup.rb'
- 'recipes/placement_api.rb'
# Offense count: 1
# Configuration parameters: MinBodyLength.
@ -53,3 +55,10 @@ Style/GuardClause:
Style/Next:
Exclude:
- 'recipes/libvirt.rb'
# Offense count: 8
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle, SupportedStyles, ConsistentQuotesInMultiline.
# SupportedStyles: single_quotes, double_quotes
Style/StringLiterals:
Enabled: false

View File

@ -124,14 +124,24 @@ default['openstack']['compute']['api']['auth']['version'] = node['openstack']['a
# A PEM encoded Certificate Authority to use when verifying HTTPs connections.
default['openstack']['compute']['api']['auth']['cafile'] = nil
# Keystone PKI signing directories
default['openstack']['compute']['api']['auth']['cache_dir'] = '/var/cache/nova/api'
# Placement API settings
default['openstack']['placement']['ssl']['enabled'] = false
default['openstack']['placement']['ssl']['certfile'] = ''
default['openstack']['placement']['ssl']['chainfile'] = ''
default['openstack']['placement']['ssl']['keyfile'] = ''
default['openstack']['placement']['ssl']['ca_certs_path'] = ''
default['openstack']['placement']['ssl']['cert_required'] = false
default['openstack']['placement']['ssl']['protocol'] = ''
default['openstack']['placement']['ssl']['ciphers'] = ''
# Platform specific settings
case platform_family
when 'rhel' # :pragma-foodcritic: ~FC024 - won't fix this
default['openstack']['compute']['platform'] = {
'api_os_compute_packages' => ['openstack-nova-api'],
'api_os_compute_service' => 'openstack-nova-api',
'api_placement_packages' => ['nova-placement-api'],
'api_placement_service' => 'nova-placement-api',
'memcache_python_packages' => ['python-memcached'],
'compute_api_metadata_packages' => ['openstack-nova-api'],
'compute_api_metadata_service' => 'openstack-nova-metadata-api',
@ -165,6 +175,8 @@ when 'debian'
default['openstack']['compute']['platform'] = {
'api_os_compute_packages' => ['nova-api-os-compute'],
'api_os_compute_service' => 'nova-api-os-compute',
'api_placement_packages' => ['nova-placement-api'],
'api_placement_service' => 'nova-placement-api',
'memcache_python_packages' => ['python-memcache'],
'compute_api_metadata_packages' => ['nova-api-metadata'],
'compute_api_metadata_service' => 'nova-api-metadata',
@ -237,6 +249,10 @@ end
default['openstack']['endpoints'][type]['compute-serial-proxy']['port'] = '6083'
default['openstack']['endpoints'][type]['compute-serial-proxy']['path'] = '/'
default['openstack']['endpoints'][type]['compute-serial-proxy']['host'] = '127.0.0.1'
# The OpenStack Compute (Nova) Placement API endpoint
default['openstack']['endpoints'][type]['placement-api']['port'] = '8778'
default['openstack']['endpoints'][type]['placement-api']['path'] = ''
default['openstack']['endpoints'][type]['placement-api']['host'] = '127.0.0.1'
end
default['openstack']['bind_service']['all']['compute-serial-proxy']['host'] = '127.0.0.1'
default['openstack']['bind_service']['all']['compute-vnc-proxy']['host'] = '127.0.0.1'
@ -247,3 +263,5 @@ default['openstack']['bind_service']['all']['compute-serial-proxy']['port'] = '6
default['openstack']['bind_service']['all']['compute-novnc']['port'] = '6080'
default['openstack']['bind_service']['all']['compute-metadata-api']['port'] = '8775'
default['openstack']['bind_service']['all']['compute-api']['port'] = '8774'
default['openstack']['bind_service']['all']['placement-api']['port'] = '8778'
default['openstack']['bind_service']['all']['placement-api']['host'] = '127.0.0.1'

View File

@ -20,7 +20,6 @@ default['openstack']['compute']['conf'].tap do |conf|
conf['DEFAULT']['dns_server'] = '8.8.8.8' # [] in docs
# [keystone_authtoken]
conf['keystone_authtoken']['signing_dir'] = '/var/cache/nova/api'
conf['keystone_authtoken']['auth_type'] = 'v3password'
conf['keystone_authtoken']['region_name'] = node['openstack']['region']
conf['keystone_authtoken']['username'] = 'nova'
@ -59,4 +58,12 @@ default['openstack']['compute']['conf'].tap do |conf|
# [oslo_concurrency] section
conf['oslo_concurrency']['lock_path'] = "#{node['openstack']['compute']['conf']['DEFAULT']['state_path']}/lock"
# [placement] section
conf['placement']['auth_type'] = 'password'
conf['placement']['os_region_name'] = node['openstack']['region']
conf['placement']['username'] = 'placement'
conf['placement']['user_domain_name'] = 'Default'
conf['placement']['project_domain_name'] = 'Default'
conf['placement']['project_name'] = 'service'
end

View File

@ -26,12 +26,6 @@ include_recipe 'openstack-compute::nova-common'
platform_options = node['openstack']['compute']['platform']
directory ::File.dirname(node['openstack']['compute']['conf']['keystone_authtoken']['signing_dir']) do
owner node['openstack']['compute']['user']
group node['openstack']['compute']['group']
mode 00700
end
platform_options['api_os_compute_packages'].each do |pkg|
package pkg do
options platform_options['package_overrides']

View File

@ -31,9 +31,15 @@ interfaces = {
internal: { url: internal_endpoint('compute-api') },
admin: { url: admin_endpoint('compute-api') }
}
placement_interfaces = {
public: { url: public_endpoint('placement-api') },
internal: { url: internal_endpoint('placement-api') }
}
auth_url = ::URI.decode identity_admin_endpoint.to_s
service_pass = get_password 'service', 'openstack-compute'
service_user = node['openstack']['compute']['conf']['keystone_authtoken']['username']
placement_service_pass = get_password 'service', 'openstack-placement'
placement_service_user = node['openstack']['compute']['conf']['placement']['username']
service_role = node['openstack']['compute']['service_role']
service_project_name = node['openstack']['compute']['conf']['keystone_authtoken']['project_name']
service_domain_name = node['openstack']['compute']['conf']['keystone_authtoken']['user_domain_name']
@ -52,15 +58,20 @@ connection_params = {
openstack_username: admin_user,
openstack_api_key: admin_pass,
openstack_project_name: admin_project,
openstack_domain_name: admin_domain
openstack_domain_name: admin_domain
}
# Register Compute Service
# Register Compute Services
openstack_service 'nova' do
type 'compute'
connection_params connection_params
end
openstack_service 'nova-placement' do
type 'placement'
connection_params connection_params
end
interfaces.each do |interface, res|
# Register Compute Endpoints
openstack_endpoint 'compute' do
@ -72,12 +83,22 @@ interfaces.each do |interface, res|
end
end
# Register Service Tenant
placement_interfaces.each do |interface, res|
openstack_endpoint 'placement' do
service_name 'nova-placement'
interface interface.to_s
url res[:url].to_s
region region
connection_params connection_params
end
end
# Register Service Project
openstack_project service_project_name do
connection_params connection_params
end
# Register Service User
# Register Service Users
openstack_user service_user do
project_name service_project_name
role_name service_role
@ -85,18 +106,27 @@ openstack_user service_user do
connection_params connection_params
end
## Grant Service role to Service User for Service Tenant ##
openstack_user service_user do
role_name service_role
openstack_user placement_service_user do
project_name service_project_name
role_name service_role
password placement_service_pass
connection_params connection_params
action :grant_role
end
openstack_user service_user do
domain_name service_domain_name
role_name service_role
user_name service_user
connection_params connection_params
action :grant_domain
## Grant Service role to Service Users for Service Project ##
[service_user, placement_service_user].each do |user|
openstack_user user do
role_name service_role
project_name service_project_name
connection_params connection_params
action :grant_role
end
openstack_user user do
domain_name service_domain_name
role_name service_role
user_name user
connection_params connection_params
action :grant_domain
end
end

View File

@ -155,6 +155,10 @@ node.default['openstack']['compute']['conf_secrets']
.[]('keystone_authtoken')['password'] =
get_password 'service', 'openstack-compute'
node.default['openstack']['compute']['conf_secrets']
.[]('placement')['password'] =
get_password 'service', 'openstack-placement'
node.default['openstack']['compute']['conf'].tap do |conf|
conf['DEFAULT']['iscsi_helper'] = platform_options['iscsi_helper']
# conf['DEFAULT']['scheduler_default_filters'] = node['openstack']['compute']['scheduler']['default_filters'].join(',')
@ -186,6 +190,9 @@ node.default['openstack']['compute']['conf'].tap do |conf|
# [keystone_authtoken] section
conf['keystone_authtoken']['auth_url'] = auth_url
# [placement] section
conf['placement']['auth_url'] = auth_url
# [glance] section
conf['glance']['api_servers'] =
"#{image_endpoint.scheme}://#{image_endpoint.host}:#{image_endpoint.port}"

71
recipes/placement_api.rb Normal file
View File

@ -0,0 +1,71 @@
# encoding: UTF-8
#
# Cookbook Name:: openstack-compute
# Recipe:: placement-api
#
# Copyright 2017, OpenStack Foundation
#
# 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 ::Chef::Recipe
include ::Openstack
end
include_recipe 'openstack-compute::nova-common'
platform_options = node['openstack']['compute']['platform']
platform_options['api_placement_packages'].each do |pkg|
package pkg do
options platform_options['package_overrides']
action :upgrade
end
end
nova_user = node['openstack']['compute']['user']
nova_group = node['openstack']['compute']['group']
execute 'placement-api: nova-manage api_db sync' do
timeout node['openstack']['compute']['dbsync_timeout']
user nova_user
group nova_group
command 'nova-manage api_db sync'
action :run
end
service 'disable nova-placement-api service' do
service_name platform_options['api_placement_service']
supports status: true, restart: true
action [:disable, :stop]
end
bind_service = node['openstack']['bind_service']['all']['placement-api']
web_app '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']
user node['openstack']['compute']['user']
group node['openstack']['compute']['group']
use_ssl node['openstack']['placement']['ssl']['enabled']
cert_file node['openstack']['placement']['ssl']['certfile']
chain_file node['openstack']['placement']['ssl']['chainfile']
key_file node['openstack']['placement']['ssl']['keyfile']
ca_certs_path node['openstack']['placement']['ssl']['ca_certs_path']
cert_required node['openstack']['placement']['ssl']['cert_required']
protocol node['openstack']['placement']['ssl']['protocol']
ciphers node['openstack']['placement']['ssl']['ciphers']
end

View File

@ -14,14 +14,6 @@ describe 'openstack-compute::api-os-compute' do
include_examples 'expect_creates_nova_lock_dir'
include_examples 'expect_creates_api_paste_template'
it 'creates the /var/cache/nova directory' do
expect(chef_run).to create_directory('/var/cache/nova').with(
user: 'nova',
group: 'nova',
mode: 0700
)
end
it do
expect(chef_run).to run_execute('nova-manage api_db sync')
.with(timeout: 3600,

View File

@ -26,6 +26,11 @@ describe 'openstack-compute::identity_registration' do
role_name = 'admin'
password = 'nova-pass'
domain_name = 'Default'
placement_service_name = 'nova-placement'
placement_service_type = 'placement'
placement_service_user = 'placement'
placement_password = 'placement-pass'
placement_url = 'http://127.0.0.1:8778'
it "registers #{project_name} Project" do
expect(chef_run).to create_openstack_project(
@ -44,9 +49,18 @@ describe 'openstack-compute::identity_registration' do
)
end
it "registers placement service" do
expect(chef_run).to create_openstack_service(
placement_service_name
).with(
connection_params: connection_params,
type: placement_service_type
)
end
context "registers #{service_name} endpoint" do
%w(admin internal public).each do |interface|
it "#{interface} endpoint with default values" do
it "creates #{interface} endpoint with default values" do
expect(chef_run).to create_openstack_endpoint(
service_type
).with(
@ -60,7 +74,23 @@ describe 'openstack-compute::identity_registration' do
end
end
it 'registers service user' do
context "registers placement endpoint" do
%w(internal public).each do |interface|
it "creates #{interface} endpoint with default values" do
expect(chef_run).to create_openstack_endpoint(
placement_service_type
).with(
service_name: placement_service_name,
# interface: interface,
url: placement_url,
region: region,
connection_params: connection_params
)
end
end
end
it 'registers nova service user' do
expect(chef_run).to create_openstack_user(
service_user
).with(
@ -71,25 +101,39 @@ describe 'openstack-compute::identity_registration' do
)
end
it do
expect(chef_run).to grant_domain_openstack_user(
service_user
it 'registers placement service user' do
expect(chef_run).to create_openstack_user(
placement_service_user
).with(
domain_name: domain_name,
project_name: project_name,
role_name: role_name,
password: placement_password,
connection_params: connection_params
)
end
it do
expect(chef_run).to grant_role_openstack_user(
service_user
).with(
project_name: project_name,
role_name: role_name,
password: password,
connection_params: connection_params
)
context "grants user roles" do
[service_user, placement_service_user].each do |user_name|
it do
expect(chef_run).to grant_domain_openstack_user(
user_name
).with(
domain_name: domain_name,
role_name: role_name,
connection_params: connection_params
)
end
it do
expect(chef_run).to grant_role_openstack_user(
user_name
).with(
project_name: project_name,
role_name: role_name,
connection_params: connection_params
)
end
end
end
end
end

View File

@ -136,6 +136,23 @@ describe 'openstack-compute::nova-common' do
end
end
context 'placement' do
it 'has correct authentication settings' do
[
'auth_type = password',
'os_region_name = RegionOne',
'password = placement-pass',
'username = placement',
'project_name = service',
'user_domain_name = Default',
'project_domain_name = Default'
].each do |line|
expect(chef_run).to render_config_file(file.name)\
.with_section_content('placement', /^#{Regexp.quote(line)}$/)
end
end
end
it 'uses default values for attributes' do
[

View File

@ -0,0 +1,34 @@
# encoding: UTF-8
require_relative 'spec_helper'
describe 'openstack-compute::placement_api' do
describe 'ubuntu' do
let(:runner) { ChefSpec::SoloRunner.new(UBUNTU_OPTS) }
let(:node) { runner.node }
let(:chef_run) { runner.converge(described_recipe) }
include_context 'compute_stubs'
it "includes nova-common recipe" do
expect(chef_run).to include_recipe 'openstack-compute::nova-common'
end
it "upgrades package nova-placement-api" do
expect(chef_run).to upgrade_package 'nova-placement-api'
end
it "executes placement-api: nova-manage api_db sync" do
expect(chef_run).to run_execute('placement-api: nova-manage api_db sync').with(
timeout: 3600,
user: 'nova',
group: 'nova',
command: 'nova-manage api_db sync'
)
end
it "disables nova-placement-api service" do
expect(chef_run).to disable_service 'disable nova-placement-api service'
end
end
end

View File

@ -70,6 +70,9 @@ shared_context 'compute_stubs' do
allow_any_instance_of(Chef::Recipe).to receive(:get_password)
.with('service', 'openstack-network')
.and_return('neutron-pass')
allow_any_instance_of(Chef::Recipe).to receive(:get_password)
.with('service', 'openstack-placement')
.and_return('placement-pass')
allow_any_instance_of(Chef::Recipe).to receive(:get_password)
.with('service', 'rbd_block_storage')
.and_return 'cinder-rbd-pass'
@ -82,6 +85,7 @@ shared_context 'compute_stubs' do
# stub_command('nova-manage network list | grep 192.168.100.0/24').and_return(false)
# stub_command('nova-manage network list | grep 192.168.200.0/24').and_return(false)
# stub_command("nova-manage floating list |grep -E '.*([0-9]{1,3}[.]){3}[0-9]{1,3}*'").and_return(false)
stub_command("/usr/sbin/apache2 -t").and_return(true)
stub_command('virsh net-list | grep -q default').and_return(true)
stub_command('ovs-vsctl br-exists br-int').and_return(true)
stub_command('ovs-vsctl br-exists br-tun').and_return(true)

View File

@ -0,0 +1,41 @@
<%= node["openstack"]["compute"]["custom_template_banner"] %>
Listen <%= @params[:server_host] %>:<%= @params[:server_port] %>
<VirtualHost <%= @params[:server_host] %>:<%= @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] %>
WSGIApplicationGroup %{GLOBAL}
WSGIPassAuthorization On
<Directory /usr/bin>
Require all granted
</Directory>
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 -%>
<% 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 -%>
<% end -%>
</VirtualHost>
WSGISocketPrefix /var/run/apache2