Merge "Add 'enforce_multipath' in connection_properties"

This commit is contained in:
Zuul 2024-12-13 01:19:12 +00:00 committed by Gerrit Code Review
commit c8ceeeb150
6 changed files with 72 additions and 7 deletions

View File

@ -172,6 +172,7 @@ class VolumeActionsController(wsgi.Controller):
if error.exc_type == 'InvalidInput': if error.exc_type == 'InvalidInput':
raise exception.InvalidInput(reason=error.value) raise exception.InvalidInput(reason=error.value)
raise raise
info['enforce_multipath'] = connector.get('enforce_multipath', False)
return {'connection_info': info} return {'connection_info': info}

View File

@ -97,12 +97,14 @@ class VolumeActionsTest(test.TestCase):
res = req.get_response(app) res = req.get_response(app)
self.assertEqual(HTTPStatus.ACCEPTED, res.status_int) self.assertEqual(HTTPStatus.ACCEPTED, res.status_int)
def test_initialize_connection(self): @ddt.data(False, True)
def test_initialize_connection(self, enforce_mpath):
with mock.patch.object(volume_api.API, with mock.patch.object(volume_api.API,
'initialize_connection') as init_conn: 'initialize_connection') as init_conn:
init_conn.return_value = {} init_conn.return_value = {}
body = {'os-initialize_connection': {'connector': { body = {'os-initialize_connection': {'connector': {
'fake': 'fake'}}} 'fake': 'fake', 'enforce_multipath': enforce_mpath}}}
expected_conn_info = {'enforce_multipath': enforce_mpath}
req = webob.Request.blank('/v3/%s/volumes/%s/action' % req = webob.Request.blank('/v3/%s/volumes/%s/action' %
(fake.PROJECT_ID, fake.VOLUME_ID)) (fake.PROJECT_ID, fake.VOLUME_ID))
req.method = "POST" req.method = "POST"
@ -111,7 +113,9 @@ class VolumeActionsTest(test.TestCase):
res = req.get_response(fakes.wsgi_app( res = req.get_response(fakes.wsgi_app(
fake_auth_context=self.context)) fake_auth_context=self.context))
actual_conn_info = jsonutils.loads(res.body).get('connection_info')
self.assertEqual(HTTPStatus.OK, res.status_int) self.assertEqual(HTTPStatus.OK, res.status_int)
self.assertEqual(expected_conn_info, actual_conn_info)
def test_initialize_connection_without_connector(self): def test_initialize_connection_without_connector(self):
with mock.patch.object(volume_api.API, with mock.patch.object(volume_api.API,

View File

@ -12,6 +12,7 @@
from unittest import mock from unittest import mock
import ddt
from oslo_config import cfg from oslo_config import cfg
from oslo_utils import importutils from oslo_utils import importutils
@ -28,6 +29,7 @@ from cinder.volume import configuration as conf
CONF = cfg.CONF CONF = cfg.CONF
@ddt.ddt
class AttachmentManagerTestCase(test.TestCase): class AttachmentManagerTestCase(test.TestCase):
"""Attachment related test for volume.manager.py.""" """Attachment related test for volume.manager.py."""
@ -46,11 +48,13 @@ class AttachmentManagerTestCase(test.TestCase):
self.manager.stats = {'allocated_capacity_gb': 100, self.manager.stats = {'allocated_capacity_gb': 100,
'pools': {}} 'pools': {}}
@ddt.data(False, True)
@mock.patch.object(db.sqlalchemy.api, '_volume_type_get', @mock.patch.object(db.sqlalchemy.api, '_volume_type_get',
v2_fakes.fake_volume_type_get) v2_fakes.fake_volume_type_get)
@mock.patch('cinder.db.sqlalchemy.api.volume_type_qos_specs_get') @mock.patch('cinder.db.sqlalchemy.api.volume_type_qos_specs_get')
@mock.patch('cinder.volume.volume_types.get_volume_type_extra_specs') @mock.patch('cinder.volume.volume_types.get_volume_type_extra_specs')
def test_attachment_update(self, get_extra_specs, mock_type_get): def test_attachment_update(self, enforce_mpath, get_extra_specs,
mock_type_get):
"""Test attachment_update.""" """Test attachment_update."""
volume_params = {'status': 'available'} volume_params = {'status': 'available'}
connector = { connector = {
@ -59,7 +63,8 @@ class AttachmentManagerTestCase(test.TestCase):
"platform": "x86_64", "platform": "x86_64",
"host": "tempest-1", "host": "tempest-1",
"os_type": "linux2", "os_type": "linux2",
"multipath": False} "multipath": False,
"enforce_multipath": enforce_mpath}
vref = tests_utils.create_volume(self.context, **volume_params) vref = tests_utils.create_volume(self.context, **volume_params)
self.manager.create_volume(self.context, vref) self.manager.create_volume(self.context, vref)
@ -77,7 +82,8 @@ class AttachmentManagerTestCase(test.TestCase):
'cacheable': False, 'cacheable': False,
'access_mode': 'rw', 'access_mode': 'rw',
'driver_volume_type': 'iscsi', 'driver_volume_type': 'iscsi',
'attachment_id': attachment_ref.id} 'attachment_id': attachment_ref.id,
'enforce_multipath': enforce_mpath}
get_extra_specs.return_value = {} get_extra_specs.return_value = {}
self.assertEqual(expected, self.assertEqual(expected,
@ -92,7 +98,8 @@ class AttachmentManagerTestCase(test.TestCase):
'cacheable': True, 'cacheable': True,
'access_mode': 'rw', 'access_mode': 'rw',
'driver_volume_type': 'iscsi', 'driver_volume_type': 'iscsi',
'attachment_id': attachment_ref.id} 'attachment_id': attachment_ref.id,
'enforce_multipath': enforce_mpath}
get_extra_specs.return_value = {'cacheable': '<is> True'} get_extra_specs.return_value = {'cacheable': '<is> True'}
self.assertEqual(expected, self.assertEqual(expected,

View File

@ -383,6 +383,47 @@ class GenericVolumeDriverTestCase(BaseDriverTestCase):
db.volume_destroy(self.context, src_vol['id']) db.volume_destroy(self.context, src_vol['id'])
db.volume_destroy(self.context, dest_vol['id']) db.volume_destroy(self.context, dest_vol['id'])
@ddt.data(False, True)
@mock.patch(driver_name + '.initialize_connection')
@mock.patch(driver_name + '.create_export', return_value=None)
@mock.patch(driver_name + '._connect_device')
def test_attach_volume_enforce_mpath(self, enforce_mpath, connect_mock,
export_mock, initialize_mock):
properties = {'host': 'myhost', 'ip': '192.168.1.43',
'initiator': u'iqn.1994-05.com.redhat:d9be887375',
'multipath': False, 'os_type': 'linux2',
'platform': 'x86_64',
'enforce_multipath': enforce_mpath}
data = {'target_discovered': True,
'target_iqn': 'iqn.2010-10.org.openstack:volume-00000001',
'target_portal': '127.0.0.0.1:3260',
'volume_id': 1,
'discard': False,
'encrypted': False,
'enforce_multipath': enforce_mpath}
passed_conn = {'driver_volume_type': 'iscsi', 'data': data.copy()}
initialize_mock.return_value = passed_conn
expected_conn = {'driver_volume_type': 'iscsi', 'data': data.copy()}
volume = tests_utils.create_volume(
self.context, status='available',
size=2)
attach_info, vol = self.volume.driver._attach_volume(self.context,
volume,
properties)
export_mock.assert_called_once_with(self.context, volume, properties)
initialize_mock.assert_called_once_with(volume, properties)
connect_mock.assert_called_once_with(expected_conn)
self.assertEqual(connect_mock.return_value, attach_info)
self.assertEqual(volume, vol)
@mock.patch(driver_name + '.initialize_connection') @mock.patch(driver_name + '.initialize_connection')
@mock.patch(driver_name + '.create_export', return_value=None) @mock.patch(driver_name + '.create_export', return_value=None)
@mock.patch(driver_name + '._connect_device') @mock.patch(driver_name + '._connect_device')
@ -397,7 +438,8 @@ class GenericVolumeDriverTestCase(BaseDriverTestCase):
'target_iqn': 'iqn.2010-10.org.openstack:volume-00000001', 'target_iqn': 'iqn.2010-10.org.openstack:volume-00000001',
'target_portal': '127.0.0.0.1:3260', 'target_portal': '127.0.0.0.1:3260',
'volume_id': 1, 'volume_id': 1,
'discard': False} 'discard': False,
'enforce_multipath': False}
passed_conn = {'driver_volume_type': 'iscsi', 'data': data.copy()} passed_conn = {'driver_volume_type': 'iscsi', 'data': data.copy()}
initialize_mock.return_value = passed_conn initialize_mock.return_value = passed_conn

View File

@ -1087,6 +1087,10 @@ class BaseVD(object, metaclass=abc.ABCMeta):
encrypted = bool(volume.encryption_key_id) encrypted = bool(volume.encryption_key_id)
conn['data']['encrypted'] = encrypted conn['data']['encrypted'] = encrypted
# Append the enforce_multipath value if the connector has it
conn['data']['enforce_multipath'] = properties.get(
'enforce_multipath', False)
try: try:
attach_info = self._connect_device(conn) attach_info = self._connect_device(conn)
except Exception as exc: except Exception as exc:

View File

@ -1980,6 +1980,8 @@ class VolumeManager(manager.CleanableManager,
raise exception.VolumeBackendAPIException(data=err_msg) raise exception.VolumeBackendAPIException(data=err_msg)
conn_info = self._parse_connection_options(context, volume, conn_info) conn_info = self._parse_connection_options(context, volume, conn_info)
conn_info['data']['enforce_multipath'] = connector.get(
'enforce_multipath', False)
LOG.info("Initialize volume connection completed successfully.", LOG.info("Initialize volume connection completed successfully.",
resource=volume) resource=volume)
return conn_info return conn_info
@ -2040,6 +2042,8 @@ class VolumeManager(manager.CleanableManager,
LOG.error(ex_msg) LOG.error(ex_msg)
raise exception.VolumeBackendAPIException(data=ex_msg) raise exception.VolumeBackendAPIException(data=ex_msg)
raise exception.VolumeBackendAPIException(data=err_msg) raise exception.VolumeBackendAPIException(data=err_msg)
conn['data']['enforce_multipath'] = connector.get(
'enforce_multipath', False)
LOG.info("Initialize snapshot connection completed successfully.", LOG.info("Initialize snapshot connection completed successfully.",
resource=snapshot) resource=snapshot)
@ -4851,6 +4855,9 @@ class VolumeManager(manager.CleanableManager,
self.db.volume_attachment_update(ctxt, attachment.id, values) self.db.volume_attachment_update(ctxt, attachment.id, values)
connection_info['attachment_id'] = attachment.id connection_info['attachment_id'] = attachment.id
# Append the enforce_multipath value if the connector has it
connection_info['enforce_multipath'] = connector.get(
'enforce_multipath', False)
LOG.debug("Connection info returned from driver %(connection_info)s", LOG.debug("Connection info returned from driver %(connection_info)s",
{'connection_info': {'connection_info':
strutils.mask_dict_password(connection_info)}) strutils.mask_dict_password(connection_info)})