diff --git a/glance_store/_drivers/filesystem.py b/glance_store/_drivers/filesystem.py index 56e4ea6d..372a06e9 100644 --- a/glance_store/_drivers/filesystem.py +++ b/glance_store/_drivers/filesystem.py @@ -545,4 +545,4 @@ class Store(glance_store.driver.Store): except Exception as e: msg = _('Unable to remove partial image ' 'data for image %(iid)s: %(e)s') - LOG.error(msg % dict(iid=iid, e=e)) + LOG.error(msg % dict(iid=iid, e=utils.exception_to_str(e))) diff --git a/glance_store/_drivers/s3.py b/glance_store/_drivers/s3.py index 7c114c3c..fdc5b20c 100644 --- a/glance_store/_drivers/s3.py +++ b/glance_store/_drivers/s3.py @@ -519,7 +519,8 @@ def create_bucket_if_missing(conf, bucket, s3_conn): s3_conn.create_bucket(bucket, location=location) except S3ResponseError as e: msg = (_("Failed to add bucket to S3.\n" - "Got error from S3: %(e)s") % {'e': e}) + "Got error from S3: %s.") % + utils.exception_to_str(e)) raise glance_store.BackendException(msg) else: msg = (_("The bucket %(bucket)s does not exist in " diff --git a/glance_store/_drivers/swift/store.py b/glance_store/_drivers/swift/store.py index 95b7cb2b..1ca2f2e4 100644 --- a/glance_store/_drivers/swift/store.py +++ b/glance_store/_drivers/swift/store.py @@ -28,6 +28,7 @@ import urllib import glance_store from glance_store._drivers.swift import utils as sutils from glance_store.common import auth +from glance_store.common import utils as cutils from glance_store import driver from glance_store import exceptions from glance_store import i18n @@ -118,7 +119,8 @@ def swift_retry_iter(resp_iter, length, store, location, context): yield chunk bytes_read += len(chunk) except swiftclient.ClientException as e: - LOG.warn(_(u"Swift exception raised %s") % unicode(e)) + LOG.warn(_("Swift exception raised %s") % + cutils.exception_to_str(e)) if bytes_read != length: if retries == store.conf.glance_store.swift_store_retry_get_count: @@ -578,7 +580,7 @@ class BaseStore(driver.Store): raise exceptions.Duplicate(message=msg) msg = (_(u"Failed to add object to Swift.\n" - "Got error from Swift: %s") % unicode(e)) + "Got error from Swift: %s.") % cutils.exception_to_str(e)) LOG.error(msg) raise glance_store.BackendException(msg) @@ -643,7 +645,8 @@ class BaseStore(driver.Store): connection.put_container(container) except swiftclient.ClientException as e: msg = (_("Failed to add container to Swift.\n" - "Got error from Swift: %(e)s") % {'e': e}) + "Got error from Swift: %s.") % + cutils.exception_to_str(e)) raise glance_store.BackendException(msg) else: msg = (_("The container %(container)s does not exist in " diff --git a/glance_store/backend.py b/glance_store/backend.py index 4c96d1d3..2bf72e0e 100644 --- a/glance_store/backend.py +++ b/glance_store/backend.py @@ -20,6 +20,7 @@ from oslo.config import cfg from stevedore import driver from stevedore import extension +from glance_store.common import utils from glance_store import exceptions from glance_store import i18n from glance_store import location @@ -173,7 +174,7 @@ def _load_stores(conf): yield (store_entry, store_instance) - except exceptions.BadStoreConfiguration as e: + except exceptions.BadStoreConfiguration: continue @@ -301,7 +302,7 @@ def safe_delete_from_backend(uri, image_id, context=None): msg = _('Failed to delete image %s in store from URI') LOG.warn(msg % image_id) except exceptions.StoreDeleteNotSupported as e: - LOG.warn(str(e)) + LOG.warn(utils.exception_to_str(e)) except exceptions.UnsupportedBackend: exc_type = sys.exc_info()[0].__name__ msg = (_('Failed to delete image %(image_id)s ' @@ -361,9 +362,9 @@ def store_add_to_backend(image_id, data, size, store, context=None): except exceptions.BackendException as e: e_msg = (_("A bad metadata structure was returned from the " "%(driver)s storage driver: %(metadata)s. %(e)s.") % - dict(driver=unicode(store), - metadata=unicode(metadata), - e=unicode(e))) + dict(driver=utils.exception_to_str(store), + metadata=utils.exception_to_str(metadata), + e=utils.exception_to_str(e))) LOG.error(e_msg) raise exceptions.BackendException(e_msg) return (location, size, checksum, metadata) diff --git a/glance_store/common/config.py b/glance_store/common/config.py index 17e5b421..7ec38248 100644 --- a/glance_store/common/config.py +++ b/glance_store/common/config.py @@ -26,6 +26,7 @@ from oslo.config import cfg from paste import deploy from glance.version import version_info as version +from glance_store.common import utils paste_deploy_opts = [ cfg.StrOpt('flavor', @@ -213,6 +214,6 @@ def load_paste_app(app_name, flavor=None, conf_file=None): "configuration file %(conf_file)s." "\nGot: %(e)r") % {'app_name': app_name, 'conf_file': conf_file, - 'e': e}) + 'e': utils.exception_to_str(e)}) logger.error(msg) raise RuntimeError(msg) diff --git a/glance_store/common/utils.py b/glance_store/common/utils.py index fb77519b..d240b861 100644 --- a/glance_store/common/utils.py +++ b/glance_store/common/utils.py @@ -25,6 +25,9 @@ try: from eventlet import sleep except ImportError: from time import sleep +import six + +from glance_store.openstack.common import strutils LOG = logging.getLogger(__name__) @@ -137,3 +140,15 @@ class CooperativeReader(object): def __iter__(self): return cooperative_iter(self.fd.__iter__()) + + +def exception_to_str(exc): + try: + error = six.text_type(exc) + except UnicodeError: + try: + error = str(exc) + except UnicodeError: + error = ("Caught '%(exception)s' exception." % + {"exception": exc.__class__.__name__}) + return strutils.safe_encode(error, errors='ignore') diff --git a/glance_store/driver.py b/glance_store/driver.py index ef94eca5..ead02111 100644 --- a/glance_store/driver.py +++ b/glance_store/driver.py @@ -20,26 +20,14 @@ import logging from oslo.config import cfg +from glance_store.common import utils from glance_store import exceptions from glance_store.i18n import _ from glance_store.openstack.common import importutils -from glance_store.openstack.common import strutils LOG = logging.getLogger(__name__) -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 Store(object): OPTIONS = None @@ -79,7 +67,7 @@ class Store(object): self._add = self.add self.add = self.add_disabled msg = (_(u"Failed to configure store correctly: %s " - "Disabling add method.") % _exception_to_unicode(e)) + "Disabling add method.") % utils.exception_to_str(e)) LOG.warn(msg) def get_schemes(self): diff --git a/tests/unit/test_store_base.py b/tests/unit/test_store_base.py index 4fcaf119..8b9c4086 100644 --- a/tests/unit/test_store_base.py +++ b/tests/unit/test_store_base.py @@ -14,8 +14,6 @@ # under the License. import glance_store as store -from glance_store import driver -from glance_store.openstack.common.gettextutils import _ from glance_store.tests import base @@ -25,27 +23,6 @@ class TestStoreBase(base.StoreBaseTest): super(TestStoreBase, self).setUp() self.config(default_store='file', group='glance_store') - def test_exception_to_unicode(self): - class FakeException(Exception): - def __str__(self): - raise UnicodeError() - - exc = Exception('error message') - ret = driver._exception_to_unicode(exc) - self.assertIsInstance(ret, unicode) - self.assertEqual(ret, 'error message') - - exc = Exception('\xa5 error message') - ret = driver._exception_to_unicode(exc) - self.assertIsInstance(ret, unicode) - self.assertEqual(ret, ' error message') - - exc = FakeException('\xa5 error message') - ret = driver._exception_to_unicode(exc) - self.assertIsInstance(ret, unicode) - self.assertEqual(ret, _("Caught '%(exception)s' exception.") % - {'exception': 'FakeException'}) - def test_create_store_exclude_unconfigurable_drivers(self): self.config(stores=["no_conf", "file"], group='glance_store') count = store.create_stores(self.conf) diff --git a/tests/unit/test_swift_store.py b/tests/unit/test_swift_store.py index 09ef4020..f6b47156 100644 --- a/tests/unit/test_swift_store.py +++ b/tests/unit/test_swift_store.py @@ -33,6 +33,7 @@ from glance_store._drivers.swift import utils as sutils from glance_store import backend from glance_store import BackendException from glance_store.common import auth +from glance_store.common import utils from glance_store import exceptions from glance_store.location import get_location_from_uri from glance_store.openstack.common import context @@ -479,7 +480,7 @@ class SwiftTests(object): except BackendException as e: exception_caught = True self.assertIn("container noexist does not exist " - "in Swift", unicode(e)) + "in Swift", utils.exception_to_str(e)) self.assertTrue(exception_caught) self.assertEqual(SWIFT_PUT_OBJECT_CALLS, 0) diff --git a/tests/unit/test_utils.py b/tests/unit/test_utils.py new file mode 100644 index 00000000..f08345e8 --- /dev/null +++ b/tests/unit/test_utils.py @@ -0,0 +1,37 @@ +# Copyright 2014 OpenStack Foundation +# All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +from oslotest import base + +from glance_store.common import utils + + +class TestUtils(base.BaseTestCase): + """Test routines in glance_store.common.utils""" + + def test_exception_to_str(self): + class FakeException(Exception): + def __str__(self): + raise UnicodeError() + + ret = utils.exception_to_str(Exception('error message')) + self.assertEqual(ret, 'error message') + + ret = utils.exception_to_str(Exception('\xa5 error message')) + self.assertEqual(ret, ' error message') + + ret = utils.exception_to_str(FakeException('\xa5 error message')) + self.assertEqual(ret, "Caught '%(exception)s' exception." % + {'exception': 'FakeException'})