# TODO (rchurch): Make sure all includes have the correct global scope class openstack::cinder::params ( $service_enabled = false, $api_port = 8776, $api_proxy_port = 28776, $region_name = undef, $service_name = 'openstack-cinder', $service_type = 'volume', $service_type_v2 = 'volumev2', $service_type_v3 = 'volumev3', $configure_endpoint = true, $enabled_backends = [], $cinder_address = undef, $cinder_directory = '/opt/cgcs/cinder', $cinder_image_conversion_dir = '/opt/img-conversions/cinder', $cinder_device = '', $cinder_size = undef, $cinder_fs_device = '/dev/drbd4', $cinder_vg_name = 'cinder-volumes', $drbd_resource = 'drbd-cinder', $iscsi_ip_address = undef, $is_ceph_external = false, # Flag files $initial_cinder_config_flag = "${::platform::params::config_path}/.initial_cinder_config_complete", $initial_cinder_lvm_config_flag = "${::platform::params::config_path}/.initial_cinder_lvm_config_complete", $initial_cinder_ceph_config_flag = "${::platform::params::config_path}/.initial_cinder_ceph_config_complete", $node_cinder_lvm_config_flag = '/etc/platform/.node_cinder_lvm_config_complete', ) { $cinder_disk = regsubst($cinder_device, '-part\d+$', '') # Take appropriate actions based on the service states defined by: # - $is_initial_cinder => first time ever when cinder is configured; # - $is_initial_cinder_lvm => first time ever when LVM cinder is configured on the system; # - $is_initial_cinder_ceph => first time ever when Ceph cinder is configured on the system; # - $is_node_cinder_lvm => cinder LVM is configured/reconfigured on a node; # - $is_node_cinder_ceph => cinder Ceph is configured/reconfigured on a node. # These states are dependent on two aspects: # 1. A flag file present on the disk either in: # - DRBD synced /opt/platform, for system flags or in # - local folder /etc/platform, for node specific flags # 2. Controller standby or active state. Sometimes manifests are applied at the same time on both # controllers with most configuration happenning on the active node and minimal on the standby. if $service_enabled { # Check if this is the first time we ever configure cinder on this system if str2bool($::is_controller_active) and str2bool($::is_initial_cinder_config) { $is_initial_cinder = true } else { $is_initial_cinder = false } if 'lvm' in $enabled_backends { # Check if this is the first time we ever configure LVM on this system if str2bool($::is_controller_active) and str2bool($::is_initial_cinder_lvm_config) { $is_initial_cinder_lvm = true } else { $is_initial_cinder_lvm = false } # Check if we should configure/reconfigure cinder LVM for this node. # True in case of node reinstalls, device replacements, reconfigurations etc. if str2bool($::is_node_cinder_lvm_config) { $is_node_cinder_lvm = true } else { $is_node_cinder_lvm = false } } else { $is_initial_cinder_lvm = false $is_node_cinder_lvm = false } if 'ceph' in $enabled_backends or $is_ceph_external { # Check if this is the first time we ever configure Ceph on this system if str2bool($::is_controller_active) and str2bool($::is_initial_cinder_ceph_config) { $is_initial_cinder_ceph = true } else { $is_initial_cinder_ceph = false } } else { $is_initial_cinder_ceph = false } # Cinder needs to be running on initial configuration of either Ceph or LVM if str2bool($::is_controller_active) and ($is_initial_cinder_lvm or $is_initial_cinder_ceph) { $enable_cinder_service = true } else { $enable_cinder_service = false } } else { $is_initial_cinder = false $is_initial_cinder_lvm = false $is_node_cinder_lvm = false $is_initial_cinder_ceph = false $is_node_cinder_ceph = false $enable_cinder_service = false } } # Called from controller manifest class openstack::cinder inherits ::openstack::cinder::params { # TODO (rchurch): This will create the cinder DB on a system that may never run cinder. This make sense? #if $is_initial_cinder { if $::platform::params::init_database { include platform::postgresql::server include ::cinder::db::postgresql } # TODO (rchurch): Make this happen after config_controller? If we do that we should # exec 'cinder-manage db sync' as root instead of 'cinder' user #if $is_initial_cinder { if str2bool($::is_initial_config_primary) { include ::cinder::db::sync } include ::platform::params include ::platform::amqp::params include ::platform::network::mgmt::params $controller_address = $::platform::network::mgmt::params::controller_address group { 'cinder': ensure => 'present', gid => '165', } user { 'cinder': ensure => 'present', comment => 'OpenStack Cinder Daemons', gid => '165', groups => ['nobody', 'cinder', $::platform::params::protected_group_name], home => '/var/lib/cinder', password => '!!', password_max_age => '-1', password_min_age => '-1', shell => '/sbin/nologin', uid => '165', } if $service_enabled { file { "${cinder_directory}": ensure => 'directory', owner => 'root', group => 'root', mode => '0755', } -> file { "${cinder_image_conversion_dir}": ensure => 'directory', owner => 'root', group => 'root', mode => '0755', } -> file { "${cinder_directory}/data": ensure => 'directory', owner => 'root', group => 'root', mode => '0755', } } else { file { "${cinder_directory}": ensure => 'directory', owner => 'root', group => 'root', mode => '0755', } -> file { "${cinder_directory}/data": ensure => 'directory', owner => 'root', group => 'root', mode => '0755', } } class { '::cinder': rabbit_use_ssl => $::platform::amqp::params::ssl_enabled, default_transport_url => $::platform::amqp::params::transport_url, } include ::cinder::keystone::authtoken include ::cinder::scheduler include ::cinder::client include ::cinder::volume include ::cinder::ceilometer include ::cinder::glance include ::openstack::cinder::config include ::openstack::cinder::backends include ::openstack::cinder::backup include ::platform::multipath::params # TODO(mpeters): move to puppet module formal parameters cinder_config { 'DEFAULT/my_ip': value => $controller_address; 'DEFAULT/state_path': value => "${cinder_directory}/data"; # Reduce the number of RPCs that can be handled in parallel from the # default of 64. Doing too much at once (e.g. creating volumes) results # in a lot of thrashing and operations time out. # Liberty renamed this from rpc_thread_pool_size to executor_thread_pool_size 'DEFAULT/executor_thread_pool_size': value => '32'; 'DEFAULT/enable_force_upload': value => true; 'DEFAULT/use_multipath_for_image_xfer': value => $::platform::multipath::params::enabled; 'backend_defaults/use_multipath_for_image_xfer': value => $::platform::multipath::params::enabled; } # Run cinder-manage to purge deleted rows daily at the 30 minute mark cron { 'cinder-purge-deleted': ensure => 'present', command => '/usr/bin/cinder-purge-deleted-active', environment => 'PATH=/bin:/usr/bin:/usr/sbin', minute => '30', hour => '*/24', user => 'root', } } class openstack::cinder::config::default( $config_params ) inherits ::openstack::cinder::params { # Realize any service parameter provided DEFAULT section params of cinder.conf create_resources('cinder_config', hiera_hash('openstack::cinder::config::default::config_params', {})) } class openstack::cinder::config inherits ::openstack::cinder::params { include ::openstack::cinder::config::default } class openstack::cinder::backup inherits ::openstack::cinder::params { # For now only support file backend backup include ::cinder::backup::posix } class openstack::cinder::backends::san inherits ::openstack::cinder::params { include ::openstack::cinder::emc_vnx include ::openstack::cinder::backends::hpe3par include ::openstack::cinder::hpelefthand } class openstack::cinder::backends inherits ::openstack::cinder::params { class { '::cinder::backends': enabled_backends => $enabled_backends } if 'lvm' in $enabled_backends { include ::openstack::cinder::lvm } if 'ceph' in $enabled_backends or $is_ceph_external { include ::openstack::cinder::backends::ceph } include openstack::cinder::backends::san } class openstack::cinder::lvm::filesystem::drbd ( $device = '/dev/drbd4', $lv_name = 'cinder-lv', $mountpoint = '/opt/cinder', $port = '7792', $vg_name = 'cinder-volumes', $drbd_handoff = true, ) inherits ::openstack::cinder::params { include ::platform::drbd::params include ::platform::drbd::cgcs::params if str2bool($::is_primary_disk_rotational) { $resync_after = $::platform::drbd::cgcs::params::resource_name } else { $resync_after = undef } if (str2bool($::is_controller_active) or (str2bool($::is_standalone_controller) and $is_node_cinder_lvm) ) { # Run DRBD cinder initial setup in two cases # 1) first time Cinder LVM is configured, # 2) when cinder's disk is replaced on a standalone controller # (mostly to accommodate SX disk replacement). # Note: Cinder disk replacement is triggered from sysinv by removing # the checkpoint file behind is_node_cinder_lvm. $ha_primary = true $initial_setup = true $service_enable = true $service_ensure = "running" } else { $ha_primary = false $initial_setup = false $service_enable = false $service_ensure = "stopped" } if $is_node_cinder_lvm { # prepare disk for drbd file { '/etc/udev/mount.blacklist': ensure => present, mode => '0644', owner => 'root', group => 'root', } -> file_line { 'blacklist ${cinder_disk} automount': ensure => present, line => $cinder_disk, path => '/etc/udev/mount.blacklist', } } drbd::resource { $drbd_resource: disk => "\"${cinder_device}\"", port => $port, device => $device, mountpoint => $mountpoint, handlers => { before-resync-target => "/usr/local/sbin/sm-notify -s ${drbd_resource} -e sync-start", after-resync-target => "/usr/local/sbin/sm-notify -s ${drbd_resource} -e sync-end", }, host1 => $::platform::drbd::params::host1, host2 => $::platform::drbd::params::host2, ip1 => $::platform::drbd::params::ip1, ip2 => $::platform::drbd::params::ip2, manage => $is_node_cinder_lvm, ha_primary => $ha_primary, initial_setup => $initial_setup, automount => $::platform::drbd::params::automount, fs_type => $::platform::drbd::params::fs_type, link_util => $::platform::drbd::params::link_util, link_speed => $::platform::drbd::params::link_speed, num_parallel => $::platform::drbd::params::num_parallel, rtt_ms => $::platform::drbd::params::rtt_ms, cpumask => $::platform::drbd::params::cpumask, resync_after => $resync_after, require => [ Class['::platform::partitions'], File_line['final filter: update lvm global_filter'] ] } if ($is_initial_cinder_lvm or (str2bool($::is_standalone_controller) and $is_node_cinder_lvm) ){ # Recreate cinder-volumes in two cases: # 1) first time Cinder LVM is configured, # 2) when cinder's disk is replaced on a standalone controller # (mostly to accommodate SX disk replacement). # Note: Cinder disk replacement is triggered from sysinv by removing # the checkpoint file behind is_node_cinder_lvm. physical_volume { $device: ensure => present, require => Drbd::Resource[$drbd_resource] } -> volume_group { $vg_name: ensure => present, physical_volumes => $device, } -> # Create an initial LV, because the LVM ocf resource does not work with # an empty VG. logical_volume { 'anchor-lv': ensure => present, volume_group => $vg_name, size => '1M', size_is_minsize => true, } -> # Deactivate the VG now. If this isn't done, it prevents DRBD from # being stopped later by the SM. exec { 'Deactivate VG': command => "vgchange -a ln ${vg_name}", } -> # Make sure the primary resource is in the correct state so that on swact to # controller-1 sm has the resource in an acceptable state to become managed # and primary. But, if this primary is a single controller we will restart # SM so keep it primary # TODO (rchurch): fix up the drbd_handoff logic. exec { 'Set $drbd_resource role': command => str2bool($drbd_handoff) ? {true => "drbdadm secondary ${drbd_resource}", default => '/bin/true'}, unless => "drbdadm role ${drbd_resource} | egrep '^Secondary'", } } } class openstack::cinder::lvm( $lvm_type = 'thin', ) inherits ::openstack::cinder::params { # if $::platform::params::system_mode != 'simplex' { # include ::openstack::cinder::lvm::filesystem::drbd # } else { # include ::openstack::cinder::lvm::filesystem::simplex # } include ::openstack::cinder::lvm::filesystem::drbd file_line { 'snapshot_autoextend_threshold': path => '/etc/lvm/lvm.conf', match => '^\s*snapshot_autoextend_threshold +=.*', line => ' snapshot_autoextend_threshold = 80', } file_line { 'snapshot_autoextend_percent': path => '/etc/lvm/lvm.conf', match => '^\s*snapshot_autoextend_percent +=.*', line => ' snapshot_autoextend_percent = 20', } file { "${cinder_directory}/iscsi-target": ensure => 'directory', owner => 'root', group => 'root', mode => '0755', require => File[$cinder_directory], } -> file { "${cinder_directory}/iscsi-target/saveconfig.json": ensure => 'present', owner => 'root', group => 'root', mode => '0600', content => '{ "fabric_modules": [], "storage_objects": [], "targets": [] }', } if $lvm_type == 'thin' { $iscsi_lvm_config = { 'lvm/iscsi_target_flags' => {'value' => 'direct'}, 'lvm/lvm_type' => {'value' => 'thin'}, 'DEFAULT/max_over_subscription_ratio' => {'value' => 1.0} } } else { $iscsi_lvm_config = { 'lvm/iscsi_target_flags' => {'value' => 'direct'}, 'lvm/lvm_type' => {'value' => 'default'}, 'lvm/volume_clear' => {'value' => 'none'} } } cinder::backend::iscsi { 'lvm': iscsi_ip_address => $iscsi_ip_address, extra_options => $iscsi_lvm_config , volumes_dir => "${cinder_directory}/data/volumes", } } define openstack::cinder::backend::ceph( $backend_enabled = false, $backend_name, $rbd_user = 'cinder', $rbd_pool, $rbd_ceph_conf = '/etc/ceph/ceph.conf' ) { if $backend_enabled { cinder::backend::rbd {$backend_name: backend_host => '$host', rbd_pool => $rbd_pool, rbd_user => $rbd_user, rbd_ceph_conf => $rbd_ceph_conf, } } else { cinder_config { "${backend_name}/volume_backend_name": ensure => absent; "${backend_name}/volume_driver": ensure => absent; "${backend_name}/backend_host": ensure => absent; "${backend_name}/rbd_ceph_conf": ensure => absent; "${backend_name}/rbd_pool": ensure => absent; } } } class openstack::cinder::backends::ceph ( $ceph_backend_configs = {} ) inherits ::openstack::cinder::params { create_resources('openstack::cinder::backend::ceph', $ceph_backend_configs) } class openstack::cinder::emc_vnx( $feature_enabled, $config_params ) inherits ::openstack::cinder::params { create_resources('cinder_config', hiera_hash('openstack::cinder::emc_vnx::config_params', {})) if $feature_enabled { $scsi_id_ensure = 'link' } else { $scsi_id_ensure = 'absent' } #TODO(rchurch): Evaluate this with Pike... Still needed? # During creating EMC cinder bootable volume, linuxscsi.py in # python2-os-brick-1.1.0-1.el7.noarch invokes "scsi_id" command and # fails as "scsi_id" is not in the search PATH. So create a symlink # here. The fix is already in the later version of os-brick. We # can remove this code when python2-os-brick is upgraded. file { '/usr/bin/scsi_id': ensure => $scsi_id_ensure, owner => 'root', group => 'root', target => '/lib/udev/scsi_id', } } define openstack::cinder::backend::hpe3par { $hiera_params = "openstack::cinder::${name}::config_params" $feature_enabled = "openstack::cinder::${name}::feature_enabled" create_resources('cinder_config', hiera_hash($hiera_params, {})) if $feature_enabled { exec {"Including $name configuration": path => [ '/usr/bin', '/usr/sbin', '/bin', '/sbin' ], command => "echo Including $name configuration", } } } class openstack::cinder::backends::hpe3par ( $sections = [] ) inherits ::openstack::cinder::params { ::openstack::cinder::backend::hpe3par {$sections:} } class openstack::cinder::hpelefthand( $feature_enabled, $config_params ) inherits ::openstack::cinder::params { create_resources('cinder_config', hiera_hash('openstack::cinder::hpelefthand::config_params', {})) # As HP SANs are addon PS supported options, make sure we have explicit # logging showing this is being included when the feature is enabled. if $feature_enabled { exec {'Including hpelefthand configuration': path => [ '/usr/bin', '/usr/sbin', '/bin', '/sbin' ], command => 'echo Including hpelefthand configuration', } } } class openstack::cinder::firewall inherits ::openstack::cinder::params { if $service_enabled { platform::firewall::rule { 'cinder-api': service_name => 'cinder', ports => $api_port, } } } class openstack::cinder::haproxy inherits ::openstack::cinder::params { if $service_enabled { platform::haproxy::proxy { 'cinder-restapi': server_name => 's-cinder', public_port => $api_port, private_port => $api_port, } } } define openstack::cinder::api::backend( $type_enabled = false, $type_name, $backend_name ) { # Run it on the active controller, otherwise the prefetch step tries to query # cinder and can fail if str2bool($::is_controller_active) { if $type_enabled { cinder_type { $type_name: ensure => present, properties => ["volume_backend_name=${backend_name}"] } } else { cinder_type { $type_name: ensure => absent } } } } class openstack::cinder::api::backends( $ceph_type_configs = {} ) inherits ::openstack::cinder::params { # Only include cinder_type the first time an lvm or ceph backend is # initialized if $is_initial_cinder_lvm { ::openstack::cinder::api::backend { 'lvm-store': type_enabled => true, type_name => 'iscsi', backend_name => 'lvm' } } # Add/Remove any additional cinder ceph tier types create_resources('openstack::cinder::api::backend', $ceph_type_configs) # Add SAN volume types here when/if required } # Called from the controller manifest class openstack::cinder::api inherits ::openstack::cinder::params { include ::platform::params $api_workers = $::platform::params::eng_workers include ::platform::network::mgmt::params $api_host = $::platform::network::mgmt::params::controller_address $upgrade = $::platform::params::controller_upgrade if $service_enabled and (str2bool($::is_controller_active) or $upgrade) { include ::cinder::keystone::auth if $::platform::params::distributed_cloud_role == 'systemcontroller' { include ::dcorch::keystone::auth include ::platform::dcorch::firewall include ::platform::dcorch::haproxy } } class { '::cinder::api': bind_host => $api_host, service_workers => $api_workers, sync_db => $::platform::params::init_database, enabled => str2bool($enable_cinder_service) } if $::openstack::cinder::params::configure_endpoint { include ::openstack::cinder::firewall include ::openstack::cinder::haproxy } if $service_enabled { include ::openstack::cinder::api::backends } class { '::openstack::cinder::pre': stage => pre } class { '::openstack::cinder::post': stage => post } } class openstack::cinder::pre { include ::openstack::cinder::params $enabled = str2bool($::openstack::cinder::params::enable_cinder_service) if $::platform::params::distributed_cloud_role =='systemcontroller' and $enabled { # need to enable cinder-api-proxy in order to apply the cinder manifest exec { 'Enable Dcorch Cinder API Proxy': command => "systemctl enable dcorch-cinder-api-proxy; systemctl start dcorch-cinder-api-proxy", } } } class openstack::cinder::post inherits openstack::cinder::params { # Ensure that phases are marked as complete if $is_initial_cinder { file { $initial_cinder_config_flag: ensure => present } } if $is_initial_cinder_lvm { file { $initial_cinder_lvm_config_flag: ensure => present } } if $is_initial_cinder_ceph { file { $initial_cinder_ceph_config_flag: ensure => present } # To workaround an upstream bug in rbd code, we need to create # an empty file /etc/ceph/ceph.client.None.keyring in order to # do cinder backup and restore. file { "/etc/ceph/ceph.client.None.keyring": ensure => file, owner => 'root', group => 'root', mode => '0644', } } if $is_node_cinder_lvm { file { $node_cinder_lvm_config_flag: ensure => present } } # cinder-api needs to be running in order to apply the cinder manifest, # however, it needs to be stopped/disabled to allow SM to manage the service. # To allow for the transition it must be explicitly stopped. Once puppet # can directly handle SM managed services, then this can be removed. exec { 'Disable OpenStack - Cinder API': command => "systemctl stop openstack-cinder-api; systemctl disable openstack-cinder-api", require => Class['openstack::cinder'], } if $::platform::params::distributed_cloud_role =='systemcontroller' { # stop and disable the cinder api proxy to allow SM to manage the service exec { 'Disable Dcorch Cinder API Proxy': command => "systemctl stop dcorch-cinder-api-proxy; systemctl disable dcorch-cinder-api-proxy", require => Class['openstack::cinder'], } } } class openstack::cinder::reload { platform::sm::restart {'cinder-scheduler': } platform::sm::restart {'cinder-volume': } platform::sm::restart {'cinder-backup': } platform::sm::restart {'cinder-api': } } # Called for runtime changes class openstack::cinder::runtime inherits ::openstack::cinder::params { include ::openstack::cinder include ::openstack::cinder::api class { '::openstack::cinder::reload': stage => post } } # Called for runtime changes on region class openstack::cinder::endpoint::runtime { if str2bool($::is_controller_active) { include ::cinder::keystone::auth } } # Called for service_parameter runtime changes: # - Currently cinder.conf only changes # - external SAN backend sections # - default section changes class openstack::cinder::service_param::runtime inherits ::openstack::cinder::params { class { '::cinder::backends': enabled_backends => $enabled_backends } include ::openstack::cinder::config::default include ::openstack::cinder::backends::san class { '::openstack::cinder::reload': stage => post } } # Called for rbd backend runtime changes class openstack::cinder::backends::ceph::runtime inherits ::openstack::cinder::params { class { '::cinder::backends': enabled_backends => $enabled_backends } if $service_enabled { include ::openstack::cinder::backends::ceph include ::openstack::cinder::api::backends } class { '::openstack::cinder::reload': stage => post } }