Honor multipath config everywhere

There are multiple places in Cinder where the os-brick call to get the
connector properties is not passing the "multipath" and
"enforce_multipath" configuration options.

This means that some driver won't return a multipathed connection
information on the initialize_connection RPC call, resulting in a single
pathed attachment even when the os-brick connector is instantiated with
the right configuration option.

This patch fixes the different calls where this is an issue:

- Backup create
- Backup restore
- Kaminario create volume from snapshot
- Kaminario create volume from volume
- Volume rekeying

And also in places where this is not affecting operations because
drivers are always returning multipathed information:

- Unity driver
- IBM FlashSystem

Closes-Bug: #1951982
Closes-Bug: #1951977
Closes-Bug: #1951981
Change-Id: I73ab87b5aaa4835a814389bc1cdd8016d75f52ef
This commit is contained in:
Gorka Eguileor 2021-11-23 17:27:24 +01:00
parent 85387cae8b
commit bf23678fe0
9 changed files with 46 additions and 11 deletions

View File

@ -456,7 +456,8 @@ class BackupManager(manager.SchedulerDependentManager):
previous_status = volume.get('previous_status', None) previous_status = volume.get('previous_status', None)
backup_service = self.service(context) backup_service = self.service(context)
properties = volume_utils.brick_get_connector_properties() properties = volume_utils.brick_get_connector_properties(
CONF.use_multipath_for_image_xfer, enforce_multipath=False)
updates = {} updates = {}
try: try:
@ -724,7 +725,8 @@ class BackupManager(manager.SchedulerDependentManager):
orig_key_id = volume.encryption_key_id orig_key_id = volume.encryption_key_id
backup_service = self.service(context) backup_service = self.service(context)
properties = volume_utils.brick_get_connector_properties() properties = volume_utils.brick_get_connector_properties(
CONF.use_multipath_for_image_xfer, enforce_multipath=False)
secure_enabled = ( secure_enabled = (
self.volume_rpcapi.secure_file_operations_enabled(context, self.volume_rpcapi.secure_file_operations_enabled(context,
volume)) volume))

View File

@ -729,7 +729,7 @@ class BackupTestCase(BaseBackupTest):
mock_attach_device.assert_called_once_with(self.ctxt, vol, mock_attach_device.assert_called_once_with(self.ctxt, vol,
properties, False) properties, False)
mock_get_backup_device.assert_called_once_with(self.ctxt, backup, vol) mock_get_backup_device.assert_called_once_with(self.ctxt, backup, vol)
mock_get_conn.assert_called_once_with() mock_get_conn.assert_called_once_with(False, enforce_multipath=False)
mock_detach_device.assert_called_once_with(self.ctxt, attach_info, mock_detach_device.assert_called_once_with(self.ctxt, attach_info,
vol, properties, False, vol, properties, False,
force=True, force=True,
@ -977,7 +977,7 @@ class BackupTestCase(BaseBackupTest):
mock_initialize_connection_snapshot.assert_called_once_with( mock_initialize_connection_snapshot.assert_called_once_with(
self.ctxt, snap, properties) self.ctxt, snap, properties)
mock_get_backup_device.assert_called_once_with(self.ctxt, backup, vol) mock_get_backup_device.assert_called_once_with(self.ctxt, backup, vol)
mock_get_conn.assert_called_once_with() mock_get_conn.assert_called_once_with(False, enforce_multipath=False)
mock_terminate_connection_snapshot.assert_called_once_with( mock_terminate_connection_snapshot.assert_called_once_with(
self.ctxt, snap, properties, force=True) self.ctxt, snap, properties, force=True)
mock_remove_export_snapshot.assert_called_once_with( mock_remove_export_snapshot.assert_called_once_with(
@ -1282,7 +1282,7 @@ class BackupTestCase(BaseBackupTest):
mock_open.assert_called_once_with('/dev/null', exp_open_mode) mock_open.assert_called_once_with('/dev/null', exp_open_mode)
mock_temporary_chown.assert_called_once_with('/dev/null') mock_temporary_chown.assert_called_once_with('/dev/null')
mock_get_conn.assert_called_once_with() mock_get_conn.assert_called_once_with(False, enforce_multipath=False)
vol.status = 'available' vol.status = 'available'
vol.obj_reset_changes() vol.obj_reset_changes()
mock_secure_enabled.assert_called_once_with(self.ctxt, vol) mock_secure_enabled.assert_called_once_with(self.ctxt, vol)

View File

@ -51,6 +51,8 @@ class MockConfig(object):
self.driver_ssl_cert_verify = True self.driver_ssl_cert_verify = True
self.driver_ssl_cert_path = None self.driver_ssl_cert_path = None
self.remove_empty_host = False self.remove_empty_host = False
self.use_multipath_for_image_xfer = False
self.enforce_multipath_for_image_xfer = False
def safe_get(self, name): def safe_get(self, name):
return getattr(self, name) return getattr(self, name)
@ -391,7 +393,7 @@ def get_backend_qos_specs(volume):
return None return None
def get_connector_properties(): def get_connector_properties(use_multipath, enforce_multipath):
return {'host': 'host1', 'wwpns': 'abcdefg'} return {'host': 'host1', 'wwpns': 'abcdefg'}

View File

@ -143,6 +143,8 @@ class TestKaminarioCommon(test.TestCase):
self.conf.volume_dd_blocksize = 2 self.conf.volume_dd_blocksize = 2
self.conf.disable_discovery = False self.conf.disable_discovery = False
self.conf.unique_fqdn_network = True self.conf.unique_fqdn_network = True
self.conf.use_multipath_for_image_xfer = False
self.conf.enforce_multipath_for_image_xfer = False
def _setup_driver(self): def _setup_driver(self):
self.driver = (kaminario_iscsi. self.driver = (kaminario_iscsi.

View File

@ -813,7 +813,9 @@ class CommonAdapter(object):
is_compressed=vol_params.is_compressed) is_compressed=vol_params.is_compressed)
src_id = src_snap.get_id() src_id = src_snap.get_id()
try: try:
conn_props = volume_utils.brick_get_connector_properties() conn_props = volume_utils.brick_get_connector_properties(
self.config.use_multipath_for_image_xfer,
self.config.enforce_multipath_for_image_xfer)
with self._connect_resource(dest_lun, conn_props, with self._connect_resource(dest_lun, conn_props,
vol_params.volume_id) as dest_info, \ vol_params.volume_id) as dest_info, \

View File

@ -219,7 +219,9 @@ class FlashSystemDriver(san.SanDriver,
LOG.debug('enter: _copy_vdisk_data: %(src)s -> %(dest)s.', LOG.debug('enter: _copy_vdisk_data: %(src)s -> %(dest)s.',
{'src': src_vdisk_name, 'dest': dest_vdisk_name}) {'src': src_vdisk_name, 'dest': dest_vdisk_name})
connector = volume_utils.brick_get_connector_properties() connector = volume_utils.brick_get_connector_properties(
self.configuration.use_multipath_for_image_xfer,
self.configuration.enforce_multipath_for_image_xfer)
(src_map, src_lun_id) = self._is_vdisk_map( (src_map, src_lun_id) = self._is_vdisk_map(
src_vdisk_name, connector) src_vdisk_name, connector)
(dest_map, dest_lun_id) = self._is_vdisk_map( (dest_map, dest_lun_id) = self._is_vdisk_map(

View File

@ -553,7 +553,9 @@ class KaminarioCinderDriver(cinder.volume.driver.ISCSIDriver):
vol_name = self.get_volume_name(volume.id) vol_name = self.get_volume_name(volume.id)
cview = src_attach_info = dest_attach_info = None cview = src_attach_info = dest_attach_info = None
rpolicy = self.get_policy() rpolicy = self.get_policy()
properties = volume_utils.brick_get_connector_properties() properties = volume_utils.brick_get_connector_properties(
self.configuration.use_multipath_for_image_xfer,
self.configuration.enforce_multipath_for_image_xfer)
LOG.debug("Searching for snapshot: %s in K2.", snap_name) LOG.debug("Searching for snapshot: %s in K2.", snap_name)
snap_rs = self.client.search("snapshots", short_name=snap_name) snap_rs = self.client.search("snapshots", short_name=snap_name)
if hasattr(snap_rs, 'hits') and snap_rs.total != 0: if hasattr(snap_rs, 'hits') and snap_rs.total != 0:
@ -624,7 +626,9 @@ class KaminarioCinderDriver(cinder.volume.driver.ISCSIDriver):
LOG.error(msg) LOG.error(msg)
raise KaminarioCinderDriverException(reason=msg) raise KaminarioCinderDriverException(reason=msg)
try: try:
properties = volume_utils.brick_get_connector_properties() properties = volume_utils.brick_get_connector_properties(
self.configuration.use_multipath_for_image_xfer,
self.configuration.enforce_multipath_for_image_xfer)
conn = self.initialize_connection(src_vref, properties) conn = self.initialize_connection(src_vref, properties)
src_attach_info = self._connect_device(conn) src_attach_info = self._connect_device(conn)
self.create_volume(volume) self.create_volume(volume)

View File

@ -523,7 +523,14 @@ class CreateVolumeFromSpecTask(flow_utils.CinderTask):
LOG.debug('rekey volume %s', volume.name) LOG.debug('rekey volume %s', volume.name)
properties = volume_utils.brick_get_connector_properties(False, False) # Rekeying writes very little data (KB), so doing a single pathed
# connection is more efficient, but it is less robust, because the
# driver could be returning a single path, and it happens to be down
# then the attach would fail where the multipathed connection would
# have succeeded.
properties = volume_utils.brick_get_connector_properties(
self.driver.configuration.use_multipath_for_image_xfer,
self.driver.configuration.enforce_multipath_for_image_xfer)
LOG.debug("properties: %s", properties) LOG.debug("properties: %s", properties)
attach_info = None attach_info = None
model_update = {} model_update = {}

View File

@ -0,0 +1,14 @@
---
fixes:
- |
`Bug #1951982 <https://bugs.launchpad.net/cinder/+bug/1951982>`_: Fixed
cloning of encrypted volumes not using multipathing to change the
encryption key used on the new volume.
- |
`Bug #1951977 <https://bugs.launchpad.net/cinder/+bug/1951977>`_: Fixed
backup create and restore not using multipath configuration when attaching
the volume.
- |
Kaminario driver `bug #1951981
<https://bugs.launchpad.net/cinder/+bug/1951981>`_: Fixed
create volume from volume or snapshot not using multipath configuration.