diff --git a/metadata.rb b/metadata.rb old mode 100644 new mode 100755 index 3e3efda..d7149db --- a/metadata.rb +++ b/metadata.rb @@ -9,6 +9,8 @@ recipe 'client', 'Installs client packages for the database used by the deployme recipe 'server', 'Installs and configures server packages for the database used by the deployment.' recipe 'mysql-client', 'Installs MySQL client packages.' recipe 'mysql-server', 'Installs and configures MySQL server packages.' +recipe 'mariadb-client', 'Installs MariaDB client packages.' +recipe 'mariadb-server', 'Installs and configures MariaDB server packages.' recipe 'postgresql-client', 'Installs PostgreSQL client packages.' recipe 'postgresql-server', 'Installs and configures PostgreSQL server packages.' recipe 'openstack-db', 'Creates necessary tables, users, and grants for OpenStack.' @@ -17,6 +19,7 @@ recipe 'openstack-db', 'Creates necessary tables, users, and grants for OpenStac supports os end +depends 'mariadb', '~> 0.3.0' depends 'mysql', '~> 6.0.13' depends 'mysql2_chef_gem', '~> 1.0.1' depends 'postgresql', '~> 3.4.18' diff --git a/recipes/mariadb-client.rb b/recipes/mariadb-client.rb new file mode 100644 index 0000000..bc3fda1 --- /dev/null +++ b/recipes/mariadb-client.rb @@ -0,0 +1,29 @@ +# encoding: UTF-8 +# +# Cookbook Name:: openstack-ops-database +# Recipe:: mariadb-client +# +# 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. +# + +node.override['mariadb']['install']['prefer_os_package'] = true +include_recipe 'mariadb::client' + +mysql2_chef_gem 'default' do + provider Chef::Provider::Mysql2ChefGem::Mariadb + action :install +end + +node['openstack']['db']['python_packages']['mariadb'].each do |pkg| + package pkg +end diff --git a/recipes/mariadb-server.rb b/recipes/mariadb-server.rb new file mode 100644 index 0000000..7835ff0 --- /dev/null +++ b/recipes/mariadb-server.rb @@ -0,0 +1,75 @@ +# encoding: UTF-8 +# +# Cookbook Name:: openstack-ops-database +# Recipe:: mariadb-server +# +# 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 # rubocop:disable Documentation + include ::Openstack +end + +db_endpoint = endpoint 'db' +super_password = get_password 'user', node['openstack']['db']['root_user_key'] + +node.override['mariadb']['allow_root_pass_change'] = true +node.override['mariadb']['server_root_password'] = super_password +node.override['mariadb']['mysqld']['bind_address'] = db_endpoint.host +node.override['mariadb']['install']['prefer_os_package'] = true + +unless db_endpoint.host == '127.0.0.1' || db_endpoint.host == 'localhost' + node.override['mariadb']['forbid_remote_root'] = false +end + +include_recipe 'openstack-ops-database::mariadb-client' + +# reuse mysql configuration for mariadb +node.override['mariadb']['mysqld']['default_storage_engine'] = node['openstack']['mysql']['default-storage-engine'] +node.override['mariadb']['mysqld']['max_connections'] = node['openstack']['mysql']['max_connections'] +include_recipe 'mariadb::server' + +# reuse mysql configuration file for mariadb +template "#{node['mariadb']['configuration']['includedir']}/openstack.cnf" do + owner 'mysql' + group 'mysql' + source 'openstack.cnf.erb' + notifies :restart, 'service[mysql]' +end + +# Current mariadb cookbook does not handle deleting anonymous users and default +# users. We need to delete them here. +mysql_connection_info = { + host: 'localhost', + username: 'root', + password: super_password +} + +mysql_database 'drop empty and default users' do + database_name 'mysql' + sql "DELETE FROM mysql.user WHERE User = '' OR Password = ''" + connection mysql_connection_info + action :query +end + +mysql_database 'test' do + connection mysql_connection_info + action :drop +end + +mysql_database 'flush priviledges after cleanup' do + database_name 'mysql' + sql 'FLUSH PRIVILEGES' + connection mysql_connection_info + action :query +end diff --git a/spec/mariadb-client-redhat_spec.rb b/spec/mariadb-client-redhat_spec.rb new file mode 100644 index 0000000..367a51d --- /dev/null +++ b/spec/mariadb-client-redhat_spec.rb @@ -0,0 +1,18 @@ +# encoding: UTF-8 + +require_relative 'spec_helper' + +describe 'openstack-ops-database::mariadb-client' do + describe 'suse' do + let(:runner) { ChefSpec::Runner.new(REDHAT_OPTS) } + let(:node) do + runner.node.set['openstack']['db']['service_type'] = 'mariadb' + runner.node + end + let(:chef_run) { runner.converge(described_recipe) } + + it 'installs mariadb python client packages' do + expect(chef_run).to install_package('MySQL-python') + end + end +end diff --git a/spec/mariadb-client-suse_spec.rb b/spec/mariadb-client-suse_spec.rb new file mode 100644 index 0000000..0a0ea4f --- /dev/null +++ b/spec/mariadb-client-suse_spec.rb @@ -0,0 +1,18 @@ +# encoding: UTF-8 + +require_relative 'spec_helper' + +describe 'openstack-ops-database::mariadb-client' do + describe 'suse' do + let(:runner) { ChefSpec::Runner.new(SUSE_OPTS) } + let(:node) do + runner.node.set['openstack']['db']['service_type'] = 'mariadb' + runner.node + end + let(:chef_run) { runner.converge(described_recipe) } + + it 'installs mariadb python client packages' do + expect(chef_run).to install_package('python-mysql') + end + end +end diff --git a/spec/mariadb-client_spec.rb b/spec/mariadb-client_spec.rb new file mode 100644 index 0000000..7976c94 --- /dev/null +++ b/spec/mariadb-client_spec.rb @@ -0,0 +1,32 @@ +# encoding: UTF-8 + +require_relative 'spec_helper' + +describe 'openstack-ops-database::mariadb-client' do + include_context 'database-stubs' + describe 'ubuntu' do + let(:runner) { ChefSpec::Runner.new(UBUNTU_OPTS) } + let(:node) do + runner.node.set['openstack']['db']['service_type'] = 'mariadb' + runner.node + end + let(:chef_run) { runner.converge(described_recipe) } + + it 'includes mariadb client recipes' do + expect(chef_run).to include_recipe('mariadb::client') + end + + it 'install mysql2 gem package' do + expect(chef_run).to install_mysql2_chef_gem('default') + .with(provider: Chef::Provider::Mysql2ChefGem::Mariadb) + end + + it 'installs mariadb python client packages' do + expect(chef_run).to install_package('python-mysqldb') + end + + it 'override prefer os package' do + expect(chef_run.node['mariadb']['install']['prefer_os_package']).to be true + end + end +end diff --git a/spec/mariadb-server-redhat_spec.rb b/spec/mariadb-server-redhat_spec.rb new file mode 100644 index 0000000..6c3afd8 --- /dev/null +++ b/spec/mariadb-server-redhat_spec.rb @@ -0,0 +1,32 @@ +# encoding: UTF-8 + +require_relative 'spec_helper' + +describe 'openstack-ops-database::mariadb-server' do + describe 'redhat' do + include_context 'database-stubs' + let(:runner) { ChefSpec::Runner.new(REDHAT_OPTS) } + let(:node) { runner.node } + let(:chef_run) { runner.converge(described_recipe) } + let(:file) { chef_run.template('/etc/my.cnf.d/openstack.cnf') } + + it 'creates template /etc/my.cnf.d/openstack.cnf' do + node.set['mariadb']['install']['version'] = '5.5' + expect(chef_run).to create_template(file.name).with( + user: 'mysql', + group: 'mysql', + source: 'openstack.cnf.erb' + ) + expect(file).to notify('service[mysql]') + [/^default-storage-engine = InnoDB$/, + /^innodb_thread_concurrency = 0$/, + /^innodb_commit_concurrency = 0$/, + /^innodb_flush_log_at_trx_commit = 2$/, + /^skip-name-resolve$/, + /^character-set-server = utf8$/].each do |line| + expect(chef_run).to render_config_file(file.name)\ + .with_section_content('mysqld', line) + end + end + end +end diff --git a/spec/mariadb-server_spec.rb b/spec/mariadb-server_spec.rb new file mode 100644 index 0000000..8cfc530 --- /dev/null +++ b/spec/mariadb-server_spec.rb @@ -0,0 +1,71 @@ +# encoding: UTF-8 + +require_relative 'spec_helper' + +describe 'openstack-ops-database::mariadb-server' do + describe 'ubuntu' do + include_context 'database-stubs' + let(:runner) { ChefSpec::Runner.new(UBUNTU_OPTS) } + let(:node) { runner.node } + let(:chef_run) { runner.converge(described_recipe) } + let(:file) { chef_run.template('/etc/mysql/conf.d/openstack.cnf') } + + it 'overrides mariadb default attributes' do + expect(chef_run.node['mariadb']['mysqld']['bind_address']).to eq '127.0.0.1' + expect(chef_run.node['mariadb']['mysqld']['default_storage_engine']).to eq 'InnoDB' + expect(chef_run.node['mariadb']['mysqld']['max_connections']).to eq '1024' + expect(chef_run.node['mariadb']['forbid_remote_root']).to be true + end + + it 'includes mariadb recipes' do + expect(chef_run).to include_recipe('openstack-ops-database::mariadb-client') + expect(chef_run).to include_recipe('mariadb::server') + end + + it 'creates template /etc/mysql/conf.d/openstack.cnf' do + node.set['mariadb']['install']['version'] = '5.5' + expect(chef_run).to create_template(file.name).with( + user: 'mysql', + group: 'mysql', + source: 'openstack.cnf.erb' + ) + expect(file).to notify('service[mysql]') + [/^default-storage-engine = InnoDB$/, + /^innodb_thread_concurrency = 0$/, + /^innodb_commit_concurrency = 0$/, + /^innodb_read_io_threads = 4$/, + /^innodb_flush_log_at_trx_commit = 2$/, + /^skip-name-resolve$/, + /^character-set-server = utf8$/, + /^max_connections = 1024$/].each do |line| + expect(chef_run).to render_config_file(file.name)\ + .with_section_content('mysqld', line) + end + end + + it 'creates mariadb with root password' do + # Password is fixed as 'abc123' by spec_helper + expect(chef_run.node['mariadb']['allow_root_pass_change']).to be true + expect(chef_run.node['mariadb']['server_root_password']).to eq 'abc123' + end + + it 'override prefer os package' do + expect(chef_run.node['mariadb']['install']['prefer_os_package']).to be true + end + + it 'allow root remote access' do + node.set['openstack']['endpoints']['db']['host'] = '192.168.1.1' + expect(chef_run.node['mariadb']['forbid_remote_root']).to be false + end + + it 'drop anonymous and empty users' do + expect(chef_run).to query_mysql_database('drop empty and default users')\ + .with(database_name: 'mysql', + sql: "DELETE FROM mysql.user WHERE User = '' OR Password = ''") + expect(chef_run).to drop_mysql_database('test') + expect(chef_run).to query_mysql_database('flush priviledges after cleanup')\ + .with(database_name: 'mysql', + sql: 'FLUSH PRIVILEGES') + end + end +end diff --git a/templates/default/openstack.cnf.erb b/templates/default/openstack.cnf.erb index 3251d68..c43fbed 100644 --- a/templates/default/openstack.cnf.erb +++ b/templates/default/openstack.cnf.erb @@ -1,7 +1,7 @@ <%= node['openstack']['db']['custom_template_banner'] %> [mysqld] default-storage-engine = <%= node['openstack']['mysql']['default-storage-engine'] %> -innodb_thread_concurrency= <%= node['openstack']['mysql']['innodb_thread_concurrency'] %> +innodb_thread_concurrency = <%= node['openstack']['mysql']['innodb_thread_concurrency'] %> innodb_commit_concurrency = <%= node['openstack']['mysql']['innodb_commit_concurrency'] %> innodb_read_io_threads = <%= node['openstack']['mysql']['innodb_read_io_threads'] %> innodb_flush_log_at_trx_commit = <%= node['openstack']['mysql']['innodb_flush_log_at_trx_commit'] %>