Merge "Handling type's multiattach extra specs in API task flow"

This commit is contained in:
Zuul 2018-07-12 21:35:14 +00:00 committed by Gerrit Code Review
commit f106003f5e
4 changed files with 56 additions and 14 deletions

View File

@ -174,6 +174,9 @@ class CreateVolumeFlowTestCase(test.TestCase):
'ExtractVolumeRequestTask.'
'_get_encryption_key_id', mock.Mock())
@mock.patch('cinder.volume.volume_types.get_volume_type_qos_specs')
@mock.patch(
'cinder.objects.volume_type.VolumeType.get_by_name_or_id',
mock.Mock(return_value={}))
def test_extract_volume_request_replication_status(self,
replication_status,
extra_specs,
@ -211,6 +214,9 @@ class CreateVolumeFlowTestCase(test.TestCase):
'ExtractVolumeRequestTask.'
'_get_encryption_key_id')
@mock.patch('cinder.volume.volume_types.get_volume_type_qos_specs')
@mock.patch(
'cinder.objects.volume_type.VolumeType.get_by_name_or_id',
mock.Mock(return_value={}))
def test_extract_volume_request_from_image_encrypted(
self,
fake_get_qos,
@ -256,8 +262,10 @@ class CreateVolumeFlowTestCase(test.TestCase):
@mock.patch('cinder.volume.flows.api.create_volume.'
'ExtractVolumeRequestTask.'
'_get_volume_type_id')
@mock.patch('cinder.objects.volume_type.VolumeType.get_by_name_or_id')
def test_extract_volume_request_from_image(
self,
fake_get_type,
fake_get_type_id,
fake_get_qos,
fake_is_encrypted):
@ -271,6 +279,7 @@ class CreateVolumeFlowTestCase(test.TestCase):
fake_image_service.create(self.ctxt, image_meta)
fake_key_manager = mock_key_manager.MockKeyManager()
volume_type = {'name': 'type1'}
fake_get_type.return_value = volume_type
task = create_volume.ExtractVolumeRequestTask(
fake_image_service,
@ -306,7 +315,8 @@ class CreateVolumeFlowTestCase(test.TestCase):
'group_id': None,
'refresh_az': False,
'replication_status': 'disabled',
'backup_id': None}
'backup_id': None,
'multiattach': False}
self.assertEqual(expected_result, result)
@mock.patch('cinder.volume.volume_types.is_encrypted')
@ -468,8 +478,10 @@ class CreateVolumeFlowTestCase(test.TestCase):
@mock.patch('cinder.volume.flows.api.create_volume.'
'ExtractVolumeRequestTask.'
'_get_volume_type_id')
@mock.patch('cinder.objects.volume_type.VolumeType.get_by_name_or_id')
def test_extract_availability_zones_with_fallback(
self,
fake_get_type,
fake_get_type_id,
fake_get_qos,
fake_is_encrypted):
@ -485,6 +497,7 @@ class CreateVolumeFlowTestCase(test.TestCase):
fake_image_service.create(self.ctxt, image_meta)
fake_key_manager = mock_key_manager.MockKeyManager()
volume_type = {'name': 'type1'}
fake_get_type.return_value = volume_type
task = create_volume.ExtractVolumeRequestTask(
fake_image_service,
@ -519,6 +532,7 @@ class CreateVolumeFlowTestCase(test.TestCase):
'cgsnapshot_id': None,
'group_id': None,
'refresh_az': True,
'multiattach': False,
'replication_status': 'disabled',
'backup_id': None}
self.assertEqual(expected_result, result)
@ -582,8 +596,10 @@ class CreateVolumeFlowTestCase(test.TestCase):
@mock.patch('cinder.volume.flows.api.create_volume.'
'ExtractVolumeRequestTask.'
'_get_volume_type_id')
@mock.patch('cinder.objects.volume_type.VolumeType.get_by_name_or_id')
def test_extract_volume_request_task_with_large_volume_size(
self,
fake_get_type,
fake_get_type_id,
fake_get_qos,
fake_is_encrypted):
@ -596,6 +612,7 @@ class CreateVolumeFlowTestCase(test.TestCase):
fake_image_service.create(self.ctxt, image_meta)
fake_key_manager = mock_key_manager.MockKeyManager()
volume_type = {'name': 'type1'}
fake_get_type.return_value = volume_type
task = create_volume.ExtractVolumeRequestTask(
fake_image_service,
@ -631,6 +648,7 @@ class CreateVolumeFlowTestCase(test.TestCase):
'cgsnapshot_id': None,
'refresh_az': False,
'group_id': None,
'multiattach': False,
'backup_id': None}
self.assertEqual(expected_result, result)
@ -639,8 +657,10 @@ class CreateVolumeFlowTestCase(test.TestCase):
@mock.patch('cinder.volume.flows.api.create_volume.'
'ExtractVolumeRequestTask.'
'_get_volume_type_id')
@mock.patch('cinder.objects.volume_type.VolumeType.get_by_name_or_id')
def test_extract_volume_request_from_image_with_qos_specs(
self,
fake_get_type,
fake_get_type_id,
fake_get_qos,
fake_is_encrypted):
@ -653,7 +673,8 @@ class CreateVolumeFlowTestCase(test.TestCase):
image_meta['size'] = 1
fake_image_service.create(self.ctxt, image_meta)
fake_key_manager = mock_key_manager.MockKeyManager()
volume_type = {'name': 'type1'}
volume_type = {'name': 'type1', 'id': 1}
fake_get_type.return_value = volume_type
task = create_volume.ExtractVolumeRequestTask(
fake_image_service,
@ -689,6 +710,7 @@ class CreateVolumeFlowTestCase(test.TestCase):
'cgsnapshot_id': None,
'group_id': None,
'refresh_az': False,
'multiattach': False,
'replication_status': 'disabled',
'backup_id': None}
self.assertEqual(expected_result, result)
@ -700,8 +722,10 @@ class CreateVolumeFlowTestCase(test.TestCase):
@mock.patch('cinder.volume.flows.api.create_volume.'
'ExtractVolumeRequestTask.'
'_get_volume_type_id')
@mock.patch('cinder.objects.volume_type.VolumeType.get_by_name_or_id')
def test_extract_image_volume_type_from_image(
self,
fake_get_type,
fake_get_type_id,
fake_get_vol_type,
fake_get_def_vol_type,
@ -709,6 +733,7 @@ class CreateVolumeFlowTestCase(test.TestCase):
fake_is_encrypted):
image_volume_type = {'name': 'type_from_image'}
fake_get_type.return_value = image_volume_type
fake_image_service = fake_image.FakeImageService()
image_id = 6
image_meta = {}
@ -755,6 +780,7 @@ class CreateVolumeFlowTestCase(test.TestCase):
'cgsnapshot_id': None,
'group_id': None,
'refresh_az': False,
'multiattach': False,
'replication_status': 'disabled',
'backup_id': None}
self.assertEqual(expected_result, result)
@ -766,8 +792,10 @@ class CreateVolumeFlowTestCase(test.TestCase):
@mock.patch('cinder.volume.flows.api.create_volume.'
'ExtractVolumeRequestTask.'
'_get_volume_type_id')
@mock.patch('cinder.objects.volume_type.VolumeType.get_by_name_or_id')
def test_extract_image_volume_type_from_image_invalid_type(
self,
fake_get_type,
fake_get_type_id,
fake_get_def_vol_type,
fake_get_qos,
@ -793,6 +821,7 @@ class CreateVolumeFlowTestCase(test.TestCase):
fake_is_encrypted.return_value = False
fake_get_type_id.return_value = 1
fake_get_def_vol_type.return_value = {'name': 'fake_vol_type'}
fake_get_type.return_value = {'name': 'fake_vol_type'}
fake_db_get_vol_type.side_effect = (
exception.VolumeTypeNotFoundByName(volume_type_name='invalid'))
fake_get_qos.return_value = {'qos_specs': None}
@ -821,6 +850,7 @@ class CreateVolumeFlowTestCase(test.TestCase):
'consistencygroup_id': None,
'cgsnapshot_id': None,
'group_id': None,
'multiattach': False,
'refresh_az': False,
'replication_status': 'disabled',
'backup_id': None}
@ -835,10 +865,12 @@ class CreateVolumeFlowTestCase(test.TestCase):
'_get_volume_type_id')
@ddt.data((8, None), (9, {'cinder_img_volume_type': None}))
@ddt.unpack
@mock.patch('cinder.objects.volume_type.VolumeType.get_by_name_or_id')
def test_extract_image_volume_type_from_image_properties_error(
self,
image_id,
fake_img_properties,
fake_get_type,
fake_get_type_id,
fake_get_def_vol_type,
fake_get_qos,
@ -861,6 +893,7 @@ class CreateVolumeFlowTestCase(test.TestCase):
fake_is_encrypted.return_value = False
fake_get_type_id.return_value = 1
fake_get_def_vol_type.return_value = {'name': 'fake_vol_type'}
fake_get_type.return_value = {'name': 'fake_vol_type'}
fake_get_qos.return_value = {'qos_specs': None}
result = task.execute(self.ctxt,
size=1,
@ -888,6 +921,7 @@ class CreateVolumeFlowTestCase(test.TestCase):
'cgsnapshot_id': None,
'group_id': None,
'refresh_az': False,
'multiattach': False,
'replication_status': 'disabled',
'backup_id': None}
self.assertEqual(expected_result, result)

View File

@ -116,7 +116,6 @@ class VolumeRetypeTestCase(base.BaseVolumeTestCase):
mock.call(volume_policies.MULTIATTACH_POLICY,
target_obj=mock.ANY),
mock.call(volume_policies.CREATE_POLICY),
mock.call(volume_policies.MULTIATTACH_POLICY),
mock.call(volume_policies.CREATE_POLICY),
mock.call(vol_action_policies.RETYPE_POLICY, target_obj=mock.ANY),
mock.call(vol_action_policies.RETYPE_POLICY, target_obj=mock.ANY),

View File

@ -289,9 +289,6 @@ class API(base.Base):
utils.check_metadata_properties(metadata)
if (volume_type and self._is_multiattach(volume_type)) or multiattach:
context.authorize(vol_policy.MULTIATTACH_POLICY)
create_what = {
'context': context,
'raw_size': size,
@ -308,7 +305,7 @@ class API(base.Base):
'optional_args': {'is_quota_committed': False},
'consistencygroup': consistencygroup,
'cgsnapshot': cgsnapshot,
'multiattach': multiattach,
'raw_multiattach': multiattach,
'group': group,
'group_snapshot': group_snapshot,
'source_group': source_group,
@ -349,8 +346,6 @@ class API(base.Base):
# Refresh the object here, otherwise things ain't right
vref = objects.Volume.get_by_id(
context, vref['id'])
vref.multiattach = (self._is_multiattach(volume_type) or
multiattach)
vref.save()
LOG.info("Create volume request issued successfully.",
resource=vref)

View File

@ -69,7 +69,8 @@ class ExtractVolumeRequestTask(flow_utils.CinderTask):
'source_volid', 'volume_type', 'volume_type_id',
'encryption_key_id', 'consistencygroup_id',
'cgsnapshot_id', 'qos_specs', 'group_id',
'refresh_az', 'backup_id', 'availability_zones'])
'refresh_az', 'backup_id', 'availability_zones',
'multiattach'])
def __init__(self, image_service, availability_zones, **kwargs):
super(ExtractVolumeRequestTask, self).__init__(addons=[ACTION],
@ -430,7 +431,8 @@ class ExtractVolumeRequestTask(flow_utils.CinderTask):
def execute(self, context, size, snapshot, image_id, source_volume,
availability_zone, volume_type, metadata, key_manager,
consistencygroup, cgsnapshot, group, group_snapshot, backup):
consistencygroup, cgsnapshot, group, group_snapshot, backup,
multiattach=False):
utils.check_exclusive_options(snapshot=snapshot,
imageRef=image_id,
@ -478,12 +480,22 @@ class ExtractVolumeRequestTask(flow_utils.CinderTask):
source_volume,
image_meta)
if encryption_key_id is not None and volume_type is not None:
if volume_type_id:
volume_type = objects.VolumeType.get_by_name_or_id(
context, volume_type_id)
extra_specs = volume_type.get('extra_specs', {})
if extra_specs.get('multiattach', '') == '<is> True':
# NOTE(tommylikehu): Although the parameter `multiattach` from
# create volume API is deprecated now, we still need to consider
# it when multiattach is not enabled in volume type.
multiattach = (extra_specs.get(
'multiattach', '') == '<is> True' or multiattach)
if multiattach and encryption_key_id:
msg = _('Multiattach cannot be used with encrypted volumes.')
raise exception.InvalidVolume(reason=msg)
if multiattach:
context.authorize(policy.MULTIATTACH_POLICY)
specs = {}
if volume_type_id:
qos_specs = volume_types.get_volume_type_qos_specs(volume_type_id)
@ -517,6 +529,7 @@ class ExtractVolumeRequestTask(flow_utils.CinderTask):
'replication_status': replication_status,
'refresh_az': refresh_az,
'backup_id': backup_id,
'multiattach': multiattach,
'availability_zones': availability_zones
}
@ -858,7 +871,8 @@ def get_flow(db_api, image_service_api, availability_zones, create_what,
availability_zones,
rebind={'size': 'raw_size',
'availability_zone': 'raw_availability_zone',
'volume_type': 'raw_volume_type'}))
'volume_type': 'raw_volume_type',
'multiattach': 'raw_multiattach'}))
api_flow.add(QuotaReserveTask(),
EntryCreateTask(),
QuotaCommitTask())