From c49ebf016d48f87431fe15559a4d3b94fd4b624e Mon Sep 17 00:00:00 2001 From: Alan Bishop Date: Mon, 20 Jan 2020 06:09:59 -0800 Subject: [PATCH] Add support for glance multistore Add new tripleo::profile::base::glance::api::multistore_config parameter to support configuring multiple glance-api backends. The parameter is optional, and represents a hash of settings for each additional backend. The existing 'glance_backend' parameter specifies the default backend. In order to support DCN/Edge deployments, the syntax supports multiple instances of the 'rbd' backend type. Restrictions are imposed to allow only a single instance of the 'cinder', 'file' and 'swift' backend types. Change-Id: I41ab9b3593bf3d078c5bbd1826df8308e3f5e7af Depends-On: I5a1c61430879a910e7b6c79effba538431959d56 (cherry picked from commit c7b9b90dbdeef35cc16b1c0b2007152c1a21b613) --- manifests/profile/base/glance/api.pp | 77 +++++---- .../profile/base/glance/backend/cinder.pp | 113 +++++++++++++ manifests/profile/base/glance/backend/file.pp | 65 ++++++++ manifests/profile/base/glance/backend/rbd.pp | 110 +++++++++++++ .../profile/base/glance/backend/swift.pp | 148 ++++++++++++++++++ .../glance-multistore-766022d470827d1d.yaml | 8 + .../tripleo_profile_base_glance_api_spec.rb | 95 +++++++++-- ...profile_base_glance_backend_cinder_spec.rb | 105 +++++++++++++ ...o_profile_base_glance_backend_file_spec.rb | 89 +++++++++++ ...eo_profile_base_glance_backend_rbd_spec.rb | 124 +++++++++++++++ ..._profile_base_glance_backend_swift_spec.rb | 99 ++++++++++++ 11 files changed, 995 insertions(+), 38 deletions(-) create mode 100644 manifests/profile/base/glance/backend/cinder.pp create mode 100644 manifests/profile/base/glance/backend/file.pp create mode 100644 manifests/profile/base/glance/backend/rbd.pp create mode 100644 manifests/profile/base/glance/backend/swift.pp create mode 100644 releasenotes/notes/glance-multistore-766022d470827d1d.yaml create mode 100644 spec/classes/tripleo_profile_base_glance_backend_cinder_spec.rb create mode 100644 spec/classes/tripleo_profile_base_glance_backend_file_spec.rb create mode 100644 spec/classes/tripleo_profile_base_glance_backend_rbd_spec.rb create mode 100644 spec/classes/tripleo_profile_base_glance_backend_swift_spec.rb diff --git a/manifests/profile/base/glance/api.pp b/manifests/profile/base/glance/api.pp index c1e05bd37..764395924 100644 --- a/manifests/profile/base/glance/api.pp +++ b/manifests/profile/base/glance/api.pp @@ -39,14 +39,22 @@ # Defaults to hiera('enable_internal_tls', false) # # [*glance_backend*] -# (Optional) Glance backend(s) to use. +# (Optional) Default glance backend type. # Defaults to downcase(hiera('glance_backend', 'swift')) # +# [*glance_backend_id*] +# (Optional) Default glance backend identifier. +# Defaults to 'default_backend' +# # [*glance_network*] # (Optional) The network name where the glance endpoint is listening on. # This is set by t-h-t. # Defaults to hiera('glance_api_network', undef) # +# [*multistore_config*] +# (Optional) Hash of settings for configuring additional glance-api backends. +# Defaults to {} +# # [*step*] # (Optional) The current step in deployment. See tripleo-heat-templates # for more details. @@ -115,15 +123,20 @@ # enable_internal_tls is set. # defaults to 9292 # +# DEPRECATED PARAMETERS +# # [*glance_rbd_client_name*] -# RBD client naem -# (optional) Defaults to hiera('glance::backend::rbd::rbd_store_user') +# (optional) Deprecated. RBD client name +# Defaults to undef +# class tripleo::profile::base::glance::api ( $bootstrap_node = hiera('glance_api_short_bootstrap_node_name', undef), $certificates_specs = hiera('apache_certificates_specs', {}), $enable_internal_tls = hiera('enable_internal_tls', false), $glance_backend = downcase(hiera('glance_backend', 'swift')), + $glance_backend_id = 'default_backend', $glance_network = hiera('glance_api_network', undef), + $multistore_config = {}, $step = Integer(hiera('step')), $oslomsg_rpc_proto = hiera('oslo_messaging_rpc_scheme', 'rabbit'), $oslomsg_rpc_hosts = any2array(hiera('oslo_messaging_rpc_node_names', undef)), @@ -140,7 +153,8 @@ class tripleo::profile::base::glance::api ( $tls_proxy_bind_ip = undef, $tls_proxy_fqdn = undef, $tls_proxy_port = 9292, - $glance_rbd_client_name = hiera('glance::backend::rbd::rbd_store_user','openstack'), + # DEPRECATED PARAMETERS + $glance_rbd_client_name = undef, ) { if $::hostname == downcase($bootstrap_node) { $sync_db = true @@ -174,35 +188,45 @@ class tripleo::profile::base::glance::api ( } include ::tripleo::profile::base::apache } - case $glance_backend { - 'swift': { $backend_store = 'swift' } - 'file': { $backend_store = 'file' } - 'rbd': { - $backend_store = 'rbd' - exec{ "exec-setfacl-${glance_rbd_client_name}-glance": - path => ['/bin', '/usr/bin'], - command => "setfacl -m u:glance:r-- /etc/ceph/ceph.client.${glance_rbd_client_name}.keyring", - unless => "getfacl /etc/ceph/ceph.client.${glance_rbd_client_name}.keyring | grep -q user:glance:r--", - } - -> exec{ "exec-setfacl-${glance_rbd_client_name}-glance-mask": - path => ['/bin', '/usr/bin'], - command => "setfacl -m m::r /etc/ceph/ceph.client.${glance_rbd_client_name}.keyring", - unless => "getfacl /etc/ceph/ceph.client.${glance_rbd_client_name}.keyring | grep -q mask::r", - } - } - 'cinder': { $backend_store = 'cinder' } - default: { fail('Unrecognized glance_backend parameter.') } + + $multistore_backends = $multistore_config.map |$backend_config| { + unless has_key($backend_config[1], 'GlanceBackend') { + fail("multistore_config '${backend_config[0]}' does not specify a glance_backend.") + } + "${backend_config[0]}:${backend_config[1]['GlanceBackend']}" } - $http_store = ['http'] - $glance_store = concat($http_store, $backend_store) + + $enabled_backends = ["${glance_backend_id}:${glance_backend}", 'http:http'] + $multistore_backends include ::glance include ::glance::config include ::glance::api::logging class { '::glance::api': - stores => $glance_store, - sync_db => $sync_db, + enabled_backends => $enabled_backends, + default_backend => $glance_backend_id, + sync_db => $sync_db, } + + ['cinder', 'file', 'rbd', 'swift'].each |String $backend_type| { + + # Generate a list of backend names for a given backend type + $backend_names = $enabled_backends.reduce([]) |$accum, String $backend| { + $backend_info = $backend.split(':') + if $backend_info[1] == $backend_type { + $accum << $backend_info[0] + } else { + $accum + } + } + + unless empty($backend_names) { + class { "tripleo::profile::base::glance::backend::${backend_type}": + backend_names => $backend_names, + multistore_config => $multistore_config, + } + } + } + $oslomsg_rpc_use_ssl_real = sprintf('%s', bool2num(str2bool($oslomsg_rpc_use_ssl))) $oslomsg_notify_use_ssl_real = sprintf('%s', bool2num(str2bool($oslomsg_notify_use_ssl))) class { '::glance::notify::rabbitmq' : @@ -223,7 +247,6 @@ class tripleo::profile::base::glance::api ( 'ssl' => $oslomsg_notify_use_ssl_real, }), } - include join(['::glance::backend::', $glance_backend]) } } diff --git a/manifests/profile/base/glance/backend/cinder.pp b/manifests/profile/base/glance/backend/cinder.pp new file mode 100644 index 000000000..b55592918 --- /dev/null +++ b/manifests/profile/base/glance/backend/cinder.pp @@ -0,0 +1,113 @@ +# Copyright 2020 Red Hat, Inc. +# +# 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: tripleo::profile::base::glance::backend::cinder +# +# Glance API cinder backend configuration for tripleo +# +# === Parameters +# +# [*backend_names*] +# Array of cinder store backend names. +# +# [*multistore_config*] +# (Optional) Hash containing multistore data for configuring multiple backends. +# Defaults to {} +# +# [*cinder_ca_certificates_file*] +# (Optional) Location of ca certicate file to use for cinder client requests. +# Defaults to hiera('glance::backend::cinder::cinder_ca_certificates_file', undef). +# +# [*cinder_api_insecure*] +# (Optional) Allow to perform insecure SSL requests to cinder. +# Defaults to hiera('glance::backend::cinder::cinder_api_insecure', undef). +# +# [*cinder_catalog_info*] +# (Optional) Info to match when looking for cinder in the service catalog. +# Defaults to hiera('glance::backend::cinder::cinder_catalog_info', undef). +# +# [*cinder_endpoint_template*] +# (Optional) Override service catalog lookup with template for cinder endpoint. +# Defaults to hiera('glance::backend::cinder::cinder_endpoint_template', undef). +# +# [*cinder_http_retries*] +# (Optional) Number of cinderclient retries on failed http calls. +# Defaults to hiera('glance::backend::cinder::cinder_http_retries', undef). +# +# [*cinder_store_auth_address*] +# (Optional) A valid authentication service address. +# Defaults to hiera('glance::backend::cinder::cinder_store_auth_address', undef). +# +# [*cinder_store_project_name*] +# (Optional) Project name where the image volume is stored in cinder. +# Defaults to hiera('glance::backend::cinder::cinder_store_project_name', undef). +# +# [*cinder_store_user_name*] +# (Optional) User name to authenticate against cinder. +# Defaults to hiera('glance::backend::cinder::cinder_store_user_name', undef) +# +# [*cinder_store_password*] +# (Optional) A valid password for the user specified by `cinder_store_user_name' +# Defaults to hiera('glance::backend::cinder::cinder_store_password', undef) +# +# [*store_description*] +# (Optional) Provides constructive information about the store backend to +# end users. +# Defaults to hiera('tripleo::profile::base::glance::api::glance_store_description', 'Cinder store'). +# +# [*step*] +# (Optional) The current step in deployment. See tripleo-heat-templates +# for more details. +# Defaults to hiera('step') +# +class tripleo::profile::base::glance::backend::cinder ( + $backend_names, + $multistore_config = {}, + $cinder_ca_certificates_file = hiera('glance::backend::cinder::cinder_ca_certificates_file', undef), + $cinder_api_insecure = hiera('glance::backend::cinder::cinder_api_insecure', undef), + $cinder_catalog_info = hiera('glance::backend::cinder::cinder_catalog_info', undef), + $cinder_endpoint_template = hiera('glance::backend::cinder::cinder_endpoint_template', undef), + $cinder_http_retries = hiera('glance::backend::cinder::cinder_http_retries', undef), + $cinder_store_auth_address = hiera('glance::backend::cinder::cinder_store_auth_address', undef), + $cinder_store_project_name = hiera('glance::backend::cinder::cinder_store_project_name', undef), + $cinder_store_user_name = hiera('glance::backend::cinder::cinder_store_user_name', undef), + $cinder_store_password = hiera('glance::backend::cinder::cinder_store_password', undef), + $store_description = hiera('tripleo::profile::base::glance::api::glance_store_description', 'Cinder store'), + $step = Integer(hiera('step')), +) { + + if $backend_names.length() > 1 { + fail('Multiple cinder backends are not supported.') + } + + if $step >= 4 { + $backend_name = $backend_names[0] + + $multistore_description = pick($multistore_config[$backend_name], {})['GlanceStoreDescription'] + $store_description_real = pick($multistore_description, $store_description) + + glance::backend::multistore::cinder { $backend_name: + cinder_api_insecure => $cinder_api_insecure, + cinder_catalog_info => $cinder_catalog_info, + cinder_http_retries => $cinder_http_retries, + cinder_endpoint_template => $cinder_endpoint_template, + cinder_ca_certificates_file => $cinder_ca_certificates_file, + cinder_store_auth_address => $cinder_store_auth_address, + cinder_store_project_name => $cinder_store_project_name, + cinder_store_user_name => $cinder_store_user_name, + cinder_store_password => $cinder_store_password, + store_description => $store_description_real, + } + } +} diff --git a/manifests/profile/base/glance/backend/file.pp b/manifests/profile/base/glance/backend/file.pp new file mode 100644 index 000000000..ae848af79 --- /dev/null +++ b/manifests/profile/base/glance/backend/file.pp @@ -0,0 +1,65 @@ +# Copyright 2020 Red Hat, Inc. +# +# 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: tripleo::profile::base::glance::backend::file +# +# Glance API file backend configuration for tripleo +# +# === Parameters +# +# [*backend_names*] +# Array of file store backend names. +# +# [*multistore_config*] +# (Optional) Hash containing multistore data for configuring multiple backends. +# Defaults to {} +# +# [*filesystem_store_datadir*] +# (Optional) Location where dist images are stored when the backend type is file. +# Defaults to hiera('glance::backend::file::filesystem_store_datadir', undef). +# +# [*store_description*] +# (Optional) Provides constructive information about the store backend to +# end users. +# Defaults to hiera('tripleo::profile::base::glance::api::glance_store_description', 'File store'). +# +# [*step*] +# (Optional) The current step in deployment. See tripleo-heat-templates +# for more details. +# Defaults to hiera('step') +# +class tripleo::profile::base::glance::backend::file ( + $backend_names, + $multistore_config = {}, + $filesystem_store_datadir = hiera('glance::backend::file::filesystem_store_datadir', undef), + $store_description = hiera('tripleo::profile::base::glance::api::glance_store_description', 'File store'), + $step = Integer(hiera('step')), +) { + + if $backend_names.length() > 1 { + fail('Multiple file backends are not supported.') + } + + if $step >= 4 { + $backend_name = $backend_names[0] + + $multistore_description = pick($multistore_config[$backend_name], {})['GlanceStoreDescription'] + $store_description_real = pick($multistore_description, $store_description) + + glance::backend::multistore::file { $backend_name: + filesystem_store_datadir => $filesystem_store_datadir, + store_description => $store_description_real, + } + } +} diff --git a/manifests/profile/base/glance/backend/rbd.pp b/manifests/profile/base/glance/backend/rbd.pp new file mode 100644 index 000000000..60f20e1ff --- /dev/null +++ b/manifests/profile/base/glance/backend/rbd.pp @@ -0,0 +1,110 @@ +# Copyright 2020 Red Hat, Inc. +# +# 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: tripleo::profile::base::glance::backend::rbd +# +# Glance API rbd backend configuration for tripleo +# +# === Parameters +# +# [*backend_names*] +# Array of rbd store backend names. +# +# [*multistore_config*] +# (Optional) Hash containing multistore data for configuring multiple backends. +# Defaults to {} +# +# [*rbd_store_ceph_conf*] +# (Optional) Ceph cluster config file. +# Defaults to hiera('glance::backend::rbd::rbd_store_ceph_conf', '/etc/ceph/ceph.conf'). +# +# [*rbd_store_user*] +# (Optional) Ceph client username. +# Defaults to hiera('glance::backend::rbd::rbd_store_user', 'openstack'). +# +# [*rbd_store_pool*] +# (Optional) Ceph pool for storing images. +# Defaults to hiera('glance::backend::rbd::rbd_store_pool', 'images'). +# +# [*rbd_store_chunk_size*] +# (Optional) RBD chunk size. +# Defaults to hiera('glance::backend::rbd::rbd_store_chunk_size', undef). +# +# [*rados_connect_timeout*] +# (Optional) RADOS connection timeout. +# Defaults to hiera('glance::backend::rbd::rados_connect_timeout', undef). +# +# [*store_description*] +# (Optional) Provides constructive information about the store backend to +# end users. +# Defaults to hiera('tripleo::profile::base::glance::api::glance_store_description', 'RBD store'). +# +# [*step*] +# (Optional) The current step in deployment. See tripleo-heat-templates +# for more details. +# Defaults to hiera('step') +# +class tripleo::profile::base::glance::backend::rbd ( + $backend_names, + $multistore_config = {}, + $rbd_store_ceph_conf = hiera('glance::backend::rbd::rbd_store_ceph_conf', '/etc/ceph/ceph.conf'), + $rbd_store_user = hiera('glance::backend::rbd::rbd_store_user', 'openstack'), + $rbd_store_pool = hiera('glance::backend::rbd::rbd_store_pool', 'images'), + $rbd_store_chunk_size = hiera('glance::backend::rbd::rbd_store_chunk_size', undef), + $rados_connect_timeout = hiera('glance::backend::rbd::rados_connect_timeout', undef), + $store_description = hiera('tripleo::profile::base::glance::api::glance_store_description', 'RBD store'), + $step = Integer(hiera('step')), +) { + + if $step >= 4 { + $backend_names.each |String $backend_name| { + $backend_config = pick($multistore_config[$backend_name], {}) + + $rbd_store_user_real = pick($backend_config['CephClientUserName'], $rbd_store_user) + $rbd_store_pool_real = pick($backend_config['GlanceRbdPoolName'], $rbd_store_pool) + $store_description_real = pick($backend_config['GlanceStoreDescription'], $store_description) + + $ceph_cluster_name = $backend_config['CephClusterName'] + if $ceph_cluster_name { + $ceph_cluster_name_real = $ceph_cluster_name + $rbd_store_ceph_conf_real = "/etc/ceph/${ceph_cluster_name}.conf" + } else { + $ceph_cluster_name_real = $rbd_store_ceph_conf.match(/(\/etc\/ceph\/)(\w+)(\.conf$)/)[2] + $rbd_store_ceph_conf_real = $rbd_store_ceph_conf + } + + $ceph_client_keyring = "/etc/ceph/${ceph_cluster_name_real}.client.${rbd_store_user_real}.keyring" + + exec { "exec-setfacl-${ceph_cluster_name_real}-${rbd_store_user_real}-glance": + path => ['/bin', '/usr/bin'], + command => "setfacl -m u:glance:r-- ${ceph_client_keyring}", + unless => "getfacl ${ceph_client_keyring} | grep -q user:glance:r--", + } + -> exec { "exec-setfacl-${ceph_cluster_name_real}-${rbd_store_user_real}-glance-mask": + path => ['/bin', '/usr/bin'], + command => "setfacl -m m::r ${ceph_client_keyring}", + unless => "getfacl ${ceph_client_keyring} | grep -q mask::r", + } + + glance::backend::multistore::rbd { $backend_name: + rbd_store_ceph_conf => $rbd_store_ceph_conf_real, + rbd_store_user => $rbd_store_user_real, + rbd_store_pool => $rbd_store_pool_real, + rbd_store_chunk_size => $rbd_store_chunk_size, + rados_connect_timeout => $rados_connect_timeout, + store_description => $store_description_real, + } + } + } +} diff --git a/manifests/profile/base/glance/backend/swift.pp b/manifests/profile/base/glance/backend/swift.pp new file mode 100644 index 000000000..fca4bba90 --- /dev/null +++ b/manifests/profile/base/glance/backend/swift.pp @@ -0,0 +1,148 @@ +# Copyright 2020 Red Hat, Inc. +# +# 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: tripleo::profile::base::glance::backend::swift +# +# Glance API swift backend configuration for tripleo +# +# === Parameters +# +# [*backend_names*] +# Array of swift store backend names. +# +# [*multistore_config*] +# (Optional) Hash containing multistore data for configuring multiple backends. +# Defaults to {} +# +# [*swift_store_user*] +# (Optional) Swift store user. +# Defaults to hiera('glance::backend::swift::swift_store_user'). +# +# [*swift_store_key*] +# (Optional) Swift store key. +# Defaults to hiera('glance::backend::swift::swift_store_key'). +# +# [*swift_store_container*] +# (Optional) Swift store container. +# Defaults to hiera('glance::backend::swift::swift_store_container', undef). +# +# [*swift_store_auth_address*] +# (Optional) Swift store auth address. +# Defaults to hiera('glance::backend::swift::swift_store_auth_address', undef). +# +# [*swift_store_auth_version*] +# (Optional) Swift store auth version. +# Defaults to hiera('glance::backend::swift::swift_store_auth_version', undef). +# +# [*swift_store_auth_project_domain_id*] +# (Optional) Useful when keystone auth is version 3. +# Defaults to hiera('glance::backend::swift::swift_store_auth_project_domain_id', undef). +# +# [*swift_store_auth_user_domain_id*] +# (Optional) Useful when keystone auth is version 3. +# Defaults to hiera('glance::backend::swift::swift_store_auth_user_domain_id', undef). +# +# [*swift_store_large_object_size*] +# (Optional) What size, in MB, should Glance start chunking image files +# and do a large object manifest in Swift? +# Defaults to hiera('glance::backend::swift::swift_store_large_object_size', undef). +# +# [*swift_store_large_object_chunk_size*] +# (Optional) When doing a large object manifest, what size, in MB, should +# Glance write chunks to Swift? This amount of data is written +# to a temporary disk buffer during the process of chunking. +# Defaults to hiera('glance::backend::swift::swift_store_large_object_chunk_size', undef). +# +# [*swift_store_create_container_on_put*] +# (Optional) Whether to create the swift container if it's missing. +# Defaults to hiera('glance::backend::swift::swift_store_create_container_on_put', undef). +# +# [*swift_store_endpoint_type*] +# (Optional) Swift store endpoint type. +# Defaults to hiera('glance::backend::swift::swift_store_endpoint_type', undef). +# +# [*swift_store_region*] +# (Optional) Swift store region. +# Defaults to hiera('glance::backend::swift::swift_store_region', undef). +# +# [*swift_store_config_file*] +# (Optional) +# Defaults to /etc/glance/glance-swift.conf. +# +# [*default_swift_reference*] +# (Optional) The reference to the default swift +# account/backing store parameters to use for adding +# new images. +# Defaults to ref1. +# +# [*store_description*] +# (Optional) Provides constructive information about the store backend to +# end users. +# Defaults to hiera('tripleo::profile::base::glance::api::glance_store_description', 'Swift store'). +# +# [*step*] +# (Optional) The current step in deployment. See tripleo-heat-templates +# for more details. +# Defaults to hiera('step') +# +class tripleo::profile::base::glance::backend::swift ( + $backend_names, + $multistore_config = {}, + $swift_store_user = hiera('glance::backend::swift::swift_store_user'), + $swift_store_key = hiera('glance::backend::swift::swift_store_key'), + $swift_store_container = hiera('glance::backend::swift::swift_store_container', undef), + $swift_store_auth_address = hiera('glance::backend::swift::swift_store_auth_address', undef), + $swift_store_auth_version = hiera('glance::backend::swift::swift_store_auth_version', undef), + $swift_store_auth_project_domain_id = hiera('glance::backend::swift::swift_store_auth_project_domain_id', undef), + $swift_store_auth_user_domain_id = hiera('glance::backend::swift::swift_store_auth_user_domain_id', undef), + $swift_store_large_object_size = hiera('glance::backend::swift::swift_store_large_object_size', undef), + $swift_store_large_object_chunk_size = hiera('glance::backend::swift::swift_store_large_object_chunk_size', undef), + $swift_store_create_container_on_put = hiera('glance::backend::swift::swift_store_create_container_on_put', undef), + $swift_store_endpoint_type = hiera('glance::backend::swift::swift_store_endpoint_type', undef), + $swift_store_region = hiera('glance::backend::swift::swift_store_region', undef), + $swift_store_config_file = '/etc/glance/glance-swift.conf', + $default_swift_reference = 'ref1', + $store_description = hiera('tripleo::profile::base::glance::api::glance_store_description', 'Swift store'), + $step = Integer(hiera('step')), +) { + + if $backend_names.length() > 1 { + fail('Multiple swift backends are not supported.') + } + + if $step >= 4 { + $backend_name = $backend_names[0] + + $multistore_description = pick($multistore_config[$backend_name], {})['GlanceStoreDescription'] + $store_description_real = pick($multistore_description, $store_description) + + glance::backend::multistore::swift { $backend_name: + swift_store_user => $swift_store_user, + swift_store_key => $swift_store_key, + swift_store_container => $swift_store_container, + swift_store_auth_address => $swift_store_auth_address, + swift_store_auth_version => $swift_store_auth_version, + swift_store_auth_project_domain_id => $swift_store_auth_project_domain_id, + swift_store_auth_user_domain_id => $swift_store_auth_user_domain_id, + swift_store_large_object_size => $swift_store_large_object_size, + swift_store_large_object_chunk_size => $swift_store_large_object_chunk_size, + swift_store_create_container_on_put => $swift_store_create_container_on_put, + swift_store_endpoint_type => $swift_store_endpoint_type, + swift_store_region => $swift_store_region, + swift_store_config_file => $swift_store_config_file, + default_swift_reference => $default_swift_reference, + store_description => $store_description_real, + } + } +} diff --git a/releasenotes/notes/glance-multistore-766022d470827d1d.yaml b/releasenotes/notes/glance-multistore-766022d470827d1d.yaml new file mode 100644 index 000000000..269f1c8dc --- /dev/null +++ b/releasenotes/notes/glance-multistore-766022d470827d1d.yaml @@ -0,0 +1,8 @@ +--- +features: + - | + Add support for configuring the glance-api service with multiple store + backends. The primary backend becomes the service's default backend, and + additional backends may be specified using an optional 'multistore_config' + hash. + diff --git a/spec/classes/tripleo_profile_base_glance_api_spec.rb b/spec/classes/tripleo_profile_base_glance_api_spec.rb index 7434866fd..58f85e24e 100644 --- a/spec/classes/tripleo_profile_base_glance_api_spec.rb +++ b/spec/classes/tripleo_profile_base_glance_api_spec.rb @@ -28,14 +28,14 @@ describe 'tripleo::profile::base::glance::api' do :step => 1, } } - it { + it 'should not configure glance' do is_expected.to contain_class('tripleo::profile::base::glance::api') is_expected.to_not contain_class('glance') is_expected.to_not contain_class('glance::config') is_expected.to_not contain_class('glance::api::logging') is_expected.to_not contain_class('glance::api') is_expected.to_not contain_class('glance::notify::rabbitmq') - } + end end context 'with step 3 on bootstrap node' do @@ -52,7 +52,7 @@ describe 'tripleo::profile::base::glance::api' do :oslomsg_notify_port => '5678', } } - it { + it 'should configure glance' do is_expected.to contain_class('tripleo::profile::base::glance::api') is_expected.to contain_class('glance') is_expected.to contain_class('glance::config') @@ -62,7 +62,7 @@ describe 'tripleo::profile::base::glance::api' do :default_transport_url => 'rabbit://glance1:foo@192.168.0.1:1234/?ssl=0', :notification_transport_url => 'rabbit://glance2:baa@192.168.0.2:5678/?ssl=0', ) - } + end end context 'with step 3 not on bootstrap node' do @@ -71,14 +71,14 @@ describe 'tripleo::profile::base::glance::api' do :bootstrap_node => 'other.example.com', } } - it { + it 'should not configure glance' do is_expected.to contain_class('tripleo::profile::base::glance::api') is_expected.to_not contain_class('glance') is_expected.to_not contain_class('glance::config') is_expected.to_not contain_class('glance::api::logging') is_expected.to_not contain_class('glance::api') is_expected.to_not contain_class('glance::notify::rabbitmq') - } + end end context 'with step 4' do @@ -95,22 +95,95 @@ describe 'tripleo::profile::base::glance::api' do :oslomsg_notify_port => '5678', } } - it { + it 'should configure glance' do is_expected.to contain_class('tripleo::profile::base::glance::api') is_expected.to contain_class('glance') is_expected.to contain_class('glance::config') is_expected.to contain_class('glance::api::logging') - is_expected.to contain_class('glance::api') + is_expected.to contain_class('glance::api').with( + :enabled_backends => ['default_backend:swift', 'http:http'], + :default_backend => 'default_backend', + ) + is_expected.to_not contain_class('tripleo::profile::base::glance::backend::cinder') + is_expected.to_not contain_class('tripleo::profile::base::glance::backend::file') + is_expected.to_not contain_class('tripleo::profile::base::glance::backend::rbd') + is_expected.to contain_class('tripleo::profile::base::glance::backend::swift').with( + :backend_names => ['default_backend'], + ) is_expected.to contain_class('glance::notify::rabbitmq').with( :default_transport_url => 'rabbit://glance1:foo@192.168.0.1:1234/?ssl=0', :notification_transport_url => 'rabbit://glance2:baa@192.168.0.2:5678/?ssl=0', ) - } + end + + context 'with multistore_config' do + before :each do + params.merge!({ + :glance_backend => 'cinder', + :glance_backend_id => 'my_cinder', + :multistore_config => { + 'my_file' => { + 'GlanceBackend' => 'file', + }, + 'rbd1' => { + 'GlanceBackend' => 'rbd', + 'CephClusterName' => 'ceph1', + 'CephClientUserName' => 'user1', + 'GlanceRbdPoolName' => 'pool1', + }, + 'rbd2' => { + 'GlanceBackend' => 'rbd', + 'CephClusterName' => 'ceph2', + 'CephClientUserName' => 'user2', + 'GlanceRbdPoolName' => 'pool2', + }, + 'my_swift' => { + 'GlanceBackend' => 'swift', + }, + }, + }) + end + it 'should configure multiple backends' do + is_expected.to contain_class('glance::api').with( + :enabled_backends => [ + 'my_cinder:cinder', + 'http:http', + 'my_file:file', + 'rbd1:rbd', + 'rbd2:rbd', + 'my_swift:swift' + ], + :default_backend => 'my_cinder', + ) + is_expected.to contain_class('tripleo::profile::base::glance::backend::cinder').with( + :backend_names => ['my_cinder'], + ) + is_expected.to contain_class('tripleo::profile::base::glance::backend::file').with( + :backend_names => ['my_file'], + ) + is_expected.to contain_class('tripleo::profile::base::glance::backend::rbd').with( + :backend_names => ['rbd1', 'rbd2'], + ) + is_expected.to contain_class('tripleo::profile::base::glance::backend::swift').with( + :backend_names => ['my_swift'], + ) + end + end + context 'with invalid multistore_config' do + before :each do + params.merge!({ + :multistore_config => { + 'rbd' => { + 'GlanceBackend_typo' => 'rbd', + }, + }, + }) + end + it_raises 'a Puppet::Error', / does not specify a glance_backend./ + end end - end - on_supported_os.each do |os, facts| context "on #{os}" do let(:facts) do diff --git a/spec/classes/tripleo_profile_base_glance_backend_cinder_spec.rb b/spec/classes/tripleo_profile_base_glance_backend_cinder_spec.rb new file mode 100644 index 000000000..a47ffa43c --- /dev/null +++ b/spec/classes/tripleo_profile_base_glance_backend_cinder_spec.rb @@ -0,0 +1,105 @@ +# +# Copyright (C) 2020 Red Hat, Inc. +# +# 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. +# + +require 'spec_helper' + +describe 'tripleo::profile::base::glance::backend::cinder' do + shared_examples_for 'tripleo::profile::base::glance::backend::cinder' do + + before :each do + facts.merge!({ :step => params[:step] }) + end + + context 'with step less than 4' do + let(:params) { { + :backend_names => ['my_cinder'], + :step => 3, + } } + + it 'should not configure a backend' do + is_expected.to contain_class('tripleo::profile::base::glance::backend::cinder') + is_expected.to_not contain_glance__backend__multistore__cinder('my_cinder') + end + end + + context 'with step 4' do + let(:params) { { + :backend_names => ['my_cinder'], + :cinder_ca_certificates_file => '/path/to/certificates_file', + :cinder_api_insecure => true, + :cinder_catalog_info => 'volume:cinder:internalURL', + :cinder_http_retries => '10', + :cinder_endpoint_template => 'http://srv-foo:8776/v1/%(project_id)s', + :cinder_store_auth_address => '127.0.0.2:8080/v3/', + :cinder_store_project_name => 'services', + :cinder_store_user_name => 'glance', + :cinder_store_password => 'glance_password', + :step => 4, + } } + + it 'should configure the backend' do + is_expected.to contain_glance__backend__multistore__cinder('my_cinder').with( + :cinder_ca_certificates_file => '/path/to/certificates_file', + :cinder_api_insecure => true, + :cinder_catalog_info => 'volume:cinder:internalURL', + :cinder_http_retries => '10', + :cinder_endpoint_template => 'http://srv-foo:8776/v1/%(project_id)s', + :cinder_store_auth_address => '127.0.0.2:8080/v3/', + :cinder_store_project_name => 'services', + :cinder_store_user_name => 'glance', + :cinder_store_password => 'glance_password', + :store_description => 'Cinder store', + ) + end + + context 'with store description in multistore_config' do + before :each do + params.merge!({ + :multistore_config => { + 'my_cinder' => { + 'GlanceStoreDescription' => 'My multistore cinder backend', + }, + }, + }) + end + it 'should use the multistore_config description' do + is_expected.to contain_glance__backend__multistore__cinder('my_cinder').with( + :store_description => 'My multistore cinder backend', + ) + end + end + + context 'with multiple backend_names' do + before :each do + params.merge!({ + :backend_names => ['cinder1', 'cinder2'], + }) + end + it_raises 'a Puppet::Error', /Multiple cinder backends are not supported./ + end + end + end + + on_supported_os.each do |os, facts| + context "on #{os}" do + let(:facts) do + facts.merge({}) + end + + it_behaves_like 'tripleo::profile::base::glance::backend::cinder' + end + end +end diff --git a/spec/classes/tripleo_profile_base_glance_backend_file_spec.rb b/spec/classes/tripleo_profile_base_glance_backend_file_spec.rb new file mode 100644 index 000000000..fea0a9b64 --- /dev/null +++ b/spec/classes/tripleo_profile_base_glance_backend_file_spec.rb @@ -0,0 +1,89 @@ +# +# Copyright (C) 2020 Red Hat, Inc. +# +# 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. +# + +require 'spec_helper' + +describe 'tripleo::profile::base::glance::backend::file' do + shared_examples_for 'tripleo::profile::base::glance::backend::file' do + + before :each do + facts.merge!({ :step => params[:step] }) + end + + context 'with step less than 4' do + let(:params) { { + :backend_names => ['my_file'], + :step => 3, + } } + + it 'should not configure a backend' do + is_expected.to contain_class('tripleo::profile::base::glance::backend::file') + is_expected.to_not contain_glance__backend__multistore__file('my_file') + end + end + + context 'with step 4' do + let(:params) { { + :backend_names => ['my_file'], + :filesystem_store_datadir => '/path/to/datadir', + :step => 4, + } } + + it 'should configure the backend' do + is_expected.to contain_glance__backend__multistore__file('my_file').with( + :filesystem_store_datadir => '/path/to/datadir', + :store_description => 'File store', + ) + end + + context 'with store description in multistore_config' do + before :each do + params.merge!({ + :multistore_config => { + 'my_file' => { + 'GlanceStoreDescription' => 'My multistore file backend', + }, + }, + }) + end + it 'should use the multistore_config description' do + is_expected.to contain_glance__backend__multistore__file('my_file').with( + :store_description => 'My multistore file backend', + ) + end + end + + context 'with multiple backend_names' do + before :each do + params.merge!({ + :backend_names => ['file1', 'file2'], + }) + end + it_raises 'a Puppet::Error', /Multiple file backends are not supported./ + end + end + end + + on_supported_os.each do |os, facts| + context "on #{os}" do + let(:facts) do + facts.merge({}) + end + + it_behaves_like 'tripleo::profile::base::glance::backend::file' + end + end +end diff --git a/spec/classes/tripleo_profile_base_glance_backend_rbd_spec.rb b/spec/classes/tripleo_profile_base_glance_backend_rbd_spec.rb new file mode 100644 index 000000000..8039b1b7f --- /dev/null +++ b/spec/classes/tripleo_profile_base_glance_backend_rbd_spec.rb @@ -0,0 +1,124 @@ +# +# Copyright (C) 2020 Red Hat, Inc. +# +# 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. +# + +require 'spec_helper' + +describe 'tripleo::profile::base::glance::backend::rbd' do + shared_examples_for 'tripleo::profile::base::glance::backend::rbd' do + + before :each do + facts.merge!({ :step => params[:step] }) + end + + context 'with step less than 4' do + let(:params) { { + :backend_names => ['my_rbd'], + :step => 3, + } } + + it 'should not configure a backend' do + is_expected.to contain_class('tripleo::profile::base::glance::backend::rbd') + is_expected.to_not contain_glance__backend__multistore__rbd('my_rbd') + end + end + + context 'with step 4' do + let(:params) { { + :backend_names => ['my_rbd'], + :step => 4, + } } + + it 'should configure the backend' do + is_expected.to contain_glance__backend__multistore__rbd('my_rbd').with( + :rbd_store_ceph_conf => '/etc/ceph/ceph.conf', + :rbd_store_user => 'openstack', + :rbd_store_pool => 'images', + :store_description => 'RBD store', + ) + is_expected.to contain_exec('exec-setfacl-ceph-openstack-glance').with_command( + 'setfacl -m u:glance:r-- /etc/ceph/ceph.client.openstack.keyring' + ) + is_expected.to contain_exec('exec-setfacl-ceph-openstack-glance-mask').with_command( + 'setfacl -m m::r /etc/ceph/ceph.client.openstack.keyring' + ) + end + + context 'with store description in multistore_config' do + before :each do + params.merge!({ + :multistore_config => { + 'my_rbd' => { + 'GlanceStoreDescription' => 'My multistore RBD backend', + }, + }, + }) + end + it 'should use the multistore_config description' do + is_expected.to contain_glance__backend__multistore__rbd('my_rbd').with( + :store_description => 'My multistore RBD backend', + ) + end + end + + context 'with multiple backend_names' do + before :each do + params.merge!({ + :backend_names => ['rbd1', 'rbd2'], + :multistore_config => { + 'rbd2' => { + 'CephClusterName' => 'ceph2', + 'CephClientUserName' => 'openstack2', + 'GlanceRbdPoolName' => 'images2', + 'GlanceStoreDescription' => 'rbd2 backend', + }, + }, + :store_description => 'rbd1 backend', + }) + end + it 'should configure multiple backends' do + is_expected.to contain_glance__backend__multistore__rbd('rbd1').with( + :rbd_store_ceph_conf => '/etc/ceph/ceph.conf', + :rbd_store_user => 'openstack', + :rbd_store_pool => 'images', + :store_description => 'rbd1 backend', + ) + is_expected.to contain_glance__backend__multistore__rbd('rbd2').with( + :rbd_store_ceph_conf => '/etc/ceph/ceph2.conf', + :rbd_store_user => 'openstack2', + :rbd_store_pool => 'images2', + :store_description => 'rbd2 backend', + ) + is_expected.to contain_exec('exec-setfacl-ceph2-openstack2-glance').with_command( + 'setfacl -m u:glance:r-- /etc/ceph/ceph2.client.openstack2.keyring' + ) + is_expected.to contain_exec('exec-setfacl-ceph2-openstack2-glance-mask').with_command( + 'setfacl -m m::r /etc/ceph/ceph2.client.openstack2.keyring' + ) + end + end + end + end + + on_supported_os.each do |os, facts| + context "on #{os}" do + let(:facts) do + facts.merge({}) + end + + it_behaves_like 'tripleo::profile::base::glance::backend::rbd' + end + end +end diff --git a/spec/classes/tripleo_profile_base_glance_backend_swift_spec.rb b/spec/classes/tripleo_profile_base_glance_backend_swift_spec.rb new file mode 100644 index 000000000..44f15de7a --- /dev/null +++ b/spec/classes/tripleo_profile_base_glance_backend_swift_spec.rb @@ -0,0 +1,99 @@ +# +# Copyright (C) 2020 Red Hat, Inc. +# +# 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. +# + +require 'spec_helper' + +describe 'tripleo::profile::base::glance::backend::swift' do + shared_examples_for 'tripleo::profile::base::glance::backend::swift' do + + before :each do + facts.merge!({ :step => params[:step] }) + end + + context 'with step less than 4' do + let(:params) { { + :backend_names => ['my_swift'], + :step => 3, + } } + + it 'should not configure a backend' do + is_expected.to contain_class('tripleo::profile::base::glance::backend::swift') + is_expected.to_not contain_glance__backend__multistore__swift('my_swift') + end + end + + context 'with step 4' do + let(:params) { { + :backend_names => ['my_swift'], + :swift_store_user => 'service:glance', + :swift_store_key => 'glance_password', + :swift_store_auth_address => '127.0.0.2:8080/v3/', + :swift_store_auth_version => 3, + :swift_store_create_container_on_put => true, + :step => 4, + } } + + it 'should configure the backend' do + is_expected.to contain_glance__backend__multistore__swift('my_swift').with( + :swift_store_user => 'service:glance', + :swift_store_key => 'glance_password', + :swift_store_auth_address => '127.0.0.2:8080/v3/', + :swift_store_auth_version => 3, + :swift_store_create_container_on_put => true, + :swift_store_config_file => '/etc/glance/glance-swift.conf', + :default_swift_reference => 'ref1', + :store_description => 'Swift store', + ) + end + + context 'with store description in multistore_config' do + before :each do + params.merge!({ + :multistore_config => { + 'my_swift' => { + 'GlanceStoreDescription' => 'My multistore swift backend', + }, + }, + }) + end + it 'should use the multistore_config description' do + is_expected.to contain_glance__backend__multistore__swift('my_swift').with( + :store_description => 'My multistore swift backend', + ) + end + end + + context 'with multiple backend_names' do + before :each do + params.merge!({ + :backend_names => ['swift1', 'swift2'], + }) + end + it_raises 'a Puppet::Error', /Multiple swift backends are not supported./ + end + end + end + + on_supported_os.each do |os, facts| + context "on #{os}" do + let(:facts) do + facts.merge({}) + end + + it_behaves_like 'tripleo::profile::base::glance::backend::swift' + end + end +end