Add check for non-existing table internal name for delete table

This change added check for non-existing internal name for tables
which caused exception when trying to delete table in CREATE_FAILED
or DELETE_FALED status if table internal name does not exist.

Change-Id: I3175a364a4e678f35b860db26f9dec999997f8a0
Closes-bug: #1422908
This commit is contained in:
Charles Wang 2015-02-17 17:28:39 -05:00
parent 84644abbb3
commit 0efeb6242d
3 changed files with 165 additions and 1 deletions

View File

@ -156,7 +156,21 @@ class SimpleStorageManager(manager.StorageManager):
self._table_info_repo.update(context, table_info, ["status"])
self._do_delete_table(context, table_info)
if not table_info.internal_name:
# if table internal name is missing, table is not actually created
# just remove the table_info entry for the table and
# send notification
LOG.info(("Table '{}' with tenant id '{}', id '{}' does not have "
"valid internal name. Unable or no need to delete.").
format(table_info.name, context.tenant, table_info.id))
self._table_info_repo.delete(context, table_info.name)
self._notifier.info(
context,
notifier.EVENT_TYPE_TABLE_DELETE_END,
table_info.name)
else:
self._do_delete_table(context, table_info)
return models.TableMeta(
table_info.id,

View File

@ -100,6 +100,7 @@ class AsyncStorageManagerTestCase(unittest.TestCase):
id = None
schema = None
creation_date_time = None
internal_name = 'fake'
mock_table_info_repo = mock.Mock()
mock_table_info_repo.get.return_value = FakeTableInfo()
@ -136,3 +137,151 @@ class AsyncStorageManagerTestCase(unittest.TestCase):
# delete method of mock_table_info_repo has been called
self.assertTrue(mock_table_info_repo.delete.called)
@mock.patch('magnetodb.storage.table_info_repo')
def test_delete_table_create_or_delete_failed(self, mock_table_info_repo):
context = mock.Mock(tenant='fake_tenant')
table_name = 'fake_table'
mock_storage_driver = mock.Mock()
mock_storage_driver.delete_table.return_value = True
class FakeTableInfoCreateFailed:
status = models.TableMeta.TABLE_STATUS_CREATE_FAILED
name = table_name
in_use = False
id = None
schema = None
creation_date_time = None
internal_name = None
mock_table_info_repo = mock.Mock()
mock_table_info_repo.get.return_value = FakeTableInfoCreateFailed()
storage_manager = async_simple_impl.AsyncSimpleStorageManager(
mock_storage_driver,
mock_table_info_repo
)
storage_manager.delete_table(context, table_name)
table_info_update_args_list = (
mock_table_info_repo.update.call_args_list
)
# called once, length of call_args_list indicates number of calls
self.assertEqual(1, len(table_info_update_args_list))
self.assertEqual(2, len(table_info_update_args_list[0]))
# tuple of Mock, TableInfo, and status list
self.assertEqual(3, len(table_info_update_args_list[0][0]))
# TableInfo status should be deleting
self.assertEqual(models.TableMeta.TABLE_STATUS_DELETING,
table_info_update_args_list[0][0][1].status)
for i in range(10):
if mock_table_info_repo.delete.called:
# delete_table method of mock_storage_driver should not
# have been called since table does not actually exist
self.assertFalse(mock_storage_driver.delete_table.called)
break
else:
time.sleep(1)
# delete method of mock_table_info_repo has been called
self.assertTrue(mock_table_info_repo.delete.called)
class FakeTableInfoDeleteFailedTableNotExist:
status = models.TableMeta.TABLE_STATUS_DELETE_FAILED
name = table_name
in_use = False
id = None
schema = None
creation_date_time = None
internal_name = None
mock_table_info_repo = mock.Mock()
mock_table_info_repo.get.return_value = (
FakeTableInfoDeleteFailedTableNotExist())
storage_manager = async_simple_impl.AsyncSimpleStorageManager(
mock_storage_driver,
mock_table_info_repo
)
storage_manager.delete_table(context, table_name)
table_info_update_args_list = (
mock_table_info_repo.update.call_args_list
)
# called once, length of call_args_list indicates number of calls
self.assertEqual(1, len(table_info_update_args_list))
self.assertEqual(2, len(table_info_update_args_list[0]))
# tuple of Mock, TableInfo, and status list
self.assertEqual(3, len(table_info_update_args_list[0][0]))
# TableInfo status should be deleting
self.assertEqual(models.TableMeta.TABLE_STATUS_DELETING,
table_info_update_args_list[0][0][1].status)
for i in range(10):
if mock_table_info_repo.delete.called:
# delete_table method of mock_storage_driver should not
# have been called since table does not actually exist
self.assertFalse(mock_storage_driver.delete_table.called)
break
else:
time.sleep(1)
# delete method of mock_table_info_repo has been called
self.assertTrue(mock_table_info_repo.delete.called)
class FakeTableInfoDeleteFailedButTableExist:
status = models.TableMeta.TABLE_STATUS_DELETE_FAILED
name = table_name
in_use = False
id = None
schema = None
creation_date_time = None
internal_name = 'fake'
mock_table_info_repo = mock.Mock()
mock_table_info_repo.get.return_value = (
FakeTableInfoDeleteFailedButTableExist())
storage_manager = async_simple_impl.AsyncSimpleStorageManager(
mock_storage_driver,
mock_table_info_repo
)
storage_manager.delete_table(context, table_name)
table_info_update_args_list = (
mock_table_info_repo.update.call_args_list
)
# called once, length of call_args_list indicates number of calls
self.assertEqual(1, len(table_info_update_args_list))
self.assertEqual(2, len(table_info_update_args_list[0]))
# tuple of Mock, TableInfo, and status list
self.assertEqual(3, len(table_info_update_args_list[0][0]))
# TableInfo status should be deleting
self.assertEqual(models.TableMeta.TABLE_STATUS_DELETING,
table_info_update_args_list[0][0][1].status)
for i in range(10):
if mock_table_info_repo.delete.called:
# delete_table method of mock_storage_driver should
# have been called because table exists
self.assertTrue(mock_storage_driver.delete_table.called)
break
else:
time.sleep(1)
# delete method of mock_table_info_repo has been called
self.assertTrue(mock_table_info_repo.delete.called)

View File

@ -101,6 +101,7 @@ class TestNotifyStorageManager(test_notification.TestNotify):
id = None
schema = None
creation_date_time = None
internal_name = None
mock_table_info_repo = mock.Mock()
mock_table_info_repo.get.return_value = FakeTableInfo()