From 594f56477feed634902b61d49385af8af704667f Mon Sep 17 00:00:00 2001 From: Mike Dorman Date: Mon, 21 Sep 2015 10:18:42 -0600 Subject: [PATCH] Add S3 backend configuration for glance Add a glance::backend::s3 class for configuring the S3 backend for Glance. Also includes a boolean default_store parameter to control whether or not S3 should be confiured as the default backend store. Default is true to follow the behavior of the swift backend configuration class. Change-Id: Iaba726932d11396bac3bdf1d671c374339f8973b --- manifests/backend/s3.pp | 97 ++++++++++++++++++++ spec/classes/glance_backend_s3_spec.rb | 117 +++++++++++++++++++++++++ 2 files changed, 214 insertions(+) create mode 100644 manifests/backend/s3.pp create mode 100644 spec/classes/glance_backend_s3_spec.rb diff --git a/manifests/backend/s3.pp b/manifests/backend/s3.pp new file mode 100644 index 00000000..6aa245b6 --- /dev/null +++ b/manifests/backend/s3.pp @@ -0,0 +1,97 @@ +# == class: glance::backend::s3 +# +# configures the storage backend for glance +# as a s3 instance +# +# === parameters: +# +# [*access_key*] +# (Required) The S3 query token access key. +# +# [*secret_key*] +# (Required) The S3 query token secret key. +# +# [*host*] +# (Required) The host where the S3 server is listening. +# +# [*bucket*] +# (Required) The S3 bucket to be used to store the Glance data. +# +# [*bucket_url_format*] +# (Optional) The S3 calling format used to determine the bucket. Either +# 'subdomain' or 'path' can be used. +# Default: 'subdomain' +# +# [*create_bucket_on_put*] +# (Optional) A boolean to determine if the S3 bucket should be created on +# upload if it does not exist or if an error should be returned to the user. +# Default: False +# +# [*large_object_size*] +# (Optional) What size, in MB, should S3 start chunking image files and do a +# multipart upload in S3. +# Default: 100 +# +# [*large_object_chunk_size*] +# (Optional) What multipart upload part size, in MB, should S3 use when +# uploading parts. The size must be greater than or equal to 5M. +# Default: 10 +# +# [*object_buffer_dir*] +# (Optional) The local directory where uploads will be staged before they are +# transferred into S3. +# Default: undef +# +# [*thread_pools*] +# (Optional) The number of thread pools to perform a multipart upload in S3. +# Default: 10 +# +# [*default_store*] +# (Optional) Whether to set S3 as the default backend store. +# Default: true +# +class glance::backend::s3( + $access_key, + $secret_key, + $host, + $bucket, + $bucket_url_format = 'subdomain', + $create_bucket_on_put = false, + $large_object_size = 100, + $large_object_chunk_size = 10, + $object_buffer_dir = undef, + $thread_pools = 10, + $default_store = true +) { + + if !is_integer($large_object_chunk_size) or $large_object_chunk_size < 5 { + fail('glance::backend::s3::large_object_chunk_size must be an integer >= 5') + } + + if !($bucket_url_format in ['subdomain', 'path']) { + fail('glance::backend::s3::bucket_url_format must be either "subdomain" or "path"') + } + + glance_api_config { + 'glance_store/s3_store_access_key': value => $access_key; + 'glance_store/s3_store_secret_key': value => $secret_key; + 'glance_store/s3_store_host': value => $host; + 'glance_store/s3_store_bucket': value => $bucket; + 'glance_store/s3_store_bucket_url_format': value => $bucket_url_format; + 'glance_store/s3_store_create_bucket_on_put': value => $create_bucket_on_put; + 'glance_store/s3_store_large_object_size': value => $large_object_size; + 'glance_store/s3_store_large_object_chunk_size': value => $large_object_chunk_size; + 'glance_store/s3_store_thread_pools': value => $thread_pools; + } + + if $object_buffer_dir { + glance_api_config { 'glance_store/s3_store_object_buffer_dir': value => $object_buffer_dir; } + } else { + glance_api_config { 'glance_store/s3_store_object_buffer_dir': ensure => absent; } + } + + if $default_store { + glance_api_config { 'glance_store/default_store': value => 's3'; } + } + +} diff --git a/spec/classes/glance_backend_s3_spec.rb b/spec/classes/glance_backend_s3_spec.rb new file mode 100644 index 00000000..37e4929e --- /dev/null +++ b/spec/classes/glance_backend_s3_spec.rb @@ -0,0 +1,117 @@ +require 'spec_helper' + +describe 'glance::backend::s3' do + let :facts do + { + :osfamily => 'Debian' + } + end + + let :params do + { + :access_key => 'access', + :secret_key => 'secret', + :host => 'host', + :bucket => 'bucket' + } + end + + describe 'when default parameters' do + + it 'configures glance-api.conf' do + is_expected.to contain_glance_api_config('glance_store/default_store').with_value('s3') + is_expected.to contain_glance_api_config('glance_store/s3_store_access_key').with_value('access') + is_expected.to contain_glance_api_config('glance_store/s3_store_secret_key').with_value('secret') + is_expected.to contain_glance_api_config('glance_store/s3_store_host').with_value('host') + is_expected.to contain_glance_api_config('glance_store/s3_store_bucket').with_value('bucket') + is_expected.to contain_glance_api_config('glance_store/s3_store_bucket_url_format').with_value('subdomain') + is_expected.to contain_glance_api_config('glance_store/s3_store_create_bucket_on_put').with_value('false') + is_expected.to contain_glance_api_config('glance_store/s3_store_large_object_size').with_value('100') + is_expected.to contain_glance_api_config('glance_store/s3_store_large_object_chunk_size').with_value('10') + is_expected.to contain_glance_api_config('glance_store/s3_store_object_buffer_dir').with_value(nil) + is_expected.to contain_glance_api_config('glance_store/s3_store_thread_pools').with_value('10') + end + + end + + describe 'when overriding parameters' do + let :params do + { + :access_key => 'access2', + :secret_key => 'secret2', + :host => 'host2', + :bucket => 'bucket2', + :bucket_url_format => 'path', + :create_bucket_on_put => true, + :large_object_size => 200, + :large_object_chunk_size => 20, + :object_buffer_dir => '/tmp', + :thread_pools => 20, + :default_store => false + } + end + + it 'configures glance-api.conf' do + is_expected.to contain_glance_api_config('glance_store/s3_store_access_key').with_value('access2') + is_expected.to contain_glance_api_config('glance_store/s3_store_secret_key').with_value('secret2') + is_expected.to contain_glance_api_config('glance_store/s3_store_host').with_value('host2') + is_expected.to contain_glance_api_config('glance_store/s3_store_bucket').with_value('bucket2') + is_expected.to contain_glance_api_config('glance_store/s3_store_bucket_url_format').with_value('path') + is_expected.to contain_glance_api_config('glance_store/s3_store_create_bucket_on_put').with_value('true') + is_expected.to contain_glance_api_config('glance_store/s3_store_large_object_size').with_value('200') + is_expected.to contain_glance_api_config('glance_store/s3_store_large_object_chunk_size').with_value('20') + is_expected.to contain_glance_api_config('glance_store/s3_store_object_buffer_dir').with_value('/tmp') + is_expected.to contain_glance_api_config('glance_store/s3_store_thread_pools').with_value('20') + is_expected.to_not contain_glance_api_config('glance_store/default_store') + end + + end + + describe 'with invalid bucket_url_format' do + let :params do + { + :access_key => 'access', + :secret_key => 'secret', + :host => 'host', + :bucket => 'bucket', + :bucket_url_format => 'invalid' + } + end + + it 'throws errors' do + is_expected.to raise_error(Puppet::Error, /glance::backend::s3::bucket_url_format must be either "subdomain" or "path"/) + end + end + + describe 'with invalid large_object_chunk_size' do + let :params do + { + :access_key => 'access', + :secret_key => 'secret', + :host => 'host', + :bucket => 'bucket', + :large_object_chunk_size => 1 + } + end + + it 'throws error' do + is_expected.to raise_error(Puppet::Error, /glance::backend::s3::large_object_chunk_size must be an integer >= 5/) + end + end + + describe 'with non-integer large_object_chunk_size' do + let :params do + { + :access_key => 'access', + :secret_key => 'secret', + :host => 'host', + :bucket => 'bucket', + :large_object_chunk_size => 'string' + } + end + + it 'throws error' do + is_expected.to raise_error(Puppet::Error, /glance::backend::s3::large_object_chunk_size must be an integer >= 5/) + end + end +end