From ff8d6074d5965809e992473d40ebab0741db7f4e Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Wed, 22 Jun 2016 10:04:08 +0200 Subject: [PATCH] Port cinder unit tests to Python 3 * test_cinder: set the code attribute of cinder client exceptions. Otherwise ClientException.__str__() of cinderclient.exceptions fails on self.code >= 100 with a TypeError (None cannot be compared to int). * Fix usage of six.reraise() in cinder _reraise(): pass the exception object as exc_value, and use type(exc) for exc_type * Use "except ... as exc:" syntax to get the current exception value instead of using sys.exc_info(). Calling sys.exc_info() in an exception handler can create reference cycles in Python 3. * Replace six.text_type(exc) with exception_to_unicode(exc) of oslo_utils.encodeutils. This function is safer and handles more cases. * tests-py3.txt: run cinder tests on Python 3 This change is partially based on the work of dims, change Ibb4fa47cd71d697a4996425b1797ac2f8cc363cd. Co-Authored-By: Davanum Srinivas Partially-Implements: blueprint nova-python3-newton Change-Id: I5c252106c0e681b79033b47ebb3d457ff23ed624 --- nova/tests/unit/volume/test_cinder.py | 12 +++++++----- nova/volume/cinder.py | 24 +++++++++++------------- tests-py3.txt | 3 --- 3 files changed, 18 insertions(+), 21 deletions(-) diff --git a/nova/tests/unit/volume/test_cinder.py b/nova/tests/unit/volume/test_cinder.py index 7722ef9009..036d49e36a 100644 --- a/nova/tests/unit/volume/test_cinder.py +++ b/nova/tests/unit/volume/test_cinder.py @@ -71,8 +71,10 @@ class CinderApiTestCase(test.NoDBTestCase): def test_get_failed(self): volume_id = 'volume_id' - cinder.cinderclient(self.ctx).AndRaise(cinder_exception.NotFound('')) - cinder.cinderclient(self.ctx).AndRaise(cinder_exception.BadRequest('')) + cinder.cinderclient(self.ctx).AndRaise( + cinder_exception.NotFound(404, '404')) + cinder.cinderclient(self.ctx).AndRaise( + cinder_exception.BadRequest(400, '400')) cinder.cinderclient(self.ctx).AndRaise( cinder_exception.ConnectionError('')) self.mox.ReplayAll() @@ -94,7 +96,7 @@ class CinderApiTestCase(test.NoDBTestCase): @mock.patch('nova.volume.cinder.cinderclient') def test_create_failed(self, mock_cinderclient): mock_cinderclient.return_value.volumes.create.side_effect = ( - cinder_exception.BadRequest('')) + cinder_exception.BadRequest(400, '400')) self.assertRaises(exception.InvalidInput, self.api.create, self.ctx, 1, '', '') @@ -486,7 +488,7 @@ class CinderApiTestCase(test.NoDBTestCase): def test_translate_cinder_exception_cinder_bad_request(self): self._do_translate_cinder_exception_test( - cinder_exception.BadRequest(''), + cinder_exception.BadRequest(400, '400'), exception.InvalidInput) def test_translate_cinder_exception_keystone_bad_request(self): @@ -496,7 +498,7 @@ class CinderApiTestCase(test.NoDBTestCase): def test_translate_cinder_exception_cinder_forbidden(self): self._do_translate_cinder_exception_test( - cinder_exception.Forbidden(''), + cinder_exception.Forbidden(403, '403'), exception.Forbidden) def test_translate_cinder_exception_keystone_forbidden(self): diff --git a/nova/volume/cinder.py b/nova/volume/cinder.py index 505ebc1117..348076faf8 100644 --- a/nova/volume/cinder.py +++ b/nova/volume/cinder.py @@ -29,6 +29,7 @@ from cinderclient.v1 import client as v1_client from keystoneauth1 import exceptions as keystone_exception from keystoneauth1 import loading as ks_loading from oslo_log import log as logging +from oslo_utils import encodeutils from oslo_utils import excutils from oslo_utils import strutils import six @@ -186,18 +187,17 @@ def translate_cinder_exception(method): try: res = method(self, ctx, *args, **kwargs) except (cinder_exception.ConnectionError, - keystone_exception.ConnectionError): - exc_type, exc_value, exc_trace = sys.exc_info() - _reraise(exception.CinderConnectionFailed( - reason=six.text_type(exc_value))) + keystone_exception.ConnectionError) as exc: + err_msg = encodeutils.exception_to_unicode(exc) + _reraise(exception.CinderConnectionFailed(reason=err_msg)) except (keystone_exception.BadRequest, - cinder_exception.BadRequest): - exc_type, exc_value, exc_trace = sys.exc_info() - _reraise(exception.InvalidInput(reason=six.text_type(exc_value))) + cinder_exception.BadRequest) as exc: + err_msg = encodeutils.exception_to_unicode(exc) + _reraise(exception.InvalidInput(reason=err_msg)) except (keystone_exception.Forbidden, - cinder_exception.Forbidden): - exc_type, exc_value, exc_trace = sys.exc_info() - _reraise(exception.Forbidden(six.text_type(exc_value))) + cinder_exception.Forbidden) as exc: + err_msg = encodeutils.exception_to_unicode(exc) + _reraise(exception.Forbidden(err_msg)) return res return wrapper @@ -243,9 +243,7 @@ def translate_mixed_exceptions(method): def _reraise(desired_exc): - exc_type, exc_value, exc_trace = sys.exc_info() - exc_value = desired_exc - six.reraise(exc_value, None, exc_trace) + six.reraise(type(desired_exc), desired_exc, sys.exc_info()[2]) class API(object): diff --git a/tests-py3.txt b/tests-py3.txt index 5dc9242de2..5057f43659 100644 --- a/tests-py3.txt +++ b/tests-py3.txt @@ -58,8 +58,6 @@ nova.tests.unit.pci.test_stats.PciDeviceStatsTestCase nova.tests.unit.pci.test_stats.PciDeviceStatsWithTagsTestCase nova.tests.unit.test_api_validation.Base64TestCase nova.tests.unit.test_bdm.BlockDeviceMappingEc2CloudTestCase -nova.tests.unit.test_cinder.CinderTestCase -nova.tests.unit.test_cinder.CinderV2TestCase nova.tests.unit.test_configdrive2.ConfigDriveTestCase nova.tests.unit.test_hacking.HackingTestCase nova.tests.unit.test_ipv6.IPv6AccountIdentiferTestCase @@ -107,7 +105,6 @@ nova.tests.unit.virt.xenapi.test_xenapi.HypervisorPoolTestCase nova.tests.unit.virt.xenapi.test_xenapi.XenAPIDiffieHellmanTestCase nova.tests.unit.virt.xenapi.test_xenapi.XenAPIDom0IptablesFirewallTestCase nova.tests.unit.virt.xenapi.test_xenapi.XenAPIVMTestCase -nova.tests.unit.volume.test_cinder.CinderApiTestCase ########################################################################## # NOTE(dims): The following tests randomly fail in the gate. Please be