Merge "Add retry in VNX driver when DB lock error happened"

This commit is contained in:
Jenkins 2016-07-27 19:51:39 +00:00 committed by Gerrit Code Review
commit 200f2b02fb
4 changed files with 66 additions and 15 deletions

View File

@ -39,6 +39,9 @@ MSG_INTERFACE_NON_EXISTENT = '13691781134'
MSG_JOIN_DOMAIN = '13157007726'
MSG_UNJOIN_DOMAIN = '13157007723'
# Necessary to retry when VNX database is locked for provisioning operation
MSG_CODE_RETRY = '13421840537'
IP_ALLOCATIONS = 2
CONTENT_TYPE_URLENCODE = {'Content-Type': 'application/x-www-form-urlencoded'}

View File

@ -98,7 +98,7 @@ class StorageObject(object):
'info': response})
def _response_validation(self, response, error_code):
"""Translate different status to ok/error status."""
"""Validates whether a response includes a certain error code."""
msg_codes = self._get_problem_message_codes(response['problems'])
for code in msg_codes:
@ -146,6 +146,7 @@ class StorageObject(object):
)
)
@utils.retry(exception.EMCVnxLockRequiredException)
def _send_request(self, req):
req_xml = constants.XML_HEADER + ET.tostring(req).decode('utf-8')
@ -155,6 +156,11 @@ class StorageObject(object):
self._translate_response(response)
if (response['maxSeverity'] != constants.STATUS_OK and
self._response_validation(response,
constants.MSG_CODE_RETRY)):
raise exception.EMCVnxLockRequiredException
return response
@utils.retry(exception.EMCVnxLockRequiredException)

View File

@ -247,6 +247,21 @@ class StorageObjectTestData(object):
'</Fault> '
)
@response
def resp_need_retry(self):
return ('<TaskResponse taskId="915525">'
'<Status maxSeverity = "error">'
'<Problem messageCode = "13421840537" component = "fake"'
' message = "unable to acquire lock(s), try later"'
' severity = "error" >'
'<Description> fake desp. </Description>'
'<Action>fake action </Action>'
'</Problem></Status></TaskResponse>')
@start_task
def req_fake_start_task(self):
return '<StartFake name="foo"></StartFake>'
class FileSystemTestData(StorageObjectTestData):
def __init__(self):

View File

@ -16,6 +16,7 @@
import copy
import ddt
from lxml import builder
import mock
from oslo_concurrency import processutils
@ -24,6 +25,7 @@ from manila import exception
from manila.share.drivers.emc.plugins.vnx import connector
from manila.share.drivers.emc.plugins.vnx import constants
from manila.share.drivers.emc.plugins.vnx import object_manager as manager
from manila.share.drivers.emc.plugins.vnx import xml_api_parser as parser
from manila import test
from manila.tests.share.drivers.emc.plugins.vnx import fakes
from manila.tests.share.drivers.emc.plugins.vnx import utils
@ -71,17 +73,17 @@ class StorageObjectManagerTestCase(test.TestCase):
fake_type)
class StorageObjectTestCase(test.TestCase):
class StorageObjectTestCaseBase(test.TestCase):
@mock.patch.object(connector, "XMLAPIConnector", mock.Mock())
@mock.patch.object(connector, "SSHConnector", mock.Mock())
def setUp(self):
super(StorageObjectTestCase, self).setUp()
super(StorageObjectTestCaseBase, self).setUp()
emd_share_driver = fakes.FakeEMCShareDriver()
self.manager = manager.StorageObjectManager(
emd_share_driver.configuration)
self.base = fakes.StorageObjectTestData()
self.pool = fakes.PoolTestData()
self.vdm = fakes.VDMTestData()
self.mover = fakes.MoverTestData()
@ -94,7 +96,32 @@ class StorageObjectTestCase(test.TestCase):
self.dns = fakes.DNSDomainTestData()
class FileSystemTestCase(StorageObjectTestCase):
class StorageObjectTestCase(StorageObjectTestCaseBase):
def test_xml_api_retry(self):
hook = utils.RequestSideEffect()
hook.append(self.base.resp_need_retry())
hook.append(self.base.resp_task_succeed())
elt_maker = builder.ElementMaker(nsmap={None: constants.XML_NAMESPACE})
xml_parser = parser.XMLAPIParser()
storage_object = manager.StorageObject(self.manager.connectors,
elt_maker, xml_parser,
self.manager)
storage_object.conn['XML'].request = utils.EMCMock(side_effect=hook)
fake_req = storage_object._build_task_package(
elt_maker.StartFake(name='foo')
)
resp = storage_object._send_request(fake_req)
self.assertEqual('ok', resp['maxSeverity'])
expected_calls = [
mock.call(self.base.req_fake_start_task()),
mock.call(self.base.req_fake_start_task())
]
storage_object.conn['XML'].request.assert_has_calls(expected_calls)
class FileSystemTestCase(StorageObjectTestCaseBase):
def setUp(self):
super(self.__class__, self).setUp()
self.hook = utils.RequestSideEffect()
@ -507,7 +534,7 @@ class FileSystemTestCase(StorageObjectTestCase):
context.conn['SSH'].run_ssh.assert_has_calls(ssh_calls)
class MountPointTestCase(StorageObjectTestCase):
class MountPointTestCase(StorageObjectTestCaseBase):
def setUp(self):
super(self.__class__, self).setUp()
self.hook = utils.RequestSideEffect()
@ -824,7 +851,7 @@ class MountPointTestCase(StorageObjectTestCase):
context.conn['XML'].request.assert_has_calls(expected_calls)
class VDMTestCase(StorageObjectTestCase):
class VDMTestCase(StorageObjectTestCaseBase):
def setUp(self):
super(self.__class__, self).setUp()
self.hook = utils.RequestSideEffect()
@ -1088,7 +1115,7 @@ class VDMTestCase(StorageObjectTestCase):
context.conn['SSH'].run_ssh.assert_has_calls(ssh_calls)
class StoragePoolTestCase(StorageObjectTestCase):
class StoragePoolTestCase(StorageObjectTestCaseBase):
def setUp(self):
super(self.__class__, self).setUp()
self.hook = utils.RequestSideEffect()
@ -1155,7 +1182,7 @@ class StoragePoolTestCase(StorageObjectTestCase):
context.conn['XML'].request.assert_has_calls(expected_calls)
class MoverTestCase(StorageObjectTestCase):
class MoverTestCase(StorageObjectTestCaseBase):
def setUp(self):
super(self.__class__, self).setUp()
self.hook = utils.RequestSideEffect()
@ -1332,7 +1359,7 @@ class MoverTestCase(StorageObjectTestCase):
context.conn['SSH'].run_ssh.assert_has_calls(ssh_calls)
class SnapshotTestCase(StorageObjectTestCase):
class SnapshotTestCase(StorageObjectTestCaseBase):
def setUp(self):
super(self.__class__, self).setUp()
self.hook = utils.RequestSideEffect()
@ -1522,7 +1549,7 @@ class SnapshotTestCase(StorageObjectTestCase):
@ddt.ddt
class MoverInterfaceTestCase(StorageObjectTestCase):
class MoverInterfaceTestCase(StorageObjectTestCaseBase):
def setUp(self):
super(self.__class__, self).setUp()
self.hook = utils.RequestSideEffect()
@ -1815,7 +1842,7 @@ class MoverInterfaceTestCase(StorageObjectTestCase):
context.conn['XML'].request.assert_has_calls(expected_calls)
class DNSDomainTestCase(StorageObjectTestCase):
class DNSDomainTestCase(StorageObjectTestCaseBase):
def setUp(self):
super(self.__class__, self).setUp()
self.hook = utils.RequestSideEffect()
@ -1925,7 +1952,7 @@ class DNSDomainTestCase(StorageObjectTestCase):
self.assertTrue(sleep_mock.called)
class CIFSServerTestCase(StorageObjectTestCase):
class CIFSServerTestCase(StorageObjectTestCaseBase):
def setUp(self):
super(self.__class__, self).setUp()
self.hook = utils.RequestSideEffect()
@ -2363,7 +2390,7 @@ class CIFSServerTestCase(StorageObjectTestCase):
context.conn['XML'].request.assert_has_calls(expected_calls)
class CIFSShareTestCase(StorageObjectTestCase):
class CIFSShareTestCase(StorageObjectTestCaseBase):
def setUp(self):
super(self.__class__, self).setUp()
self.hook = utils.RequestSideEffect()
@ -2712,7 +2739,7 @@ class CIFSShareTestCase(StorageObjectTestCase):
context.conn['SSH'].run_ssh.assert_has_calls(ssh_calls)
class NFSShareTestCase(StorageObjectTestCase):
class NFSShareTestCase(StorageObjectTestCaseBase):
def setUp(self):
super(self.__class__, self).setUp()
self.ssh_hook = utils.SSHSideEffect()