Prevent removal of share server used by CG

Previously, it was possible to remove such a share
server, which would lead to exceptions when
attempting to remove the CG.

APIImpact
Change-Id: I6577eee837cb10119934108032e99835e63b7bd2
Closes-bug: 1501326
This commit is contained in:
John Spray 2015-09-30 13:55:55 +01:00
parent ab048dc85c
commit 2516733710
5 changed files with 57 additions and 0 deletions

View File

@ -908,6 +908,12 @@ def consistency_group_create(context, values):
return IMPL.consistency_group_create(context, values)
def consistency_group_get_all_by_share_server(context, share_server_id):
"""Get all consistency groups associated with a share server."""
return IMPL.consistency_group_get_all_by_share_server(context,
share_server_id)
def consistency_group_get_all_by_project(context, project_id, detailed=True):
"""Get all consistency groups belonging to a project."""
return IMPL.consistency_group_get_all_by_project(context, project_id,

View File

@ -3063,6 +3063,12 @@ def consistency_group_get_all_by_project(context, project_id, detailed=True):
return values
@require_context
def consistency_group_get_all_by_share_server(context, share_server_id):
return _consistency_group_get_all_query(context).filter_by(
share_server_id=share_server_id).all()
@require_context
def consistency_group_create(context, values):
consistency_group = models.ConsistencyGroup()

View File

@ -465,8 +465,17 @@ class API(base.Base):
policy.check_policy(context, 'share_server', 'delete', server)
shares = self.db.share_instances_get_all_by_share_server(context,
server['id'])
if shares:
raise exception.ShareServerInUse(share_server_id=server['id'])
cgs = self.db.consistency_group_get_all_by_share_server(context,
server['id'])
if cgs:
LOG.error(_LE("share server '%(ssid)s' in use by CGs"),
{'ssid': server['id']})
raise exception.ShareServerInUse(share_server_id=server['id'])
# NOTE(vponomaryov): There is no share_server status update here,
# it is intentional.
# Status will be changed in manila.share.manager after verification

View File

@ -324,6 +324,20 @@ class ConsistencyGroupDatabaseAPITestCase(test.TestCase):
self.assertEqual(expected_cg['id'], cg['id'])
self.assertEqual(expected_cg['name'], cg['name'])
def test_consistency_group_get_all_by_share_server(self):
fake_server = 123
expected_cg = db_utils.create_consistency_group(
share_server_id=fake_server)
db_utils.create_consistency_group()
cgs = db_api.consistency_group_get_all_by_share_server(self.ctxt,
fake_server)
self.assertEqual(1, len(cgs))
cg = cgs[0]
self.assertEqual(expected_cg['id'], cg['id'])
self.assertEqual(expected_cg['name'], cg['name'])
def test_consistency_group_get_all_by_project_with_details(self):
fake_project = 'fake_project'
expected_cg = db_utils.create_consistency_group(

View File

@ -875,6 +875,8 @@ class ShareAPITestCase(test.TestCase):
@mock.patch.object(db_api, 'share_instances_get_all_by_share_server',
mock.Mock(return_value=[]))
@mock.patch.object(db_api, 'consistency_group_get_all_by_share_server',
mock.Mock(return_value=[]))
def test_delete_share_server_no_dependent_shares(self):
server = {'id': 'fake_share_server_id'}
server_returned = {
@ -885,11 +887,15 @@ class ShareAPITestCase(test.TestCase):
self.api.delete_share_server(self.context, server)
db_api.share_instances_get_all_by_share_server.assert_called_once_with(
self.context, server['id'])
db_api.consistency_group_get_all_by_share_server.\
assert_called_once_with(self.context, server['id'])
self.share_rpcapi.delete_share_server.assert_called_once_with(
self.context, server_returned)
@mock.patch.object(db_api, 'share_instances_get_all_by_share_server',
mock.Mock(return_value=['fake_share', ]))
@mock.patch.object(db_api, 'consistency_group_get_all_by_share_server',
mock.Mock(return_value=[]))
def test_delete_share_server_dependent_share_exists(self):
server = {'id': 'fake_share_server_id'}
self.assertRaises(exception.ShareServerInUse,
@ -899,6 +905,22 @@ class ShareAPITestCase(test.TestCase):
db_api.share_instances_get_all_by_share_server.assert_called_once_with(
self.context, server['id'])
@mock.patch.object(db_api, 'share_instances_get_all_by_share_server',
mock.Mock(return_value=[]))
@mock.patch.object(db_api, 'consistency_group_get_all_by_share_server',
mock.Mock(return_value=['fake_cg', ]))
def test_delete_share_server_dependent_cg_exists(self):
server = {'id': 'fake_share_server_id'}
self.assertRaises(exception.ShareServerInUse,
self.api.delete_share_server,
self.context,
server)
db_api.share_instances_get_all_by_share_server.assert_called_once_with(
self.context, server['id'])
db_api.consistency_group_get_all_by_share_server.\
assert_called_once_with(self.context, server['id'])
@mock.patch.object(db_api, 'share_snapshot_update', mock.Mock())
def test_delete_snapshot(self):
snapshot = db_utils.create_snapshot(