Merge "Prevent share type deletion if linked to group types" into stable/rocky

This commit is contained in:
Zuul 2020-04-30 22:27:48 +00:00 committed by Gerrit Code Review
commit cef5e7b034
4 changed files with 88 additions and 22 deletions

View File

@ -3975,18 +3975,25 @@ def share_type_destroy(context, id):
session = get_session() session = get_session()
with session.begin(): with session.begin():
_share_type_get(context, id, session) _share_type_get(context, id, session)
results = (model_query(context, models.ShareInstance, session=session, shares_count = model_query(
read_deleted="no").
filter_by(share_type_id=id).count())
share_group_count = model_query(
context, context,
models.ShareGroupShareTypeMapping, models.ShareInstance,
read_deleted="no", read_deleted="no",
session=session, session=session,
).filter_by(share_type_id=id).count() ).filter_by(share_type_id=id).count()
if results or share_group_count: share_group_types_count = model_query(
LOG.error('ShareType %s deletion failed, ShareType in use.', context,
id) models.ShareGroupTypeShareTypeMapping,
read_deleted="no",
session=session,
).filter_by(share_type_id=id).count()
if shares_count or share_group_types_count:
msg = ("Deletion of share type %(stype)s failed; it in use by "
"%(shares)d shares and %(gtypes)d share group types")
msg_args = {'stype': id,
'shares': shares_count,
'gtypes': share_group_types_count}
LOG.error(msg, msg_args)
raise exception.ShareTypeInUse(share_type_id=id) raise exception.ShareTypeInUse(share_type_id=id)
(model_query(context, models.ShareTypeExtraSpecs, session=session). (model_query(context, models.ShareTypeExtraSpecs, session=session).
filter_by(share_type_id=id).soft_delete()) filter_by(share_type_id=id).soft_delete())
@ -4847,6 +4854,11 @@ def share_group_type_destroy(context, type_id):
).filter_by( ).filter_by(
share_group_type_id=type_id, share_group_type_id=type_id,
).soft_delete() ).soft_delete()
model_query(
context, models.ShareGroupTypeShareTypeMapping, session=session
).filter_by(
share_group_type_id=type_id,
).soft_delete()
model_query( model_query(
context, models.ShareGroupTypes, session=session context, models.ShareGroupTypes, session=session
).filter_by( ).filter_by(

View File

@ -632,8 +632,8 @@ class ShareGroupTypeSpecsNotFound(NotFound):
class ShareTypeInUse(ManilaException): class ShareTypeInUse(ManilaException):
message = _("Share Type %(share_type_id)s deletion is not allowed with " message = _("Share Type %(share_type_id)s deletion is not allowed while "
"shares present with the type.") "shares or share group types are associated with the type.")
class IPAddressInUse(InUse): class IPAddressInUse(InUse):

View File

@ -1194,6 +1194,57 @@ class ShareGroupDatabaseAPITestCase(test.TestCase):
self.assertEqual(constants.STATUS_AVAILABLE, member['status']) self.assertEqual(constants.STATUS_AVAILABLE, member['status'])
@ddt.ddt
class ShareGroupTypeAPITestCase(test.TestCase):
def setUp(self):
super(ShareGroupTypeAPITestCase, self).setUp()
self.ctxt = context.RequestContext(
user_id='user_id', project_id='project_id', is_admin=True)
@ddt.data(True, False)
def test_share_type_destroy_in_use(self, used_by_groups):
share_type_1 = db_utils.create_share_type(name='fike')
share_type_2 = db_utils.create_share_type(name='bowman')
share_group_type_1 = db_utils.create_share_group_type(
name='orange', is_public=False, share_types=[share_type_1['id']],
group_specs={'dabo': 'allin', 'cadence': 'count'},
override_defaults=True)
share_group_type_2 = db_utils.create_share_group_type(
name='regalia', share_types=[share_type_2['id']])
if used_by_groups:
share_group_1 = db_utils.create_share_group(
share_group_type_id=share_group_type_1['id'],
share_types=[share_type_1['id']])
share_group_2 = db_utils.create_share_group(
share_group_type_id=share_group_type_2['id'],
share_types=[share_type_2['id']])
self.assertRaises(exception.ShareGroupTypeInUse,
db_api.share_group_type_destroy,
self.ctxt, share_group_type_1['id'])
self.assertRaises(exception.ShareGroupTypeInUse,
db_api.share_group_type_destroy,
self.ctxt, share_group_type_2['id'])
# Cleanup share groups
db_api.share_group_destroy(self.ctxt, share_group_1['id'])
db_api.share_group_destroy(self.ctxt, share_group_2['id'])
# Let's cleanup share_group_type_1 and verify it is gone
self.assertIsNone(db_api.share_group_type_destroy(
self.ctxt, share_group_type_1['id']))
self.assertDictMatch(
{}, db_api.share_group_type_specs_get(
self.ctxt, share_group_type_1['id']))
self.assertRaises(exception.ShareGroupTypeNotFound,
db_api.share_group_type_get,
self.ctxt, share_group_type_1['id'])
# share_group_type_2 must still be around
self.assertEqual(share_group_type_2['id'],
db_api.share_group_type_get(
self.ctxt, share_group_type_2['id'])['id'])
@ddt.ddt @ddt.ddt
class ShareSnapshotDatabaseAPITestCase(test.TestCase): class ShareSnapshotDatabaseAPITestCase(test.TestCase):
@ -2994,29 +3045,26 @@ class ShareTypeAPITestCase(test.TestCase):
self.ctxt = context.RequestContext( self.ctxt = context.RequestContext(
user_id='user_id', project_id='project_id', is_admin=True) user_id='user_id', project_id='project_id', is_admin=True)
@ddt.data({'used_by_shares': True, 'used_by_groups': False}, @ddt.data({'used_by_shares': True, 'used_by_group_types': False},
{'used_by_shares': False, 'used_by_groups': True}, {'used_by_shares': False, 'used_by_group_types': True},
{'used_by_shares': True, 'used_by_groups': True}) {'used_by_shares': True, 'used_by_group_types': True})
@ddt.unpack @ddt.unpack
def test_share_type_destroy_in_use(self, used_by_shares, def test_share_type_destroy_in_use(self, used_by_shares,
used_by_groups): used_by_group_types):
share_type_1 = db_utils.create_share_type( share_type_1 = db_utils.create_share_type(
name='orange', extra_specs={'somekey': 'someval'}) name='orange', extra_specs={'somekey': 'someval'})
share_type_2 = db_utils.create_share_type(name='regalia') share_type_2 = db_utils.create_share_type(name='regalia')
if used_by_shares: if used_by_shares:
share_1 = db_utils.create_share(share_type_id=share_type_1['id']) share_1 = db_utils.create_share(share_type_id=share_type_1['id'])
db_utils.create_share(share_type_id=share_type_2['id']) db_utils.create_share(share_type_id=share_type_2['id'])
if used_by_groups: if used_by_group_types:
group_type_1 = db_utils.create_share_group_type( group_type_1 = db_utils.create_share_group_type(
name='crimson', share_types=[share_type_1['id']]) name='crimson', share_types=[share_type_1['id']])
group_type_2 = db_utils.create_share_group_type( db_utils.create_share_group_type(
name='tide', share_types=[share_type_2['id']]) name='tide', share_types=[share_type_2['id']])
share_group_1 = db_utils.create_share_group( share_group_1 = db_utils.create_share_group(
share_group_type_id=group_type_1['id'], share_group_type_id=group_type_1['id'],
share_types=[share_type_1['id']]) share_types=[share_type_1['id']])
db_utils.create_share_group(
share_group_type_id=group_type_2['id'],
share_types=[share_type_2['id']])
self.assertRaises(exception.ShareTypeInUse, self.assertRaises(exception.ShareTypeInUse,
db_api.share_type_destroy, db_api.share_type_destroy,
@ -3028,13 +3076,13 @@ class ShareTypeAPITestCase(test.TestCase):
# Let's cleanup share_type_1 and verify it is gone # Let's cleanup share_type_1 and verify it is gone
if used_by_shares: if used_by_shares:
db_api.share_instance_delete(self.ctxt, share_1.instance.id) db_api.share_instance_delete(self.ctxt, share_1.instance.id)
if used_by_groups: if used_by_group_types:
db_api.share_group_destroy(self.ctxt, share_group_1['id']) db_api.share_group_destroy(self.ctxt, share_group_1['id'])
db_api.share_group_type_destroy(self.ctxt, db_api.share_group_type_destroy(self.ctxt,
group_type_1['id']) group_type_1['id'])
self.assertIsNone(db_api.share_type_destroy( self.assertIsNone(
self.ctxt, share_type_1['id'])) db_api.share_type_destroy(self.ctxt, share_type_1['id']))
self.assertDictMatch( self.assertDictMatch(
{}, db_api.share_type_extra_specs_get( {}, db_api.share_type_extra_specs_get(
self.ctxt, share_type_1['id'])) self.ctxt, share_type_1['id']))

View File

@ -0,0 +1,6 @@
---
fixes:
- |
Fixed `Launchpad bug 1699836 <https://launchpad.net/bugs/1699836>`_ by
preventing share type deletion when there are share group types
associated with them.