sync to latest oslo-incubator code
This patch also syncs with latest oslo-incubator, to solve bug 1354470 and safe log auth token when --debug is enabled, see https://github.com/openstack/oslo-incubator/blob/master/openstack/common/apiclient/client.py#L128 Note, this patch also removes importutils.py since it is no longer used. Change-Id: I4f2d18ef05c3be27cf2ee3474761408e3f5ccbcd Closes-Bug: #1354470
This commit is contained in:
		@@ -40,6 +40,6 @@ try:
 | 
				
			|||||||
    _LC = _translators.log_critical
 | 
					    _LC = _translators.log_critical
 | 
				
			||||||
except ImportError:
 | 
					except ImportError:
 | 
				
			||||||
    # NOTE(dims): Support for cases where a project wants to use
 | 
					    # NOTE(dims): Support for cases where a project wants to use
 | 
				
			||||||
    # code from ceilometerclient-incubator, but is not ready to be internationalized
 | 
					    # code from oslo-incubator, but is not ready to be internationalized
 | 
				
			||||||
    # (like tempest)
 | 
					    # (like tempest)
 | 
				
			||||||
    _ = _LI = _LW = _LE = _LC = lambda x: x
 | 
					    _ = _LI = _LW = _LE = _LC = lambda x: x
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -17,6 +17,19 @@
 | 
				
			|||||||
# E0202: An attribute inherited from %s hide this method
 | 
					# E0202: An attribute inherited from %s hide this method
 | 
				
			||||||
# pylint: disable=E0202
 | 
					# pylint: disable=E0202
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					########################################################################
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# THIS MODULE IS DEPRECATED
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Please refer to
 | 
				
			||||||
 | 
					# https://etherpad.openstack.org/p/kilo-ceilometerclient-library-proposals for
 | 
				
			||||||
 | 
					# the discussion leading to this deprecation.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# We recommend checking out the python-openstacksdk project
 | 
				
			||||||
 | 
					# (https://launchpad.net/python-openstacksdk) instead.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					########################################################################
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import abc
 | 
					import abc
 | 
				
			||||||
import argparse
 | 
					import argparse
 | 
				
			||||||
import os
 | 
					import os
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -20,6 +20,20 @@
 | 
				
			|||||||
Base utilities to build API operation managers and objects on top of.
 | 
					Base utilities to build API operation managers and objects on top of.
 | 
				
			||||||
"""
 | 
					"""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					########################################################################
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# THIS MODULE IS DEPRECATED
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Please refer to
 | 
				
			||||||
 | 
					# https://etherpad.openstack.org/p/kilo-ceilometerclient-library-proposals for
 | 
				
			||||||
 | 
					# the discussion leading to this deprecation.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# We recommend checking out the python-openstacksdk project
 | 
				
			||||||
 | 
					# (https://launchpad.net/python-openstacksdk) instead.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					########################################################################
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# E1102: %s is not callable
 | 
					# E1102: %s is not callable
 | 
				
			||||||
# pylint: disable=E1102
 | 
					# pylint: disable=E1102
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -495,6 +509,8 @@ class Resource(object):
 | 
				
			|||||||
        new = self.manager.get(self.id)
 | 
					        new = self.manager.get(self.id)
 | 
				
			||||||
        if new:
 | 
					        if new:
 | 
				
			||||||
            self._add_details(new._info)
 | 
					            self._add_details(new._info)
 | 
				
			||||||
 | 
					            self._add_details(
 | 
				
			||||||
 | 
					                {'x_request_id': self.manager.client.last_request_id})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __eq__(self, other):
 | 
					    def __eq__(self, other):
 | 
				
			||||||
        if not isinstance(other, Resource):
 | 
					        if not isinstance(other, Resource):
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -25,6 +25,7 @@ OpenStack Client interface. Handles the REST calls and responses.
 | 
				
			|||||||
# E0202: An attribute inherited from %s hide this method
 | 
					# E0202: An attribute inherited from %s hide this method
 | 
				
			||||||
# pylint: disable=E0202
 | 
					# pylint: disable=E0202
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import hashlib
 | 
				
			||||||
import logging
 | 
					import logging
 | 
				
			||||||
import time
 | 
					import time
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -33,14 +34,15 @@ try:
 | 
				
			|||||||
except ImportError:
 | 
					except ImportError:
 | 
				
			||||||
    import json
 | 
					    import json
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from oslo.utils import encodeutils
 | 
				
			||||||
from oslo.utils import importutils
 | 
					from oslo.utils import importutils
 | 
				
			||||||
import requests
 | 
					import requests
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from ceilometerclient.openstack.common._i18n import _
 | 
					from ceilometerclient.openstack.common._i18n import _
 | 
				
			||||||
from ceilometerclient.openstack.common.apiclient import exceptions
 | 
					from ceilometerclient.openstack.common.apiclient import exceptions
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
_logger = logging.getLogger(__name__)
 | 
					_logger = logging.getLogger(__name__)
 | 
				
			||||||
 | 
					SENSITIVE_HEADERS = ('X-Auth-Token', 'X-Subject-Token',)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class HTTPClient(object):
 | 
					class HTTPClient(object):
 | 
				
			||||||
@@ -98,19 +100,32 @@ class HTTPClient(object):
 | 
				
			|||||||
        self.http = http or requests.Session()
 | 
					        self.http = http or requests.Session()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.cached_token = None
 | 
					        self.cached_token = None
 | 
				
			||||||
 | 
					        self.last_request_id = None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def _safe_header(self, name, value):
 | 
				
			||||||
 | 
					        if name in SENSITIVE_HEADERS:
 | 
				
			||||||
 | 
					            # because in python3 byte string handling is ... ug
 | 
				
			||||||
 | 
					            v = value.encode('utf-8')
 | 
				
			||||||
 | 
					            h = hashlib.sha1(v)
 | 
				
			||||||
 | 
					            d = h.hexdigest()
 | 
				
			||||||
 | 
					            return encodeutils.safe_decode(name), "{SHA1}%s" % d
 | 
				
			||||||
 | 
					        else:
 | 
				
			||||||
 | 
					            return (encodeutils.safe_decode(name),
 | 
				
			||||||
 | 
					                    encodeutils.safe_decode(value))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def _http_log_req(self, method, url, kwargs):
 | 
					    def _http_log_req(self, method, url, kwargs):
 | 
				
			||||||
        if not self.debug:
 | 
					        if not self.debug:
 | 
				
			||||||
            return
 | 
					            return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        string_parts = [
 | 
					        string_parts = [
 | 
				
			||||||
            "curl -i",
 | 
					            "curl -g -i",
 | 
				
			||||||
            "-X '%s'" % method,
 | 
					            "-X '%s'" % method,
 | 
				
			||||||
            "'%s'" % url,
 | 
					            "'%s'" % url,
 | 
				
			||||||
        ]
 | 
					        ]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        for element in kwargs['headers']:
 | 
					        for element in kwargs['headers']:
 | 
				
			||||||
            header = "-H '%s: %s'" % (element, kwargs['headers'][element])
 | 
					            header = ("-H '%s: %s'" %
 | 
				
			||||||
 | 
					                      self._safe_header(element, kwargs['headers'][element]))
 | 
				
			||||||
            string_parts.append(header)
 | 
					            string_parts.append(header)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        _logger.debug("REQ: %s" % " ".join(string_parts))
 | 
					        _logger.debug("REQ: %s" % " ".join(string_parts))
 | 
				
			||||||
@@ -177,6 +192,8 @@ class HTTPClient(object):
 | 
				
			|||||||
                               start_time, time.time()))
 | 
					                               start_time, time.time()))
 | 
				
			||||||
        self._http_log_resp(resp)
 | 
					        self._http_log_resp(resp)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.last_request_id = resp.headers.get('x-openstack-request-id')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if resp.status_code >= 400:
 | 
					        if resp.status_code >= 400:
 | 
				
			||||||
            _logger.debug(
 | 
					            _logger.debug(
 | 
				
			||||||
                "Request returned failure status: %s",
 | 
					                "Request returned failure status: %s",
 | 
				
			||||||
@@ -327,6 +344,10 @@ class BaseClient(object):
 | 
				
			|||||||
        return self.http_client.client_request(
 | 
					        return self.http_client.client_request(
 | 
				
			||||||
            self, method, url, **kwargs)
 | 
					            self, method, url, **kwargs)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @property
 | 
				
			||||||
 | 
					    def last_request_id(self):
 | 
				
			||||||
 | 
					        return self.http_client.last_request_id
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def head(self, url, **kwargs):
 | 
					    def head(self, url, **kwargs):
 | 
				
			||||||
        return self.client_request("HEAD", url, **kwargs)
 | 
					        return self.client_request("HEAD", url, **kwargs)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -20,6 +20,19 @@
 | 
				
			|||||||
Exception definitions.
 | 
					Exception definitions.
 | 
				
			||||||
"""
 | 
					"""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					########################################################################
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# THIS MODULE IS DEPRECATED
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Please refer to
 | 
				
			||||||
 | 
					# https://etherpad.openstack.org/p/kilo-ceilometerclient-library-proposals for
 | 
				
			||||||
 | 
					# the discussion leading to this deprecation.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# We recommend checking out the python-openstacksdk project
 | 
				
			||||||
 | 
					# (https://launchpad.net/python-openstacksdk) instead.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					########################################################################
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import inspect
 | 
					import inspect
 | 
				
			||||||
import sys
 | 
					import sys
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -34,14 +47,6 @@ class ClientException(Exception):
 | 
				
			|||||||
    pass
 | 
					    pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class MissingArgs(ClientException):
 | 
					 | 
				
			||||||
    """Supplied arguments are not sufficient for calling a function."""
 | 
					 | 
				
			||||||
    def __init__(self, missing):
 | 
					 | 
				
			||||||
        self.missing = missing
 | 
					 | 
				
			||||||
        msg = _("Missing arguments: %s") % ", ".join(missing)
 | 
					 | 
				
			||||||
        super(MissingArgs, self).__init__(msg)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class ValidationError(ClientException):
 | 
					class ValidationError(ClientException):
 | 
				
			||||||
    """Error in validation on API client side."""
 | 
					    """Error in validation on API client side."""
 | 
				
			||||||
    pass
 | 
					    pass
 | 
				
			||||||
@@ -62,11 +67,16 @@ class AuthorizationFailure(ClientException):
 | 
				
			|||||||
    pass
 | 
					    pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class ConnectionRefused(ClientException):
 | 
					class ConnectionError(ClientException):
 | 
				
			||||||
    """Cannot connect to API service."""
 | 
					    """Cannot connect to API service."""
 | 
				
			||||||
    pass
 | 
					    pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class ConnectionRefused(ConnectionError):
 | 
				
			||||||
 | 
					    """Connection refused while trying to connect to API service."""
 | 
				
			||||||
 | 
					    pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class AuthPluginOptionsMissing(AuthorizationFailure):
 | 
					class AuthPluginOptionsMissing(AuthorizationFailure):
 | 
				
			||||||
    """Auth plugin misses some options."""
 | 
					    """Auth plugin misses some options."""
 | 
				
			||||||
    def __init__(self, opt_names):
 | 
					    def __init__(self, opt_names):
 | 
				
			||||||
@@ -447,10 +457,13 @@ def from_response(response, method, url):
 | 
				
			|||||||
        except ValueError:
 | 
					        except ValueError:
 | 
				
			||||||
            pass
 | 
					            pass
 | 
				
			||||||
        else:
 | 
					        else:
 | 
				
			||||||
            if isinstance(body, dict) and isinstance(body.get("error"), dict):
 | 
					            if isinstance(body, dict):
 | 
				
			||||||
                error = body["error"]
 | 
					                error = body.get(list(body)[0])
 | 
				
			||||||
                kwargs["message"] = error.get("message")
 | 
					                if isinstance(error, dict):
 | 
				
			||||||
                kwargs["details"] = error.get("details")
 | 
					                    kwargs["message"] = (error.get("message") or
 | 
				
			||||||
 | 
					                                         error.get("faultstring"))
 | 
				
			||||||
 | 
					                    kwargs["details"] = (error.get("details") or
 | 
				
			||||||
 | 
					                                         six.text_type(body))
 | 
				
			||||||
    elif content_type.startswith("text/"):
 | 
					    elif content_type.startswith("text/"):
 | 
				
			||||||
        kwargs["details"] = response.text
 | 
					        kwargs["details"] = response.text
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -21,6 +21,19 @@ wrong the tests might raise AssertionError. I've indicated in comments the
 | 
				
			|||||||
places where actual behavior differs from the spec.
 | 
					places where actual behavior differs from the spec.
 | 
				
			||||||
"""
 | 
					"""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					########################################################################
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# THIS MODULE IS DEPRECATED
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Please refer to
 | 
				
			||||||
 | 
					# https://etherpad.openstack.org/p/kilo-ceilometerclient-library-proposals for
 | 
				
			||||||
 | 
					# the discussion leading to this deprecation.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# We recommend checking out the python-openstacksdk project
 | 
				
			||||||
 | 
					# (https://launchpad.net/python-openstacksdk) instead.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					########################################################################
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# W0102: Dangerous default value %s as argument
 | 
					# W0102: Dangerous default value %s as argument
 | 
				
			||||||
# pylint: disable=W0102
 | 
					# pylint: disable=W0102
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -168,6 +181,8 @@ class FakeHTTPClient(client.HTTPClient):
 | 
				
			|||||||
        else:
 | 
					        else:
 | 
				
			||||||
            status, body = resp
 | 
					            status, body = resp
 | 
				
			||||||
            headers = {}
 | 
					            headers = {}
 | 
				
			||||||
 | 
					        self.last_request_id = headers.get('x-openstack-request-id',
 | 
				
			||||||
 | 
					                                           'req-test')
 | 
				
			||||||
        return TestResponse({
 | 
					        return TestResponse({
 | 
				
			||||||
            "status_code": status,
 | 
					            "status_code": status,
 | 
				
			||||||
            "text": body,
 | 
					            "text": body,
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										100
									
								
								ceilometerclient/openstack/common/apiclient/utils.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										100
									
								
								ceilometerclient/openstack/common/apiclient/utils.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,100 @@
 | 
				
			|||||||
 | 
					#
 | 
				
			||||||
 | 
					#    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.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					########################################################################
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# THIS MODULE IS DEPRECATED
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Please refer to
 | 
				
			||||||
 | 
					# https://etherpad.openstack.org/p/kilo-ceilometerclient-library-proposals for
 | 
				
			||||||
 | 
					# the discussion leading to this deprecation.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# We recommend checking out the python-openstacksdk project
 | 
				
			||||||
 | 
					# (https://launchpad.net/python-openstacksdk) instead.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					########################################################################
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from oslo.utils import encodeutils
 | 
				
			||||||
 | 
					import six
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from ceilometerclient.openstack.common._i18n import _
 | 
				
			||||||
 | 
					from ceilometerclient.openstack.common.apiclient import exceptions
 | 
				
			||||||
 | 
					from ceilometerclient.openstack.common import uuidutils
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def find_resource(manager, name_or_id, **find_args):
 | 
				
			||||||
 | 
					    """Look for resource in a given manager.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Used as a helper for the _find_* methods.
 | 
				
			||||||
 | 
					    Example:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    .. code-block:: python
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        def _find_hypervisor(cs, hypervisor):
 | 
				
			||||||
 | 
					            #Get a hypervisor by name or ID.
 | 
				
			||||||
 | 
					            return cliutils.find_resource(cs.hypervisors, hypervisor)
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    # first try to get entity as integer id
 | 
				
			||||||
 | 
					    try:
 | 
				
			||||||
 | 
					        return manager.get(int(name_or_id))
 | 
				
			||||||
 | 
					    except (TypeError, ValueError, exceptions.NotFound):
 | 
				
			||||||
 | 
					        pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # now try to get entity as uuid
 | 
				
			||||||
 | 
					    try:
 | 
				
			||||||
 | 
					        if six.PY2:
 | 
				
			||||||
 | 
					            tmp_id = encodeutils.safe_encode(name_or_id)
 | 
				
			||||||
 | 
					        else:
 | 
				
			||||||
 | 
					            tmp_id = encodeutils.safe_decode(name_or_id)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if uuidutils.is_uuid_like(tmp_id):
 | 
				
			||||||
 | 
					            return manager.get(tmp_id)
 | 
				
			||||||
 | 
					    except (TypeError, ValueError, exceptions.NotFound):
 | 
				
			||||||
 | 
					        pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # for str id which is not uuid
 | 
				
			||||||
 | 
					    if getattr(manager, 'is_alphanum_id_allowed', False):
 | 
				
			||||||
 | 
					        try:
 | 
				
			||||||
 | 
					            return manager.get(name_or_id)
 | 
				
			||||||
 | 
					        except exceptions.NotFound:
 | 
				
			||||||
 | 
					            pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    try:
 | 
				
			||||||
 | 
					        try:
 | 
				
			||||||
 | 
					            return manager.find(human_id=name_or_id, **find_args)
 | 
				
			||||||
 | 
					        except exceptions.NotFound:
 | 
				
			||||||
 | 
					            pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # finally try to find entity by name
 | 
				
			||||||
 | 
					        try:
 | 
				
			||||||
 | 
					            resource = getattr(manager, 'resource_class', None)
 | 
				
			||||||
 | 
					            name_attr = resource.NAME_ATTR if resource else 'name'
 | 
				
			||||||
 | 
					            kwargs = {name_attr: name_or_id}
 | 
				
			||||||
 | 
					            kwargs.update(find_args)
 | 
				
			||||||
 | 
					            return manager.find(**kwargs)
 | 
				
			||||||
 | 
					        except exceptions.NotFound:
 | 
				
			||||||
 | 
					            msg = _("No %(name)s with a name or "
 | 
				
			||||||
 | 
					                    "ID of '%(name_or_id)s' exists.") % \
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    "name": manager.resource_class.__name__.lower(),
 | 
				
			||||||
 | 
					                    "name_or_id": name_or_id
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            raise exceptions.CommandError(msg)
 | 
				
			||||||
 | 
					    except exceptions.NoUniqueMatch:
 | 
				
			||||||
 | 
					        msg = _("Multiple %(name)s matches found for "
 | 
				
			||||||
 | 
					                "'%(name_or_id)s', use an ID to be more specific.") % \
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                "name": manager.resource_class.__name__.lower(),
 | 
				
			||||||
 | 
					                "name_or_id": name_or_id
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        raise exceptions.CommandError(msg)
 | 
				
			||||||
@@ -1,73 +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 related utilities and helper functions.
 | 
					 | 
				
			||||||
"""
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import sys
 | 
					 | 
				
			||||||
import traceback
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def import_class(import_str):
 | 
					 | 
				
			||||||
    """Returns a class from a string including module and class."""
 | 
					 | 
				
			||||||
    mod_str, _sep, class_str = import_str.rpartition('.')
 | 
					 | 
				
			||||||
    __import__(mod_str)
 | 
					 | 
				
			||||||
    try:
 | 
					 | 
				
			||||||
        return getattr(sys.modules[mod_str], class_str)
 | 
					 | 
				
			||||||
    except AttributeError:
 | 
					 | 
				
			||||||
        raise ImportError('Class %s cannot be found (%s)' %
 | 
					 | 
				
			||||||
                          (class_str,
 | 
					 | 
				
			||||||
                           traceback.format_exception(*sys.exc_info())))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def import_object(import_str, *args, **kwargs):
 | 
					 | 
				
			||||||
    """Import a class and return an instance of it."""
 | 
					 | 
				
			||||||
    return import_class(import_str)(*args, **kwargs)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def import_object_ns(name_space, import_str, *args, **kwargs):
 | 
					 | 
				
			||||||
    """Tries to import object from default namespace.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    Imports a class and return an instance of it, first by trying
 | 
					 | 
				
			||||||
    to find the class in a default namespace, then failing back to
 | 
					 | 
				
			||||||
    a full path if not found in the default namespace.
 | 
					 | 
				
			||||||
    """
 | 
					 | 
				
			||||||
    import_value = "%s.%s" % (name_space, import_str)
 | 
					 | 
				
			||||||
    try:
 | 
					 | 
				
			||||||
        return import_class(import_value)(*args, **kwargs)
 | 
					 | 
				
			||||||
    except ImportError:
 | 
					 | 
				
			||||||
        return import_class(import_str)(*args, **kwargs)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def import_module(import_str):
 | 
					 | 
				
			||||||
    """Import a module."""
 | 
					 | 
				
			||||||
    __import__(import_str)
 | 
					 | 
				
			||||||
    return sys.modules[import_str]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def import_versioned_module(version, submodule=None):
 | 
					 | 
				
			||||||
    module = 'ceilometerclient.v%s' % version
 | 
					 | 
				
			||||||
    if submodule:
 | 
					 | 
				
			||||||
        module = '.'.join((module, submodule))
 | 
					 | 
				
			||||||
    return import_module(module)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def try_import(import_str, default=None):
 | 
					 | 
				
			||||||
    """Try to import a module and if it fails return default."""
 | 
					 | 
				
			||||||
    try:
 | 
					 | 
				
			||||||
        return import_module(import_str)
 | 
					 | 
				
			||||||
    except ImportError:
 | 
					 | 
				
			||||||
        return default
 | 
					 | 
				
			||||||
		Reference in New Issue
	
	Block a user