From: Xiao Chen Date: Wed, 11 Sep 2013 06:37:16 +0000 (+0800) Subject: Fixing UnicodeEncodeError against volume creating function X-Git-Url: https://review.fuel-infra.org/gitweb?a=commitdiff_plain;h=b3e8cb5b4236c39126d445c7645aed2922ab3991;p=openstack-build%2Fcinder-build.git Fixing UnicodeEncodeError against volume creating function When creating a volume with non-English characters and there is not enough space for it, then an UnicodeEncodeError occurs. So we need convert any coded exception message to unicode string for logging. Fixes bug 1223128 Change-Id: If1d4faad2bcde696f20565deb01226de33caccad --- diff --git a/cinder/tests/test_create_volume_flow.py b/cinder/tests/test_create_volume_flow.py index e3e7452bd..a3c550be5 100644 --- a/cinder/tests/test_create_volume_flow.py +++ b/cinder/tests/test_create_volume_flow.py @@ -79,6 +79,27 @@ class CreateVolumeFlowTestCase(test.TestCase): self.counter = float(0) self.stubs.Set(time, 'time', self.time_inc) + def test_exception_to_unicode(self): + class FakeException(Exception): + def __str__(self): + raise UnicodeError() + + exc = Exception('error message') + ret = create_volume._exception_to_unicode(exc) + self.assertEqual(unicode, type(ret)) + self.assertEqual(ret, 'error message') + + exc = Exception('\xa5 error message') + ret = create_volume._exception_to_unicode(exc) + self.assertEqual(unicode, type(ret)) + self.assertEqual(ret, ' error message') + + unicodeExc = FakeException('\xa5 error message') + ret = create_volume._exception_to_unicode(unicodeExc) + self.assertEqual(unicode, type(ret)) + self.assertEqual(ret, _("Caught '%(exception)s' exception.") % + {'exception': 'FakeException'}) + def test_cast_create_volume(self): props = {} diff --git a/cinder/volume/flows/create_volume/__init__.py b/cinder/volume/flows/create_volume/__init__.py index 391250a6f..b0ea1c9cc 100644 --- a/cinder/volume/flows/create_volume/__init__.py +++ b/cinder/volume/flows/create_volume/__init__.py @@ -30,6 +30,7 @@ from cinder.openstack.common import excutils from cinder.openstack.common import log as logging from cinder.openstack.common.notifier import api as notifier from cinder.openstack.common import processutils +from cinder.openstack.common import strutils from cinder.openstack.common import timeutils from cinder import policy from cinder import quota @@ -147,6 +148,18 @@ def _error_out_volume(context, db, volume_id, reason=None): 'update': update}) +def _exception_to_unicode(exc): + try: + return unicode(exc) + except UnicodeError: + try: + return strutils.safe_decode(str(exc), errors='ignore') + except UnicodeError: + msg = (_("Caught '%(exception)s' exception.") % + {"exception": exc.__class__.__name__}) + return strutils.safe_decode(msg, errors='ignore') + + class ExtractVolumeRequestTask(base.CinderTask): """Processes an api request values into a validated set of values. @@ -868,7 +881,8 @@ class OnFailureRescheduleTask(base.CinderTask): "attempt %(num)d due to %(reason)s") % {'volume_id': volume_id, 'method': _make_pretty_name(create_volume), - 'num': num_attempts, 'reason': unicode(cause.exc)}) + 'num': num_attempts, + 'reason': _exception_to_unicode(cause.exc)}) if all(cause.exc_info): # Stringify to avoid circular ref problem in json serialization