]> review.fuel-infra Code Review - openstack-build/cinder-build.git/commitdiff
Fixing UnicodeEncodeError against volume creating function
authorXiao Chen <chenxiao@cn.ibm.com>
Wed, 11 Sep 2013 06:37:16 +0000 (14:37 +0800)
committerXiao Chen <chenxiao@cn.ibm.com>
Wed, 11 Sep 2013 10:37:50 +0000 (18:37 +0800)
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

cinder/tests/test_create_volume_flow.py
cinder/volume/flows/create_volume/__init__.py

index e3e7452bd39d5c3cfb7f9307fbb5b36270b0ca85..a3c550be5e0ffcab46dae8139a31a3542ef3a00e 100644 (file)
@@ -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 = {}
index 391250a6f33cf4e0010d6119b1213aea02d2e375..b0ea1c9cc59920e27522474af9c1d068b4602588 100644 (file)
@@ -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