iscsi multipath support

Add service parameter to enable multiple iSCSI multipath:

   system service-parameter-add cinder DEFAULT multipath=true
   system service-parameter-apply cinder

Add Puppet manifests for multipathd service.

When multipath service parameter is enabled then controller
and compute nodes go into config out-of-date status. They
need to be locked/unlocked to apply the new configuration:

1. cinder.conf (only for controllers)

       [DEFAULT]
       use_multipath_for_image_xfer=true

       [backend_defaults]
       use_multipath_for_image_xfer=true

   Note:
     a. enforce_multipath_for_image_xfer option is not set
        to allow fallback to single path in case multipathd
        service is not available

2.  load dm_multipath kernel module

3.  multipath.conf
      defaults {
          user_friendly_names yes
          find_multipaths yes
      }

      blacklist {
          device {
              vendor "*"
          }
      }

      blacklist_exceptions {
          property "(SCSI_IDENT_|ID_WWN)"
          device {
              vendor "3PARdata"
          }
      }

    Notes:
      a. multipath support is enabled only for hpe3par
         iSCSI devices by:
         - blacklisting devices from all vendors
         - blacklisting all devices that do not
           have ID_WWN or SCSI_IDENT_ udev entries
           (see multipath.conf manual page)
         - making an exception for 3PARdata vendor

      b. multipath service is managed by systemd

Story: 2002996
Task: 27040
Change-Id: Ib34d4542f93e78a507073f43808658be2b9fc87d
Signed-off-by: Daniel Badea <daniel.badea@windriver.com>
This commit is contained in:
Daniel Badea 2018-10-03 20:50:53 +00:00
parent cc447124c2
commit 5e5578134f
11 changed files with 139 additions and 5 deletions

View File

@ -33,6 +33,7 @@ include ::platform::collectd
include ::platform::filesystem::compute
include ::platform::docker
include ::platform::kubernetes::worker
include ::platform::multipath
include ::openstack::client
include ::openstack::neutron

View File

@ -66,6 +66,8 @@ include ::platform::collectd
include ::platform::fm
include ::platform::fm::api
include ::platform::multipath
include ::openstack::client
include ::openstack::keystone
include ::openstack::keystone::api

View File

@ -197,7 +197,8 @@ class openstack::cinder
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;
@ -208,6 +209,8 @@ class openstack::cinder
# 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

View File

@ -142,6 +142,7 @@ class openstack::nova::compute (
include ::platform::network::mgmt::params
include ::platform::network::infra::params
include ::platform::multipath::params
include ::nova::keystone::authtoken
include ::nova::compute::neutron
@ -280,6 +281,7 @@ class openstack::nova::compute (
'libvirt/libvirt_images_type': value => $libvirt_images_type;
'libvirt/live_migration_inbound_addr': value => "${::platform::params::hostname}-infra";
'libvirt/live_migration_uri': ensure => absent;
'libvirt/volume_use_multipath': value => $::platform::multipath::params::enabled;
# enable auto-converge by default
'libvirt/live_migration_permit_auto_converge': value => "True";

View File

@ -0,0 +1,39 @@
class platform::multipath::params (
$enabled = false,
) {
}
class platform::multipath
inherits platform::multipath::params {
if $enabled {
file { '/etc/multipath.conf':
ensure => 'present',
mode => '0644',
content => template("platform/multipath.conf.erb")
} ->
service { 'start-multipathd':
ensure => 'running',
enable => true,
name => 'multipathd',
hasstatus => true,
hasrestart => true,
} ->
exec { 'systemctl-enable-multipathd':
command => '/usr/bin/systemctl enable multipathd.service',
}
} else {
service { 'stop-multipathd':
ensure => 'stopped',
enable => false,
name => 'multipathd',
hasstatus => true,
hasrestart => true,
} ->
exec { 'systemctl-disable-multipathd':
command => '/usr/bin/systemctl disable multipathd.service',
} ->
file { '/etc/multipath.conf':
ensure => 'absent',
}
}
}

View File

@ -0,0 +1,17 @@
defaults {
user_friendly_names yes
find_multipaths yes
}
blacklist {
device {
vendor "*"
}
}
blacklist_exceptions {
property "(SCSI_IDENT_|ID_WWN)"
device {
vendor "3PARdata"
}
}

View File

@ -188,6 +188,12 @@ class ServiceParameterController(rest.RestController):
p.section == constants.SERVICE_PARAM_SECTION_CINDER_HPE3PAR_STATE or
p.section == constants.SERVICE_PARAM_SECTION_CINDER_HPELEFTHAND_STATE))]
# filter out cinder multipath state
parms = [p for p in parms if not(
p.service == constants.SERVICE_TYPE_CINDER and
p.section == constants.SERVICE_PARAM_SECTION_CINDER_DEFAULT and
p.name == constants.SERVICE_PARAM_CINDER_DEFAULT_MULTIPATH_STATE)]
# filter out firewall_rules_id
parms = [p for p in parms if not (
p.service == constants.SERVICE_TYPE_PLATFORM and p.section ==

View File

@ -848,6 +848,9 @@ SERVICE_PARAM_SECTION_IDENTITY_CONFIG = 'config'
SERVICE_PARAM_SECTION_CINDER_DEFAULT = 'DEFAULT'
SERVICE_PARAM_CINDER_DEFAULT_VOLUME_TYPE = 'default_volume_type'
SERVICE_PARAM_CINDER_DEFAULT_MULTIPATH = 'multipath'
SERVICE_PARAM_CINDER_DEFAULT_MULTIPATH_STATE = 'multipath.state'
SERVICE_PARAM_CINDER_DEFAULT_MULTIPATH_STATE_DISABLED = 'false'
SERVICE_PARAM_SECTION_CINDER_EMC_VNX = 'emc_vnx'
SERVICE_PARAM_CINDER_EMC_VNX_ENABLED = 'enabled'

View File

@ -1096,7 +1096,8 @@ CINDER_DEFAULT_PARAMETER_REQUIRED = []
CINDER_DEFAULT_PARAMETER_OPTIONAL = (
CINDER_DEFAULT_PARAMETER_REQUIRED +
CINDER_DEFAULT_PARAMETER_PROTECTED + [
'default_volume_type'
constants.SERVICE_PARAM_CINDER_DEFAULT_VOLUME_TYPE,
constants.SERVICE_PARAM_CINDER_DEFAULT_MULTIPATH,
]
)
@ -1104,14 +1105,16 @@ CINDER_DEFAULT_PARAMETER_VALIDATOR = {
# Mandatory parameters
# Required parameters
# Optional parameters
'default_volume_type': _validate_not_empty
constants.SERVICE_PARAM_CINDER_DEFAULT_VOLUME_TYPE: _validate_not_empty,
constants.SERVICE_PARAM_CINDER_DEFAULT_MULTIPATH: _validate_boolean,
}
CINDER_DEFAULT_PARAMETER_RESOURCE = {
# Mandatory parameters
# Required parameters
# Optional parameters
'default_volume_type': None
constants.SERVICE_PARAM_CINDER_DEFAULT_VOLUME_TYPE: None,
constants.SERVICE_PARAM_CINDER_DEFAULT_MULTIPATH: None,
}
CINDER_EMC_VNX_SAN_IP = 'san_ip'

View File

@ -6880,6 +6880,12 @@ class ConductorManager(service.PeriodicService):
}
self._config_apply_runtime_manifest(context, config_uuid, config_dict)
multipath_state_changed = self._multipath_update_state()
if multipath_state_changed:
self._config_update_hosts(context,
[constants.CONTROLLER, constants.COMPUTE],
reboot=True)
elif service == constants.SERVICE_TYPE_PLATFORM:
config_dict = {
"personalities": personalities,
@ -7036,6 +7042,43 @@ class ConductorManager(service.PeriodicService):
LOG.info("Updating %s to %s" % (name, new_state))
self.dbapi.service_parameter_update(status_param.uuid, {'value': new_state})
def _multipath_get_state(self):
try:
state = self.dbapi.service_parameter_get_one(
constants.SERVICE_TYPE_CINDER,
constants.SERVICE_PARAM_SECTION_CINDER_DEFAULT,
constants.SERVICE_PARAM_CINDER_DEFAULT_MULTIPATH_STATE
)
except exception.NotFound:
state = self.dbapi.service_parameter_create({
'service': constants.SERVICE_TYPE_CINDER,
'section': constants.SERVICE_PARAM_SECTION_CINDER_DEFAULT,
'name': constants.SERVICE_PARAM_CINDER_DEFAULT_MULTIPATH_STATE,
'value': constants.SERVICE_PARAM_CINDER_DEFAULT_MULTIPATH_STATE_DISABLED
})
return state
def _multipath_update_state(self):
"""Update multipath service parameter state
:return True if multipath state changed, False otherwise
"""
state_param = self._multipath_get_state()
current_state = state_param.value
try:
state = self.dbapi.service_parameter_get_one(
constants.SERVICE_TYPE_CINDER,
constants.SERVICE_PARAM_SECTION_CINDER_DEFAULT,
constants.SERVICE_PARAM_CINDER_DEFAULT_MULTIPATH
).value
except exception.NotFound:
state = constants.SERVICE_PARAM_CINDER_DEFAULT_MULTIPATH_STATE_DISABLED
if current_state != state:
self.dbapi.service_parameter_update(
state_param.uuid, dict(value=state))
return True
return False
def update_sdn_controller_config(self, context):
"""Update the SDN controller configuration"""
LOG.info("update_sdn_controller_config")

View File

@ -18,7 +18,8 @@ LOG = logging.getLogger(__name__)
SP_CINDER_DEFAULT = constants.SERVICE_PARAM_SECTION_CINDER_DEFAULT
SP_CINDER_DEFAULT_PREFIX = 'openstack::cinder::config::default'
SP_CINDER_DEFAULT_ALL_SUPPORTED_PARAMS = [
constants.SERVICE_PARAM_CINDER_DEFAULT_VOLUME_TYPE
constants.SERVICE_PARAM_CINDER_DEFAULT_VOLUME_TYPE,
constants.SERVICE_PARAM_CINDER_DEFAULT_MULTIPATH,
# Hardcoded params: params we always want set
]
@ -146,9 +147,21 @@ def sp_common_post_process(config, section, section_map, is_service_enabled,
config[conf_name] = provided_params_puppet_format
#
# Section specific post processing calls: DEFAULT, emc_vnx, hpe3par, hpelefthand
#
def sp_multipath_post_process(config, provided_params):
# DEFAULT/multipath does not map 1:1 to an entry in cinder.conf
param = constants.SERVICE_PARAM_CINDER_DEFAULT_MULTIPATH
multipath_key = 'platform::multipath::params::enabled'
if provided_params.get(param, 'false').lower() == 'true':
config[multipath_key] = True
else:
config.pop(multipath_key, None)
provided_params.pop(param, None)
param_state = constants.SERVICE_PARAM_CINDER_DEFAULT_MULTIPATH_STATE
provided_params.pop(param_state, None)
def sp_default_post_process(config, section, section_map,
@ -180,6 +193,8 @@ def sp_default_post_process(config, section, section_map,
if param not in provided_params:
absent_params.append(param)
sp_multipath_post_process(config, provided_params)
sp_common_post_process(config, section, section_map, is_service_enabled,
enabled_backends, is_a_feature=False)