Destroy the related resources when delete a bay

Currently, when we delete a bay, we will delete the stack firstly,
then try to detroy the bay record in db. And at this time, a
BayNotEmpty exception may raised if some of pods, services or rc
are related to this bay. In the meanwhile, the stack should be already
deleted, actually, the left bay record is unavailable.

This patch destroy the related resources when delete a bay.

Change-Id: I56cd8813417bd4a6f6c340deb8afd88d5516f225
Closes-bug: #1440630
This commit is contained in:
lqslan 2015-04-06 10:33:59 +08:00
parent cffdd37052
commit dbb3769fa3
5 changed files with 41 additions and 39 deletions

View File

@ -376,10 +376,6 @@ class BayAlreadyExists(Conflict):
message = _("A node with UUID %(uuid)s already exists.")
class BayNotEmpty(Invalid):
message = _("Bay %(bay)s is not empty.")
class ContainerNotFound(ResourceNotFound):
message = _("Container %(container)s could not be found.")

View File

@ -189,21 +189,22 @@ class Connection(api.Connection):
raise exception.BayNotFound(bay=bay_uuid)
def destroy_bay(self, bay_id):
def bay_not_empty(session, bay_uuid):
def destroy_bay_resources(session, bay_uuid):
"""Checks whether the bay does not have resources."""
query = model_query(models.Pod, session=session)
query = self._add_pods_filters(query, {'bay_uuid': bay_uuid})
if query.count() != 0:
return True
query.delete()
query = model_query(models.Service, session=session)
query = self._add_services_filters(query, {'bay_uuid': bay_uuid})
if query.count() != 0:
return True
query.delete()
query = model_query(models.ReplicationController, session=session)
query = self._add_rcs_filters(query, {'bay_uuid': bay_uuid})
return query.count() != 0
if query.count() != 0:
query.delete()
session = get_session()
with session.begin():
@ -215,13 +216,7 @@ class Connection(api.Connection):
except NoResultFound:
raise exception.BayNotFound(bay=bay_id)
# TODO(hongbin): delete pods and services that attached to the bay.
# We don't do it now because it could cause a long deletion
# time which would block the conductor. It needs either threads
# or coroutines.
if bay_not_empty(session, bay_ref['uuid']):
raise exception.BayNotEmpty(bay=bay_id)
destroy_bay_resources(session, bay_ref['uuid'])
query.delete()
def update_bay(self, bay_id, values):

View File

@ -440,28 +440,19 @@ class TestDelete(api_base.FunctionalTest):
obj_utils.create_test_pod(self.context, bay_uuid=self.bay.uuid)
response = self.delete('/bays/%s' % self.bay.uuid,
expect_errors=True)
self.assertEqual(400, response.status_int)
self.assertEqual('application/json', response.content_type)
self.assertTrue(response.json['error_message'])
self.assertIn(self.bay.uuid, response.json['error_message'])
self.assertEqual(204, response.status_int)
def test_delete_bay_with_services(self):
obj_utils.create_test_service(self.context, bay_uuid=self.bay.uuid)
response = self.delete('/bays/%s' % self.bay.uuid,
expect_errors=True)
self.assertEqual(400, response.status_int)
self.assertEqual('application/json', response.content_type)
self.assertTrue(response.json['error_message'])
self.assertIn(self.bay.uuid, response.json['error_message'])
self.assertEqual(204, response.status_int)
def test_delete_bay_with_replication_controllers(self):
obj_utils.create_test_rc(self.context, bay_uuid=self.bay.uuid)
response = self.delete('/bays/%s' % self.bay.uuid,
expect_errors=True)
self.assertEqual(400, response.status_int)
self.assertEqual('application/json', response.content_type)
self.assertTrue(response.json['error_message'])
self.assertIn(self.bay.uuid, response.json['error_message'])
self.assertEqual(204, response.status_int)
def test_delete_bay_with_name_not_found(self):
response = self.delete('/bays/not_found', expect_errors=True)

View File

@ -143,10 +143,6 @@ class TestException(base.BaseTestCase):
self.assertRaises(exception.BayAlreadyExists,
lambda: self.raise_(exception.BayAlreadyExists()))
def test_BayNotEmpty(self):
self.assertRaises(exception.BayNotEmpty,
lambda: self.raise_(exception.BayNotEmpty()))
def test_BayModelNotFound(self):
self.assertRaises(exception.BayModelNotFound,
lambda: self.raise_(exception.BayModelNotFound()))

View File

@ -144,29 +144,53 @@ class DbBayTestCase(base.DbTestCase):
bay = utils.create_test_bay()
pod = utils.create_test_pod(bay_uuid=bay.uuid)
self.assertEqual(bay.uuid, pod.bay_uuid)
self.assertRaises(exception.BayNotEmpty,
self.dbapi.destroy_bay, bay.id)
self.dbapi.destroy_bay(bay.id)
self.assertRaises(exception.PodNotFound,
self.dbapi.get_pod_by_id, self.context, pod.id)
def test_destroy_bay_that_has_pods_by_uuid(self):
bay = utils.create_test_bay()
pod = utils.create_test_pod(bay_uuid=bay.uuid)
self.assertEqual(bay.uuid, pod.bay_uuid)
self.assertRaises(exception.BayNotEmpty,
self.dbapi.destroy_bay, bay.uuid)
self.dbapi.destroy_bay(bay.uuid)
self.assertRaises(exception.PodNotFound,
self.dbapi.get_pod_by_id, self.context, pod.id)
def test_destroy_bay_that_has_services(self):
bay = utils.create_test_bay()
service = utils.create_test_service(bay_uuid=bay.uuid)
self.assertEqual(bay.uuid, service.bay_uuid)
self.assertRaises(exception.BayNotEmpty,
self.dbapi.destroy_bay, bay.id)
self.dbapi.destroy_bay(bay.id)
self.assertRaises(exception.ServiceNotFound,
self.dbapi.get_service_by_id,
self.context, service.id)
def test_destroy_bay_that_has_services_by_uuid(self):
bay = utils.create_test_bay()
service = utils.create_test_service(bay_uuid=bay.uuid)
self.assertEqual(bay.uuid, service.bay_uuid)
self.assertRaises(exception.BayNotEmpty,
self.dbapi.destroy_bay, bay.uuid)
self.dbapi.destroy_bay(bay.id)
self.assertRaises(exception.ServiceNotFound,
self.dbapi.get_service_by_id,
self.context, service.id)
def test_destroy_bay_that_has_rc(self):
bay = utils.create_test_bay()
rc = utils.create_test_rc(bay_uuid=bay.uuid)
self.assertEqual(bay.uuid, rc.bay_uuid)
self.dbapi.destroy_bay(bay.id)
self.assertRaises(exception.ReplicationControllerNotFound,
self.dbapi.get_rc_by_id,
self.context, rc.id)
def test_destroy_bay_that_has_rc_by_uuid(self):
bay = utils.create_test_bay()
rc = utils.create_test_rc(bay_uuid=bay.uuid)
self.assertEqual(bay.uuid, rc.bay_uuid)
self.dbapi.destroy_bay(bay.uuid)
self.assertRaises(exception.ReplicationControllerNotFound,
self.dbapi.get_rc_by_id,
self.context, rc.id)
def test_update_bay(self):
bay = utils.create_test_bay()