diff --git a/manifests/db.pp b/manifests/db.pp index e3d5e4a01..14d2555c8 100644 --- a/manifests/db.pp +++ b/manifests/db.pp @@ -42,6 +42,14 @@ # (optional) Connection url to connect to nova api slave database (read-only). # Defaults to $::os_service_default # +# [*placement_database_connection*] +# (optional) Connection url to connect to nova placement database. +# Defaults to $::os_service_default +# +# [*placement_slave_connection*] +# (optional) Connection url to connect to nova placement slave database (read-only). +# Defaults to $::os_service_default +# # [*database_idle_timeout*] # Timeout when db connections should be reaped. # (Optional) Defaults to $::os_service_default @@ -68,17 +76,19 @@ # (Optional) Defaults to $::os_service_default # class nova::db ( - $database_db_max_retries = $::os_service_default, - $database_connection = $::os_service_default, - $slave_connection = $::os_service_default, - $api_database_connection = $::os_service_default, - $api_slave_connection = $::os_service_default, - $database_idle_timeout = $::os_service_default, - $database_min_pool_size = $::os_service_default, - $database_max_pool_size = $::os_service_default, - $database_max_retries = $::os_service_default, - $database_retry_interval = $::os_service_default, - $database_max_overflow = $::os_service_default, + $database_db_max_retries = $::os_service_default, + $database_connection = $::os_service_default, + $slave_connection = $::os_service_default, + $api_database_connection = $::os_service_default, + $api_slave_connection = $::os_service_default, + $placement_database_connection = $::os_service_default, + $placement_slave_connection = $::os_service_default, + $database_idle_timeout = $::os_service_default, + $database_min_pool_size = $::os_service_default, + $database_max_pool_size = $::os_service_default, + $database_max_retries = $::os_service_default, + $database_retry_interval = $::os_service_default, + $database_max_overflow = $::os_service_default, ) { include ::nova::deps @@ -90,6 +100,8 @@ class nova::db ( $slave_connection_real = pick($::nova::slave_connection, $slave_connection) $api_database_connection_real = pick($::nova::api_database_connection, $api_database_connection) $api_slave_connection_real = pick($::nova::api_slave_connection, $api_slave_connection) + $placement_database_connection_real = pick($::nova::placement_database_connection, $placement_database_connection) + $placement_slave_connection_real = pick($::nova::placement_slave_connection, $placement_slave_connection) $database_idle_timeout_real = pick($::nova::database_idle_timeout, $database_idle_timeout) $database_min_pool_size_real = pick($::nova::database_min_pool_size, $database_min_pool_size) $database_max_pool_size_real = pick($::nova::database_max_pool_size, $database_max_pool_size) @@ -127,4 +139,16 @@ class nova::db ( } + if !is_service_default($placement_database_connection_real) { + + validate_re($placement_database_connection_real, + '^(sqlite|mysql(\+pymysql)?|postgresql):\/\/(\S+:\S+@\S+\/\S+)?') + + nova_config { + 'placement_database/connection': value => $placement_database_connection_real, secret => true; + 'placement_database/slave_connection': value => $placement_slave_connection_real, secret => true; + } + + } + } diff --git a/manifests/db/mysql_placement.pp b/manifests/db/mysql_placement.pp new file mode 100644 index 000000000..62615788f --- /dev/null +++ b/manifests/db/mysql_placement.pp @@ -0,0 +1,59 @@ +# == Class: nova::db::mysql_placement +# +# Class that configures mysql for the nova_placement database. +# +# === Parameters: +# +# [*password*] +# Password to use for the nova user +# +# [*dbname*] +# (optional) The name of the database +# Defaults to 'nova_placement' +# +# [*user*] +# (optional) The mysql user to create +# Defaults to 'nova_placement' +# +# [*host*] +# (optional) The IP address of the mysql server +# Defaults to '127.0.0.1' +# +# [*charset*] +# (optional) The charset to use for the nova database +# Defaults to 'utf8' +# +# [*collate*] +# (optional) The collate to use for the nova database +# Defaults to 'utf8_general_ci' +# +# [*allowed_hosts*] +# (optional) Additional hosts that are allowed to access this DB +# Defaults to undef +# +class nova::db::mysql_placement( + $password, + $dbname = 'nova_placement', + $user = 'nova_placement', + $host = '127.0.0.1', + $charset = 'utf8', + $collate = 'utf8_general_ci', + $allowed_hosts = undef, +) { + + include ::nova::deps + + ::openstacklib::db::mysql { 'nova_placement': + user => $user, + password_hash => mysql_password($password), + dbname => $dbname, + host => $host, + charset => $charset, + collate => $collate, + allowed_hosts => $allowed_hosts, + } + + Anchor['nova::db::begin'] + ~> Class['nova::db::mysql_placement'] + ~> Anchor['nova::db::end'] +} diff --git a/manifests/init.pp b/manifests/init.pp index 5a3de38cd..625d463da 100644 --- a/manifests/init.pp +++ b/manifests/init.pp @@ -25,6 +25,14 @@ # (optional) Connection url to connect to nova API slave database (read-only). # Defaults to undef. # +# [*placement_database_connection*] +# (optional) Connection url for the nova placement database. +# Defaults to undef. +# +# [*placement_slave_connection*] +# (optional) Connection url to connect to nova placement slave database (read-only). +# Defaults to undef. +# # [*database_max_retries*] # (optional) Maximum database connection retries during startup. # Defaults to undef. @@ -427,6 +435,8 @@ class nova( $slave_connection = undef, $api_database_connection = undef, $api_slave_connection = undef, + $placement_database_connection = undef, + $placement_slave_connection = undef, $block_device_allocate_retries = $::os_service_default, $block_device_allocate_retries_interval = $::os_service_default, $database_idle_timeout = undef, diff --git a/releasenotes/notes/nova-placement-30566167309fd124.yaml b/releasenotes/notes/nova-placement-30566167309fd124.yaml index 6fe5ff3b3..8104143de 100644 --- a/releasenotes/notes/nova-placement-30566167309fd124.yaml +++ b/releasenotes/notes/nova-placement-30566167309fd124.yaml @@ -3,5 +3,6 @@ features: - Nova Placement API deployment in WSGI with Apache by using nova::wsgi::apache_placement. - Keystone resources support for Nova Placement API by using nova::keystone::auth_placement. - Allow to configure [placement] section in nova.conf by using nova::placement. + - Allow to create and use a database dedicated for Nova Placement (recommended). deprecations: - nova::wsgi::apache is deprecated in favor of nova::wsgi::apache_api. diff --git a/spec/acceptance/nova_wsgi_apache_spec.rb b/spec/acceptance/nova_wsgi_apache_spec.rb index 0e9a12c70..d388fcf91 100644 --- a/spec/acceptance/nova_wsgi_apache_spec.rb +++ b/spec/acceptance/nova_wsgi_apache_spec.rb @@ -29,12 +29,13 @@ describe 'basic nova' do # Nova resources class { '::nova': - database_connection => 'mysql+pymysql://nova:a_big_secret@127.0.0.1/nova?charset=utf8', - api_database_connection => 'mysql+pymysql://nova_api:a_big_secret@127.0.0.1/nova_api?charset=utf8', - default_transport_url => 'rabbit://nova:an_even_bigger_secret@127.0.0.1:5672/', - image_service => 'nova.image.glance.GlanceImageService', - glance_api_servers => 'localhost:9292', - debug => true, + database_connection => 'mysql+pymysql://nova:a_big_secret@127.0.0.1/nova?charset=utf8', + api_database_connection => 'mysql+pymysql://nova_api:a_big_secret@127.0.0.1/nova_api?charset=utf8', + placement_database_connection => 'mysql+pymysql://nova_placement:a_big_secret@127.0.0.1/nova_placement?charset=utf8', + default_transport_url => 'rabbit://nova:an_even_bigger_secret@127.0.0.1:5672/', + image_service => 'nova.image.glance.GlanceImageService', + glance_api_servers => 'localhost:9292', + debug => true, } class { '::nova::db::mysql': password => 'a_big_secret', @@ -42,6 +43,9 @@ describe 'basic nova' do class { '::nova::db::mysql_api': password => 'a_big_secret', } + class { '::nova::db::mysql_placement': + password => 'a_big_secret', + } class { '::nova::keystone::auth': password => 'a_big_secret', } diff --git a/spec/classes/nova_db_mysql_placement_spec.rb b/spec/classes/nova_db_mysql_placement_spec.rb new file mode 100644 index 000000000..7abf1462f --- /dev/null +++ b/spec/classes/nova_db_mysql_placement_spec.rb @@ -0,0 +1,85 @@ +require 'spec_helper' + +describe 'nova::db::mysql_placement' do + + shared_examples_for 'nova::db::mysql_placement' do + + let :pre_condition do + 'include mysql::server' + end + + let :required_params do + { :password => "qwerty" } + end + + context 'with only required params' do + let :params do + required_params + end + it { is_expected.to contain_openstacklib__db__mysql('nova_placement').with( + :user => 'nova_placement', + :password_hash => '*AA1420F182E88B9E5F874F6FBE7459291E8F4601', + :charset => 'utf8', + :collate => 'utf8_general_ci', + )} + end + + context 'overriding allowed_hosts param to array' do + let :params do + { :password => 'novapass', + :allowed_hosts => ['127.0.0.1','%'], + }.merge(required_params) + end + + it { is_expected.to contain_openstacklib__db__mysql('nova_placement').with( + :user => 'nova_placement', + :password_hash => '*AA1420F182E88B9E5F874F6FBE7459291E8F4601', + :charset => 'utf8', + :collate => 'utf8_general_ci', + :allowed_hosts => ['127.0.0.1','%'], + )} + end + + context 'overriding allowed_hosts param to string' do + let :params do + { :password => 'novapass2', + :allowed_hosts => '192.168.1.1', + }.merge(required_params) + end + + it { is_expected.to contain_openstacklib__db__mysql('nova_placement').with( + :user => 'nova_placement', + :password_hash => '*AA1420F182E88B9E5F874F6FBE7459291E8F4601', + :charset => 'utf8', + :collate => 'utf8_general_ci', + :allowed_hosts => '192.168.1.1', + )} + end + + context 'when overriding charset' do + let :params do + { :password => 'novapass', + :charset => 'latin1', + }.merge(required_params) + end + + it { is_expected.to contain_openstacklib__db__mysql('nova_placement').with( + :charset => 'latin1', + )} + end + + end + + on_supported_os({ + :supported_os => OSDefaults.get_supported_os + }).each do |os,facts| + context "on #{os}" do + let (:facts) do + facts.merge!(OSDefaults.get_facts()) + end + + it_configures 'nova::db::mysql_placement' + end + end + +end diff --git a/spec/classes/nova_db_spec.rb b/spec/classes/nova_db_spec.rb index 731d44506..d1d71d301 100644 --- a/spec/classes/nova_db_spec.rb +++ b/spec/classes/nova_db_spec.rb @@ -14,6 +14,8 @@ describe 'nova::db' do it { is_expected.to_not contain_nova_config('database/slave_connection') } it { is_expected.to_not contain_nova_config('api_database/connection') } it { is_expected.to_not contain_nova_config('api_database/slave_connection') } + it { is_expected.to_not contain_nova_config('placement_database/connection') } + it { is_expected.to_not contain_nova_config('placement_database/slave_connection') } it { is_expected.to_not contain_nova_config('database/idle_timeout') } it { is_expected.to_not contain_nova_config('database/min_pool_size') } it { is_expected.to_not contain_nova_config('database/max_retries') } @@ -23,10 +25,12 @@ describe 'nova::db' do context 'with overriden parameters' do before :each do params.merge!( - :database_connection => 'mysql+pymysql://user:pass@db/db1', - :slave_connection => 'mysql+pymysql://user:pass@slave/db1', - :api_database_connection => 'mysql+pymysql://user:pass@db/db2', - :api_slave_connection => 'mysql+pymysql://user:pass@slave/db2', + :database_connection => 'mysql+pymysql://user:pass@db/db1', + :slave_connection => 'mysql+pymysql://user:pass@slave/db1', + :api_database_connection => 'mysql+pymysql://user:pass@db/db2', + :api_slave_connection => 'mysql+pymysql://user:pass@slave/db2', + :placement_database_connection => 'mysql+pymysql://user:pass@db/db2', + :placement_slave_connection => 'mysql+pymysql://user:pass@slave/db2', ) end @@ -35,6 +39,8 @@ describe 'nova::db' do it { is_expected.to contain_nova_config('database/slave_connection').with_value('mysql+pymysql://user:pass@slave/db1').with_secret(true) } it { is_expected.to contain_nova_config('api_database/connection').with_value('mysql+pymysql://user:pass@db/db2').with_secret(true) } it { is_expected.to contain_nova_config('api_database/slave_connection').with_value('mysql+pymysql://user:pass@slave/db2').with_secret(true) } + it { is_expected.to contain_nova_config('placement_database/connection').with_value('mysql+pymysql://user:pass@db/db2').with_secret(true) } + it { is_expected.to contain_nova_config('placement_database/slave_connection').with_value('mysql+pymysql://user:pass@slave/db2').with_secret(true) } it { is_expected.to contain_nova_config('database/idle_timeout').with_value('') } it { is_expected.to contain_nova_config('database/min_pool_size').with_value('') } it { is_expected.to contain_nova_config('database/max_retries').with_value('') }