Merge "Fix share manager to save data after driver error"
This commit is contained in:
commit
a2b175719b
@ -71,8 +71,9 @@ class ManilaException(Exception):
|
||||
headers = {}
|
||||
safe = False
|
||||
|
||||
def __init__(self, message=None, **kwargs):
|
||||
def __init__(self, message=None, detail_data={}, **kwargs):
|
||||
self.kwargs = kwargs
|
||||
self.detail_data = detail_data
|
||||
|
||||
if 'code' not in self.kwargs:
|
||||
try:
|
||||
|
@ -30,6 +30,7 @@ from manila import context
|
||||
from manila import exception
|
||||
from manila.i18n import _LE
|
||||
from manila.i18n import _LI
|
||||
from manila.i18n import _LW
|
||||
from manila import manager
|
||||
from manila import network
|
||||
from manila.openstack.common import log as logging
|
||||
@ -242,9 +243,20 @@ class ShareManager(manager.SchedulerDependentManager):
|
||||
context, share_ref, share_server=share_server)
|
||||
self.db.share_update(context, share_id,
|
||||
{'export_location': export_location})
|
||||
except Exception:
|
||||
except Exception as e:
|
||||
with excutils.save_and_reraise_exception():
|
||||
LOG.error(_LE("Share %s failed on creation."), share_id)
|
||||
detail_data = getattr(e, 'detail_data', {})
|
||||
if (isinstance(detail_data, dict) and
|
||||
detail_data.get('export_location')):
|
||||
self.db.share_update(
|
||||
context, share_id,
|
||||
{'export_location': detail_data['export_location']})
|
||||
else:
|
||||
LOG.warning(_LW('Share information in exception '
|
||||
'can not be written to db because it '
|
||||
'contains %s and it is not a dictionary.'),
|
||||
detail_data)
|
||||
self.db.share_update(context, share_id, {'status': 'error'})
|
||||
else:
|
||||
LOG.info(_LI("Share created successfully."))
|
||||
@ -447,8 +459,23 @@ class ShareManager(manager.SchedulerDependentManager):
|
||||
return self.db.share_server_update(
|
||||
context, share_server['id'],
|
||||
{'status': constants.STATUS_ACTIVE})
|
||||
except Exception:
|
||||
except Exception as e:
|
||||
with excutils.save_and_reraise_exception():
|
||||
detail_data = getattr(e, 'detail_data', {})
|
||||
if (type(detail_data) is dict and
|
||||
detail_data.get('server_details')):
|
||||
|
||||
server_details = detail_data['server_details']
|
||||
|
||||
if isinstance(server_details, dict):
|
||||
self.db.share_server_backend_details_set(
|
||||
context, share_server['id'], server_details)
|
||||
else:
|
||||
LOG.warning(_LW('Server Information in '
|
||||
'exception can not be written to db '
|
||||
'because it contains %s and it is not '
|
||||
'a dictionary.'), server_details)
|
||||
|
||||
self.db.share_server_update(context, share_server['id'],
|
||||
{'status': constants.STATUS_ERROR})
|
||||
self.network_api.deallocate_network(context, share_network)
|
||||
|
@ -566,6 +566,25 @@ class ShareManagerTestCase(test.TestCase):
|
||||
self.assertEqual(shr['status'], 'available')
|
||||
self.assertEqual(shr['share_server_id'], share_srv['id'])
|
||||
|
||||
def test_create_share_with_error_in_driver(self):
|
||||
"""Test db updates if share creation fails in driver."""
|
||||
share = self._create_share()
|
||||
share_id = share['id']
|
||||
some_data = 'fake_location'
|
||||
self.share_manager.driver = mock.Mock()
|
||||
e = exception.ManilaException(
|
||||
detail_data={'export_location': some_data})
|
||||
self.share_manager.driver.create_share.side_effect = e
|
||||
self.assertRaises(
|
||||
exception.ManilaException,
|
||||
self.share_manager.create_share,
|
||||
self.context,
|
||||
share_id
|
||||
)
|
||||
self.assertTrue(self.share_manager.driver.create_share.called)
|
||||
shr = db.share_get(self.context, share_id)
|
||||
self.assertEqual(some_data, shr['export_location'])
|
||||
|
||||
def test_create_share_with_server_created(self):
|
||||
"""Test share can be created and share server is created."""
|
||||
share_net = self._create_share_network()
|
||||
@ -951,3 +970,102 @@ class ShareManagerTestCase(test.TestCase):
|
||||
context, share_server['id'], {'status': constants.STATUS_ERROR})
|
||||
self.share_manager.network_api.deallocate_network.\
|
||||
assert_called_once_with(context, share_network)
|
||||
|
||||
def test_setup_server_exception_in_driver(self):
|
||||
# Setup required test data
|
||||
context = "fake_context"
|
||||
share_server = {
|
||||
'id': 'fake_id',
|
||||
'share_network_id': 'fake_sn_id',
|
||||
}
|
||||
share_network = {'id': 'fake_sn_id'}
|
||||
server_info = {'details_key': 'value'}
|
||||
network_info = {'fake_network_info_key': 'fake_network_info_value'}
|
||||
allocation_number = 0
|
||||
|
||||
# Mock required parameters
|
||||
self.stubs.Set(self.share_manager.db, 'share_network_get',
|
||||
mock.Mock(return_value=share_network))
|
||||
self.stubs.Set(self.share_manager.driver,
|
||||
'get_network_allocations_number',
|
||||
mock.Mock(return_value=allocation_number))
|
||||
self.stubs.Set(self.share_manager.db, 'share_server_update',
|
||||
mock.Mock())
|
||||
self.stubs.Set(self.share_manager.network_api, 'deallocate_network',
|
||||
mock.Mock())
|
||||
self.stubs.Set(self.share_manager, '_form_server_setup_info',
|
||||
mock.Mock(return_value=network_info))
|
||||
self.stubs.Set(self.share_manager.db,
|
||||
'share_server_backend_details_set',
|
||||
mock.Mock())
|
||||
self.stubs.Set(self.share_manager.driver, 'setup_server',
|
||||
mock.Mock(side_effect=exception.ManilaException(
|
||||
detail_data={'server_details': server_info})))
|
||||
|
||||
# execute method _setup_server
|
||||
self.assertRaises(
|
||||
exception.ManilaException,
|
||||
self.share_manager._setup_server,
|
||||
context,
|
||||
share_server,
|
||||
)
|
||||
self.share_manager.db.share_network_get.assert_called_once_with(
|
||||
context, share_server['share_network_id'])
|
||||
self.share_manager.driver.get_network_allocations_number.\
|
||||
assert_called_once_with()
|
||||
self.share_manager._form_server_setup_info.assert_called_once_with(
|
||||
context, share_server, share_network)
|
||||
self.share_manager.db.share_server_backend_details_set.\
|
||||
assert_called_once_with(context, share_server['id'], server_info)
|
||||
self.share_manager.db.share_server_update.assert_called_once_with(
|
||||
context, share_server['id'], {'status': constants.STATUS_ERROR})
|
||||
self.share_manager.network_api.deallocate_network.\
|
||||
assert_called_once_with(context, share_network)
|
||||
|
||||
def test_setup_server_incorrect_detail_data(self):
|
||||
# Setup required test data
|
||||
context = "fake_context"
|
||||
share_server = {
|
||||
'id': 'fake_id',
|
||||
'share_network_id': 'fake_sn_id',
|
||||
}
|
||||
share_network = {'id': 'fake_sn_id'}
|
||||
network_info = {'fake_network_info_key': 'fake_network_info_value'}
|
||||
allocation_number = 0
|
||||
|
||||
# Mock required parameters
|
||||
self.stubs.Set(self.share_manager.db, 'share_network_get',
|
||||
mock.Mock(return_value=share_network))
|
||||
self.stubs.Set(self.share_manager.driver,
|
||||
'get_network_allocations_number',
|
||||
mock.Mock(return_value=allocation_number))
|
||||
self.stubs.Set(self.share_manager.db, 'share_server_update',
|
||||
mock.Mock())
|
||||
self.stubs.Set(self.share_manager.network_api, 'deallocate_network',
|
||||
mock.Mock())
|
||||
self.stubs.Set(self.share_manager, '_form_server_setup_info',
|
||||
mock.Mock(return_value=network_info))
|
||||
self.stubs.Set(self.share_manager.db,
|
||||
'share_server_backend_details_set',
|
||||
mock.Mock())
|
||||
self.stubs.Set(self.share_manager.driver, 'setup_server',
|
||||
mock.Mock(side_effect=exception.ManilaException(
|
||||
detail_data='not dictionary detail data')))
|
||||
|
||||
# execute method _setup_server
|
||||
self.assertRaises(
|
||||
exception.ManilaException,
|
||||
self.share_manager._setup_server,
|
||||
context,
|
||||
share_server,
|
||||
)
|
||||
self.share_manager.db.share_network_get.assert_called_once_with(
|
||||
context, share_server['share_network_id'])
|
||||
self.share_manager.driver.get_network_allocations_number.\
|
||||
assert_called_once_with()
|
||||
self.share_manager._form_server_setup_info.assert_called_once_with(
|
||||
context, share_server, share_network)
|
||||
self.share_manager.db.share_server_update.assert_called_once_with(
|
||||
context, share_server['id'], {'status': constants.STATUS_ERROR})
|
||||
self.share_manager.network_api.deallocate_network.\
|
||||
assert_called_once_with(context, share_network)
|
||||
|
Loading…
x
Reference in New Issue
Block a user