From 34873ff7639f08ab64b9a032abd81e004b9f8b7d Mon Sep 17 00:00:00 2001 From: Emilien Macchi Date: Fri, 14 Mar 2014 20:44:20 +0100 Subject: [PATCH] volume/storage: Add NetApp support This patch aims to: - Transform cloud::volume::storage to support multi-backend feature from puppet-cinder - Add NetApp backend support - Create Volume Types for each backend - Add documentation to cloud::volume::storage - Add a note to the README to inform that we support now NetApp - Keep backward compatibility with previous module release (without multi-backend, only RBD) - Configure scheduler if multi backend is enabled Feature #358 Signed-off-by: Emilien Macchi --- README.md | 1 + manifests/volume/controller.pp | 12 +- manifests/volume/storage.pp | 171 ++++++++++++++++--- spec/classes/cloud_volume_controller_spec.rb | 18 +- spec/classes/cloud_volume_storage_spec.rb | 111 ++++++++++-- 5 files changed, 273 insertions(+), 40 deletions(-) diff --git a/README.md b/README.md index 6edf837b..04d4c034 100644 --- a/README.md +++ b/README.md @@ -32,6 +32,7 @@ Cinder, Glance and Nova can use Ceph as backend storage, using [puppet-ceph](htt Only KVM and QEMU are supported as hypervisors, for now. Neutron use ML2 plugin with GRE and Open-vSwitch drivers. +Cinder has multi-backend support with Ceph used by default and NetApp as an option. [Puppet Modules](http://docs.puppetlabs.com/learning/modules1.html#modules) are a collection of related contents that can be used to model the configuration of a discrete service. diff --git a/manifests/volume/controller.pp b/manifests/volume/controller.pp index 5c2a0941..85e7e120 100644 --- a/manifests/volume/controller.pp +++ b/manifests/volume/controller.pp @@ -23,6 +23,8 @@ class cloud::volume::controller( $ks_glance_internal_host = $os_params::ks_glance_internal_host, $ks_glance_api_internal_port = $os_params::ks_glance_api_internal_port, $api_eth = $os_params::api_eth, + # Maintain backward compatibility for multi-backend + $volume_multi_backend = false, # TODO(EmilienM) Disabled for now: http://git.io/kfTmcA # $backup_ceph_pool = $os_params::cinder_rbd_backup_pool, # $backup_ceph_user = $os_params::cinder_rbd_backup_user @@ -30,7 +32,15 @@ class cloud::volume::controller( include 'cloud::volume' - class { 'cinder::scheduler': } + if ! $volume_multi_backend { + $scheduler_driver_real = false + } else { + $scheduler_driver_real = 'cinder.scheduler.filter_scheduler.FilterScheduler' + } + + class { 'cinder::scheduler': + scheduler_driver => $scheduler_driver_real + } class { 'cinder::api': keystone_password => $ks_cinder_password, diff --git a/manifests/volume/storage.pp b/manifests/volume/storage.pp index 24759759..3d77a81a 100644 --- a/manifests/volume/storage.pp +++ b/manifests/volume/storage.pp @@ -17,12 +17,22 @@ # # === Parameters # +# [*volume_multi_backend*] +# (optionnal) To maintain backward compatibility with previous versions of this module, +# this parameter aims to enable or not the multi-backend feature. +# Defaults to false +# +# [*rbd_backend*] +# (optionnal) Use RBD backend or not. +# Defaults to true +# +# [*rbd_backend_name*] +# (optionnal) Backend name presented to end-user. +# Defaults to 'rbd' +# # [*cinder_rbd_pool*] # (optional) Specifies the pool name for the block device driver. # -# [*glance_api_version*] -# (optional) Required for Ceph functionality. -# # [*cinder_rbd_user*] # (optional) A required parameter to configure OS init scripts and cephx. # @@ -48,38 +58,157 @@ # A value of zero disables cloning # Defaults to '5' # +# [*ks_keystone_internal_proto*] +# (optional) Protocol used to connect to API. Could be 'http' or 'https'. +# Defaults to 'http' # +# [*ks_keystone_internal_host*] +# (optional) Internal Hostname or IP to connect to Keystone API +# Defaults to '127.0.0.1' +# +# [*ks_keystone_internal_port*] +# (optional) TCP port to connect to Keystone API from admin network +# Default to '5000' +# +# [*ks_cinder_password*] +# (optional) Password used by Cinder to connect to Keystone API +# Defaults to 'secrete' +# +# [*netapp_backend*] +# (optionnal) Use NetApp backend or not. +# Defaults to false +# +# [*netapp_backend_name*] +# (optionnal) Backend name presented to end-user. +# Defaults to 'rbd' +# +# [*netapp_login*] +# (optionnal) Administrative user account name used to access the storage +# system. +# Defaults to 'netapp' +# +# [*netapp_password*] +# (optionnal) Password for the administrative user account specified in the +# netapp_login parameter. +# Defaults to 'secrete' +# +# [*netapp_server_hostname*] +# (optionnal) The hostname (or IP address) for the storage system. +# Defaults to '127.0.0.1' +# + + class cloud::volume::storage( - $glance_api_version = $os_params::glance_api_version, + # Maintain backward compatibility + $volume_multi_backend = false, $cinder_rbd_pool = $os_params::cinder_rbd_pool, $cinder_rbd_user = $os_params::cinder_rbd_user, $cinder_rbd_secret_uuid = $os_params::ceph_fsid, + # RBD is our reference backend by default. + $rbd_backend = true, + $rbd_backend_name = 'rbd', + $ks_keystone_internal_proto = 'http', + $ks_keystone_internal_port = '5000', + $ks_keystone_internal_host = '127.0.0.1', + $ks_cinder_password = 'secrete', + # NetApp stays an option by default. + $netapp_backend = false, + $netapp_backend_name = 'netapp', + $netapp_server_hostname = '127.0.0.1', + $netapp_login = 'netapp', + $netapp_password = 'secrete', + # Deprecated parameters + $glance_api_version = '2', $cinder_rbd_conf = '/etc/ceph/ceph.conf', $cinder_rbd_flatten_volume_from_snapshot = false, - $cinder_rbd_max_clone_depth = '5', + $cinder_rbd_max_clone_depth = '5' ) { include 'cloud::volume' include 'cinder::volume' - class { 'cinder::volume::rbd': - rbd_pool => $cinder_rbd_pool, - glance_api_version => $glance_api_version, - rbd_user => $cinder_rbd_user, - rbd_secret_uuid => $cinder_rbd_secret_uuid, - rbd_ceph_conf => $cinder_rbd_conf, - rbd_flatten_volume_from_snapshot => $cinder_rbd_flatten_volume_from_snapshot, - rbd_max_clone_depth => $cinder_rbd_max_clone_depth, - } + if $volume_multi_backend { + # Manage Volume types. + # It allows to the end-user to choose from which backend he would like to provision a volume. + # Cinder::Type requires keystone credentials + Cinder::Type { + os_tenant_name => 'services', + os_username => 'cinder', + os_password => $ks_cinder_password, + os_auth_url => "${ks_keystone_internal_proto}://${ks_keystone_internal_host}:${ks_keystone_internal_port}/v2.0" + } - Ceph::Key <<| title == $cinder_rbd_user |>> - file { "/etc/ceph/ceph.client.${cinder_rbd_user}.keyring": - owner => 'cinder', - group => 'cinder', - mode => '0400', - require => Ceph::Key[$cinder_rbd_user] + if $rbd_backend { + # Configure RBD as a backend + cinder::backend::rbd {"${rbd_backend_name}": + rbd_pool => $cinder_rbd_pool, + rbd_user => $cinder_rbd_user, + rbd_secret_uuid => $cinder_rbd_secret_uuid + } + + # Configure a specific Volume Type + cinder::type {'rbd': + set_key => 'volume_backend_name', + set_value => $rbd_backend_name + } + + # Configure Ceph keyring + Ceph::Key <<| title == $cinder_rbd_user |>> + file { "/etc/ceph/ceph.client.${cinder_rbd_user}.keyring": + owner => 'cinder', + group => 'cinder', + mode => '0400', + require => Ceph::Key[$cinder_rbd_user] + } + Concat::Fragment <<| title == 'ceph-client-os' |>> + } + + if $netapp_backend { + # Configure NetApp as a backend + cinder::backend::netapp {"${netapp_backend_name}": + netapp_server_hostname => $netapp_server_hostname, + netapp_login => $netapp_login, + netapp_password => $netapp_password + } + + # Configure a specific Volume Type + cinder::type {'netapp': + set_key => 'volume_backend_name', + set_value => $netapp_backend_name + } + } + + # TODO(EmilienM) need to be optimized: + if $netapp_backend and $rbd_backend { + $enabled_backends = ['netapp', 'rbd'] + } elsif $netapp_backend and ! $rbd_backend { + $enabled_backends = ['netapp'] + } elsif ! $netapp_backend and $rbd_backend { + $enabled_backends = ['rbd'] + } else { + fail('no cinder backend has been enabled on storage nodes.') + } + class {'cinder::backends': enabled_backends => $enabled_backends } + } else { + # Backward compatibility + class { 'cinder::volume::rbd': + rbd_pool => $cinder_rbd_pool, + glance_api_version => $glance_api_version, + rbd_user => $cinder_rbd_user, + rbd_secret_uuid => $cinder_rbd_secret_uuid, + rbd_ceph_conf => $cinder_rbd_conf, + rbd_flatten_volume_from_snapshot => $cinder_rbd_flatten_volume_from_snapshot, + rbd_max_clone_depth => $cinder_rbd_max_clone_depth + } + Ceph::Key <<| title == $cinder_rbd_user |>> + file { "/etc/ceph/ceph.client.${cinder_rbd_user}.keyring": + owner => 'cinder', + group => 'cinder', + mode => '0400', + require => Ceph::Key[$cinder_rbd_user] + } + Concat::Fragment <<| title == 'ceph-client-os' |>> } - Concat::Fragment <<| title == 'ceph-client-os' |>> } diff --git a/spec/classes/cloud_volume_controller_spec.rb b/spec/classes/cloud_volume_controller_spec.rb index bb68b427..475a1fd6 100644 --- a/spec/classes/cloud_volume_controller_spec.rb +++ b/spec/classes/cloud_volume_controller_spec.rb @@ -43,6 +43,7 @@ describe 'cloud::volume::controller' do :ks_keystone_internal_host => '10.0.0.1', :ks_glance_internal_host => '10.0.0.1', :ks_glance_api_internal_port => '9292', + :volume_multi_backend => false, # TODO(EmilienM) Disabled for now: http://git.io/kfTmcA #:backup_ceph_user => 'cinder', #:backup_ceph_pool => 'ceph_backup_cinder', @@ -71,8 +72,21 @@ describe 'cloud::volume::controller' do ) end - it 'configure cinder scheduler' do - should contain_class('cinder::scheduler') + it 'configure cinder scheduler without multi-backend' do + should contain_class('cinder::scheduler').with( + :scheduler_driver => false + ) + end + + context 'with multi-backend' do + before :each do + params.merge!( :volume_multi_backend => true ) + end + it 'configure cinder scheduler with multi-backend' do + should contain_class('cinder::scheduler').with( + :scheduler_driver => 'cinder.scheduler.filter_scheduler.FilterScheduler' + ) + end end # TODO(Emilien) Disabled for now: http://git.io/uM5sgg diff --git a/spec/classes/cloud_volume_storage_spec.rb b/spec/classes/cloud_volume_storage_spec.rb index f7f41e48..2851de95 100644 --- a/spec/classes/cloud_volume_storage_spec.rb +++ b/spec/classes/cloud_volume_storage_spec.rb @@ -38,10 +38,17 @@ describe 'cloud::volume::storage' do end let :params do - { :cinder_rbd_pool => 'ceph_cinder', - :cinder_rbd_user => 'cinder', - :cinder_rbd_secret_uuid => 'secrete', - :glance_api_version => '2' } + { :volume_multi_backend => true, + :cinder_rbd_pool => 'ceph_cinder', + :cinder_rbd_user => 'cinder', + :cinder_rbd_secret_uuid => 'secrete', + :rbd_backend => true, + :rbd_backend_name => 'lowcost', + :ks_keystone_internal_proto => 'http', + :ks_keystone_internal_port => '5000', + :ks_keystone_internal_host => 'keystone.host', + :ks_cinder_password => 'secrete', + :netapp_backend => false } end it 'configure cinder common' do @@ -68,21 +75,93 @@ describe 'cloud::volume::storage' do ) end - it 'configure cinder volume with rbd backend' do - + it 'configure cinder volume service' do should contain_class('cinder::volume') - - should contain_class('cinder::volume::rbd').with( - :rbd_pool => 'ceph_cinder', - :glance_api_version => '2', - :rbd_user => 'cinder', - :rbd_secret_uuid => 'secrete', - :rbd_ceph_conf => '/etc/ceph/ceph.conf', - :rbd_flatten_volume_from_snapshot => false, - :rbd_max_clone_depth => '5' - ) end + context 'with RBD backend' do + before :each do + params.merge!( :rbd_backend => true ) + end + + it 'configures rbd volume driver' do + should contain_cinder_config('lowcost/volume_backend_name').with_value('lowcost') + should contain_cinder_config('lowcost/rbd_pool').with_value('ceph_cinder') + should contain_cinder_config('lowcost/rbd_user').with_value('cinder') + should contain_cinder_config('lowcost/rbd_secret_uuid').with_value('secrete') + should contain_cinder__type('rbd').with( + :set_key => 'volume_backend_name', + :set_value => 'lowcost' + ) + end + end + + context 'with NetApp backend' do + before :each do + params.merge!( + :netapp_backend => true, + :netapp_backend_name => 'premium', + :netapp_server_hostname => 'netapp-server.host', + :netapp_login => 'joe', + :netapp_password => 'secrete' + ) + end + it 'configures netapp volume driver' do + should contain_cinder_config('premium/volume_backend_name').with_value('premium') + should contain_cinder_config('premium/netapp_login').with_value('joe') + should contain_cinder_config('premium/netapp_password').with_value('secrete') + should contain_cinder_config('premium/netapp_server_hostname').with_value('netapp-server.host') + should contain_cinder__type('netapp').with( + :set_key => 'volume_backend_name', + :set_value => 'premium' + ) + end + end + + context 'without any backend' do + before :each do + params.merge!( + :netapp_backend => false, + :rbd_backend => false + ) + end + it 'should fail to configure cinder-volume'do + expect { subject }.to raise_error(/no cinder backend has been enabled on storage nodes./) + end + end + + context 'with all backends enabled' do + before :each do + params.merge!( + :netapp_backend => true, + :rbd_backend => true + ) + end + it 'configure all cinder backends' do + should contain_class('cinder::backends').with( + :enabled_backends => ['netapp', 'rbd'] + ) + end + end + + context 'with backward compatiblity (without multi-backend)' do + before :each do + params.merge!( + :volume_multi_backend => false, + ) + end + it 'configure rbd volume driver without multi-backend' do + should contain_class('cinder::volume::rbd').with( + :rbd_pool => 'ceph_cinder', + :rbd_user => 'cinder', + :rbd_secret_uuid => 'secrete', + :rbd_ceph_conf => '/etc/ceph/ceph.conf', + :rbd_flatten_volume_from_snapshot => false, + :rbd_max_clone_depth => '5', + :glance_api_version => '2' + ) + end + end end context 'on Debian platforms' do