diff --git a/.coveragerc b/.coveragerc index 6ebbd47e..3354c0e2 100644 --- a/.coveragerc +++ b/.coveragerc @@ -1,7 +1,7 @@ [run] branch = True source = castellan -omit = castellan/tests/*,castellan/openstack/* +omit = castellan/tests/* [report] ignore_errors = True diff --git a/castellan/common/exception.py b/castellan/common/exception.py index f45db7a4..5f01beaf 100644 --- a/castellan/common/exception.py +++ b/castellan/common/exception.py @@ -19,7 +19,7 @@ Castellan exception subclasses import six.moves.urllib.parse as urlparse -from castellan.openstack.common import _i18n as u +from castellan.i18n import _ _FATAL_EXCEPTION_FORMAT_ERRORS = False @@ -36,7 +36,7 @@ class CastellanException(Exception): a 'message' property. That message will get printf'd with the keyword arguments provided to the constructor. """ - message = u._("An unknown exception occurred") + message = _("An unknown exception occurred") def __init__(self, message_arg=None, *args, **kwargs): if not message_arg: @@ -53,22 +53,22 @@ class CastellanException(Exception): class Forbidden(CastellanException): - message = u._("You are not authorized to complete this action.") + message = _("You are not authorized to complete this action.") class KeyManagerError(CastellanException): - message = u._("Key manager error: %(reason)s") + message = _("Key manager error: %(reason)s") class ManagedObjectNotFoundError(CastellanException): - message = u._("Key not found, uuid: %(uuid)s") + message = _("Key not found, uuid: %(uuid)s") class AuthTypeInvalidError(CastellanException): - message = u._("Invalid auth_type was specified, auth_type: %(type)s") + message = _("Invalid auth_type was specified, auth_type: %(type)s") class InsufficientCredentialDataError(CastellanException): - message = u._("Insufficient credential data was provided, either " - "\"token\" must be set in the passed conf, or a context " - "with an \"auth_token\" property must be passed.") + message = _("Insufficient credential data was provided, either " + "\"token\" must be set in the passed conf, or a context " + "with an \"auth_token\" property must be passed.") diff --git a/castellan/common/utils.py b/castellan/common/utils.py index 7340ea48..746d21ba 100644 --- a/castellan/common/utils.py +++ b/castellan/common/utils.py @@ -21,7 +21,7 @@ from castellan.common.credentials import keystone_token from castellan.common.credentials import password from castellan.common.credentials import token from castellan.common import exception -from castellan.openstack.common import _i18n as u +from castellan.i18n import _LE from oslo_config import cfg from oslo_log import log as logging @@ -164,7 +164,7 @@ def credential_factory(conf=None, context=None): reauthenticate=conf.key_manager.reauthenticate) else: - LOG.error(u._LE("Invalid auth_type specified.")) + LOG.error(_LE("Invalid auth_type specified.")) raise exception.AuthTypeInvalidError( type=conf.key_manager.auth_type) diff --git a/castellan/i18n.py b/castellan/i18n.py new file mode 100644 index 00000000..f2aae30e --- /dev/null +++ b/castellan/i18n.py @@ -0,0 +1,37 @@ +# Copyright 2014 IBM Corp. +# +# 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. + +"""oslo.i18n integration module. + +See http://docs.openstack.org/developer/oslo.i18n/usage.html . + +""" + +import oslo_i18n + + +_translators = oslo_i18n.TranslatorFactory(domain='castellan') + +# The primary translation function using the well-known name "_" +_ = _translators.primary + +# Translators for log levels. +# +# The abbreviated names are meant to reflect the usual use of a short +# name like '_'. The "L" is for "log" and the other letter comes from +# the level. +_LI = _translators.log_info +_LW = _translators.log_warning +_LE = _translators.log_error +_LC = _translators.log_critical diff --git a/castellan/key_manager/barbican_key_manager.py b/castellan/key_manager/barbican_key_manager.py index 4021bc23..3e448221 100644 --- a/castellan/key_manager/barbican_key_manager.py +++ b/castellan/key_manager/barbican_key_manager.py @@ -38,7 +38,7 @@ from castellan.common.objects import public_key as pub_key from castellan.common.objects import symmetric_key as sym_key from castellan.common.objects import x_509 from castellan.key_manager import key_manager -from castellan.openstack.common import _i18n as u +from castellan.i18n import _, _LE, _LI from barbicanclient import client as barbican_client from barbicanclient import exceptions as barbican_exceptions @@ -100,7 +100,7 @@ class BarbicanKeyManager(key_manager.KeyManager): # Confirm context is provided, if not raise forbidden if not context: - msg = u._("User is not authorized to use key manager.") + msg = _LE("User is not authorized to use key manager.") LOG.error(msg) raise exception.Forbidden(msg) @@ -118,7 +118,7 @@ class BarbicanKeyManager(key_manager.KeyManager): self._current_context = context except Exception as e: - LOG.error(u._LE("Error creating Barbican client: %s"), e) + LOG.error(_LE("Error creating Barbican client: %s"), e) raise exception.KeyManagerError(reason=e) self._base_url = self._create_base_url(auth, @@ -166,7 +166,7 @@ class BarbicanKeyManager(key_manager.KeyManager): token=context.auth_token, project_id=context.tenant) else: - msg = u._("context must be of type KeystonePassword, " + msg = _LE("context must be of type KeystonePassword, " "KeystoneToken, or RequestContext.") LOG.error(msg) raise exception.Forbidden(reason=msg) @@ -187,7 +187,7 @@ class BarbicanKeyManager(key_manager.KeyManager): discovery = auth.get_discovery(sess, url=endpoint) raw_data = discovery.raw_version_data() if len(raw_data) == 0: - msg = u._LE( + msg = _LE( "Could not find discovery information for %s") % endpoint LOG.error(msg) raise exception.KeyManagerError(reason=msg) @@ -225,7 +225,7 @@ class BarbicanKeyManager(key_manager.KeyManager): except (barbican_exceptions.HTTPAuthError, barbican_exceptions.HTTPClientError, barbican_exceptions.HTTPServerError) as e: - LOG.error(u._LE("Error creating key: %s"), e) + LOG.error(_LE("Error creating key: %s"), e) raise exception.KeyManagerError(reason=e) def create_key_pair(self, context, algorithm, length, @@ -263,7 +263,7 @@ class BarbicanKeyManager(key_manager.KeyManager): except (barbican_exceptions.HTTPAuthError, barbican_exceptions.HTTPClientError, barbican_exceptions.HTTPServerError) as e: - LOG.error(u._LE("Error creating key pair: %s"), e) + LOG.error(_LE("Error creating key pair: %s"), e) raise exception.KeyManagerError(reason=e) def _get_barbican_object(self, barbican_client, managed_object): @@ -342,7 +342,7 @@ class BarbicanKeyManager(key_manager.KeyManager): except (barbican_exceptions.HTTPAuthError, barbican_exceptions.HTTPClientError, barbican_exceptions.HTTPServerError) as e: - LOG.error(u._LE("Error storing object: %s"), e) + LOG.error(_LE("Error storing object: %s"), e) raise exception.KeyManagerError(reason=e) def _create_secret_ref(self, object_id): @@ -352,7 +352,7 @@ class BarbicanKeyManager(key_manager.KeyManager): :return: the URL of the requested secret """ if not object_id: - msg = u._("Key ID is None") + msg = _("Key ID is None") raise exception.KeyManagerError(reason=msg) base_url = self._base_url if base_url[-1] != '/': @@ -376,8 +376,8 @@ class BarbicanKeyManager(key_manager.KeyManager): kwargs = {"status": error_status, "code": order.error_status_code, "reason": order.error_reason} - msg = u._LE("Order is in %(status)s status - status code: " - "%(code)s, status reason: %(reason)s") % kwargs + msg = _LE("Order is in %(status)s status - status code: " + "%(code)s, status reason: %(reason)s") % kwargs LOG.error(msg) raise exception.KeyManagerError(reason=msg) if order.status != active_status: @@ -386,17 +386,17 @@ class BarbicanKeyManager(key_manager.KeyManager): 'status': order.status, 'active': active_status, 'delay': retry_delay} - msg = u._LI("Retry attempt #%(attempt)i out of %(total)i: " - "Order status is '%(status)s'. Waiting for " - "'%(active)s', will retry in %(delay)s " - "seconds") + msg = _LI("Retry attempt #%(attempt)i out of %(total)i: " + "Order status is '%(status)s'. Waiting for " + "'%(active)s', will retry in %(delay)s " + "seconds") LOG.info(msg, kwargs) time.sleep(retry_delay) order = barbican_client.orders.get(order_ref) else: return order - msg = u._LE("Exceeded retries: Failed to find '%(active)s' status " - "within %(num_retries)i retries") % { + msg = _LE("Exceeded retries: Failed to find '%(active)s' status " + "within %(num_retries)i retries") % { 'active': active_status, 'num_retries': number_of_retries} LOG.error(msg) @@ -500,7 +500,7 @@ class BarbicanKeyManager(key_manager.KeyManager): barbican_exceptions.HTTPClientError, barbican_exceptions.HTTPServerError) as e: with excutils.save_and_reraise_exception(): - LOG.error(u._LE("Error getting secret metadata: %s"), e) + LOG.error(_LE("Error getting secret metadata: %s"), e) def _is_secret_not_found_error(self, error): if (isinstance(error, barbican_exceptions.HTTPClientError) and @@ -527,7 +527,7 @@ class BarbicanKeyManager(key_manager.KeyManager): except (barbican_exceptions.HTTPAuthError, barbican_exceptions.HTTPClientError, barbican_exceptions.HTTPServerError) as e: - LOG.error(u._LE("Error retrieving object: %s"), e) + LOG.error(_LE("Error retrieving object: %s"), e) if self._is_secret_not_found_error(e): raise exception.ManagedObjectNotFoundError( uuid=managed_object_id) @@ -551,7 +551,7 @@ class BarbicanKeyManager(key_manager.KeyManager): except (barbican_exceptions.HTTPAuthError, barbican_exceptions.HTTPClientError, barbican_exceptions.HTTPServerError) as e: - LOG.error(u._LE("Error deleting object: %s"), e) + LOG.error(_LE("Error deleting object: %s"), e) if self._is_secret_not_found_error(e): raise exception.ManagedObjectNotFoundError( uuid=managed_object_id) diff --git a/castellan/openstack/__init__.py b/castellan/openstack/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/castellan/openstack/common/__init__.py b/castellan/openstack/common/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/castellan/openstack/common/_i18n.py b/castellan/openstack/common/_i18n.py deleted file mode 100644 index 83f24d42..00000000 --- a/castellan/openstack/common/_i18n.py +++ /dev/null @@ -1,45 +0,0 @@ -# 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. - -"""oslo.i18n integration module. - -See http://docs.openstack.org/developer/oslo.i18n/usage.html - -""" - -try: - import oslo_i18n - - # NOTE(dhellmann): This reference to o-s-l-o will be replaced by the - # application name when this module is synced into the separate - # repository. It is OK to have more than one translation function - # using the same domain, since there will still only be one message - # catalog. - _translators = oslo_i18n.TranslatorFactory(domain='castellan') - - # The primary translation function using the well-known name "_" - _ = _translators.primary - - # Translators for log levels. - # - # The abbreviated names are meant to reflect the usual use of a short - # name like '_'. The "L" is for "log" and the other letter comes from - # the level. - _LI = _translators.log_info - _LW = _translators.log_warning - _LE = _translators.log_error - _LC = _translators.log_critical -except ImportError: - # NOTE(dims): Support for cases where a project wants to use - # code from oslo-incubator, but is not ready to be internationalized - # (like tempest) - _ = _LI = _LW = _LE = _LC = lambda x: x diff --git a/castellan/openstack/common/fileutils.py b/castellan/openstack/common/fileutils.py deleted file mode 100644 index 9097c35d..00000000 --- a/castellan/openstack/common/fileutils.py +++ /dev/null @@ -1,149 +0,0 @@ -# Copyright 2011 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. - -import contextlib -import errno -import logging -import os -import stat -import tempfile - -from oslo_utils import excutils - -LOG = logging.getLogger(__name__) - -_FILE_CACHE = {} -DEFAULT_MODE = stat.S_IRWXU | stat.S_IRWXG | stat.S_IRWXO - - -def ensure_tree(path, mode=DEFAULT_MODE): - """Create a directory (and any ancestor directories required) - - :param path: Directory to create - :param mode: Directory creation permissions - """ - try: - os.makedirs(path, mode) - except OSError as exc: - if exc.errno == errno.EEXIST: - if not os.path.isdir(path): - raise - else: - raise - - -def read_cached_file(filename, force_reload=False): - """Read from a file if it has been modified. - - :param force_reload: Whether to reload the file. - :returns: A tuple with a boolean specifying if the data is fresh - or not. - """ - global _FILE_CACHE - - if force_reload: - delete_cached_file(filename) - - reloaded = False - mtime = os.path.getmtime(filename) - cache_info = _FILE_CACHE.setdefault(filename, {}) - - if not cache_info or mtime > cache_info.get('mtime', 0): - LOG.debug("Reloading cached file %s" % filename) - with open(filename) as fap: - cache_info['data'] = fap.read() - cache_info['mtime'] = mtime - reloaded = True - return (reloaded, cache_info['data']) - - -def delete_cached_file(filename): - """Delete cached file if present. - - :param filename: filename to delete - """ - global _FILE_CACHE - - if filename in _FILE_CACHE: - del _FILE_CACHE[filename] - - -def delete_if_exists(path, remove=os.unlink): - """Delete a file, but ignore file not found error. - - :param path: File to delete - :param remove: Optional function to remove passed path - """ - - try: - remove(path) - except OSError as e: - if e.errno != errno.ENOENT: - raise - - -@contextlib.contextmanager -def remove_path_on_error(path, remove=delete_if_exists): - """Protect code that wants to operate on PATH atomically. - Any exception will cause PATH to be removed. - - :param path: File to work with - :param remove: Optional function to remove passed path - """ - - try: - yield - except Exception: - with excutils.save_and_reraise_exception(): - remove(path) - - -def file_open(*args, **kwargs): - """Open file - - see built-in open() documentation for more details - - Note: The reason this is kept in a separate module is to easily - be able to provide a stub module that doesn't alter system - state at all (for unit tests) - """ - return open(*args, **kwargs) - - -def write_to_tempfile(content, path=None, suffix='', prefix='tmp'): - """Create temporary file or use existing file. - - This util is needed for creating temporary file with - specified content, suffix and prefix. If path is not None, - it will be used for writing content. If the path doesn't - exist it'll be created. - - :param content: content for temporary file. - :param path: same as parameter 'dir' for mkstemp - :param suffix: same as parameter 'suffix' for mkstemp - :param prefix: same as parameter 'prefix' for mkstemp - - For example: it can be used in database tests for creating - configuration files. - """ - if path: - ensure_tree(path) - - (fd, path) = tempfile.mkstemp(suffix=suffix, dir=path, prefix=prefix) - try: - os.write(fd, content) - finally: - os.close(fd) - return path diff --git a/castellan/openstack/common/local.py b/castellan/openstack/common/local.py deleted file mode 100644 index 0819d5b9..00000000 --- a/castellan/openstack/common/local.py +++ /dev/null @@ -1,45 +0,0 @@ -# Copyright 2011 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. - -"""Local storage of variables using weak references""" - -import threading -import weakref - - -class WeakLocal(threading.local): - def __getattribute__(self, attr): - rval = super(WeakLocal, self).__getattribute__(attr) - if rval: - # NOTE(mikal): this bit is confusing. What is stored is a weak - # reference, not the value itself. We therefore need to lookup - # the weak reference and return the inner value here. - rval = rval() - return rval - - def __setattr__(self, attr, value): - value = weakref.ref(value) - return super(WeakLocal, self).__setattr__(attr, value) - - -# NOTE(mikal): the name "store" should be deprecated in the future -store = WeakLocal() - -# A "weak" store uses weak references and allows an object to fall out of scope -# when it falls out of scope in the code that uses the thread local storage. A -# "strong" store will hold a reference to the object so that it never falls out -# of scope. -weak_store = WeakLocal() -strong_store = threading.local() diff --git a/openstack-common.conf b/openstack-common.conf deleted file mode 100644 index fe6de0d5..00000000 --- a/openstack-common.conf +++ /dev/null @@ -1,8 +0,0 @@ -[DEFAULT] - -# The list of modules to copy from oslo-incubator.git -module=log -module=policy - -# The base module to hold the copy of openstack.common -base=castellan diff --git a/requirements.txt b/requirements.txt index 54a64da7..346c7603 100644 --- a/requirements.txt +++ b/requirements.txt @@ -8,5 +8,6 @@ cryptography!=1.3.0,>=1.0 # BSD/Apache-2.0 python-barbicanclient>=4.0.0 # Apache-2.0 oslo.config>=3.14.0 # Apache-2.0 oslo.context>=2.9.0 # Apache-2.0 +oslo.i18n>=2.1.0 # Apache-2.0 oslo.log>=3.11.0 # Apache-2.0 oslo.utils>=3.17.0 # Apache-2.0 diff --git a/tox.ini b/tox.ini index 5b6d4d35..75f28679 100644 --- a/tox.ini +++ b/tox.ini @@ -61,4 +61,7 @@ commands = # H803 skipped on purpose per list discussion. show-source = True -exclude=.venv,.git,.tox,dist,doc,*openstack/common*,*lib/python*,*egg,build +exclude=.venv,.git,.tox,dist,doc,*lib/python*,*egg,build + +[hacking] +import_exceptions = castellan.i18n