summaryrefslogtreecommitdiff
path: root/ceilometerclient/openstack/common/apiclient/base.py
diff options
context:
space:
mode:
Diffstat (limited to 'ceilometerclient/openstack/common/apiclient/base.py')
-rw-r--r--ceilometerclient/openstack/common/apiclient/base.py63
1 files changed, 44 insertions, 19 deletions
diff --git a/ceilometerclient/openstack/common/apiclient/base.py b/ceilometerclient/openstack/common/apiclient/base.py
index f8531f8..b5394f8 100644
--- a/ceilometerclient/openstack/common/apiclient/base.py
+++ b/ceilometerclient/openstack/common/apiclient/base.py
@@ -24,11 +24,13 @@ Base utilities to build API operation managers and objects on top of.
# pylint: disable=E1102
import abc
+import copy
import six
from six.moves.urllib import parse
from ceilometerclient.openstack.common.apiclient import exceptions
+from ceilometerclient.openstack.common.gettextutils import _
from ceilometerclient.openstack.common import strutils
@@ -73,8 +75,8 @@ class HookableMixin(object):
:param cls: class that registers hooks
:param hook_type: hook type, e.g., '__pre_parse_args__'
- :param **args: args to be passed to every hook function
- :param **kwargs: kwargs to be passed to every hook function
+ :param args: args to be passed to every hook function
+ :param kwargs: kwargs to be passed to every hook function
"""
hook_funcs = cls._hooks_map.get(hook_type) or []
for hook_func in hook_funcs:
@@ -97,12 +99,13 @@ class BaseManager(HookableMixin):
super(BaseManager, self).__init__()
self.client = client
- def _list(self, url, response_key, obj_class=None, json=None):
+ def _list(self, url, response_key=None, obj_class=None, json=None):
"""List the collection.
:param url: a partial URL, e.g., '/servers'
:param response_key: the key to be looked up in response dictionary,
- e.g., 'servers'
+ e.g., 'servers'. If response_key is None - all response body
+ will be used.
:param obj_class: class for constructing the returned objects
(self.resource_class will be used by default)
:param json: data that will be encoded as JSON and passed in POST
@@ -116,7 +119,7 @@ class BaseManager(HookableMixin):
if obj_class is None:
obj_class = self.resource_class
- data = body[response_key]
+ data = body[response_key] if response_key is not None else body
# NOTE(ja): keystone returns values as list as {'values': [ ... ]}
# unlike other services which just return the list...
try:
@@ -126,15 +129,17 @@ class BaseManager(HookableMixin):
return [obj_class(self, res, loaded=True) for res in data if res]
- def _get(self, url, response_key):
+ def _get(self, url, response_key=None):
"""Get an object from collection.
:param url: a partial URL, e.g., '/servers'
:param response_key: the key to be looked up in response dictionary,
- e.g., 'server'
+ e.g., 'server'. If response_key is None - all response body
+ will be used.
"""
body = self.client.get(url).json()
- return self.resource_class(self, body[response_key], loaded=True)
+ data = body[response_key] if response_key is not None else body
+ return self.resource_class(self, data, loaded=True)
def _head(self, url):
"""Retrieve request headers for an object.
@@ -144,21 +149,23 @@ class BaseManager(HookableMixin):
resp = self.client.head(url)
return resp.status_code == 204
- def _post(self, url, json, response_key, return_raw=False):
+ def _post(self, url, json, response_key=None, return_raw=False):
"""Create an object.
:param url: a partial URL, e.g., '/servers'
:param json: data that will be encoded as JSON and passed in POST
request (GET will be sent by default)
:param response_key: the key to be looked up in response dictionary,
- e.g., 'servers'
+ e.g., 'server'. If response_key is None - all response body
+ will be used.
:param return_raw: flag to force returning raw JSON instead of
Python object of self.resource_class
"""
body = self.client.post(url, json=json).json()
+ data = body[response_key] if response_key is not None else body
if return_raw:
- return body[response_key]
- return self.resource_class(self, body[response_key])
+ return data
+ return self.resource_class(self, data)
def _put(self, url, json=None, response_key=None):
"""Update an object with PUT method.
@@ -167,7 +174,8 @@ class BaseManager(HookableMixin):
:param json: data that will be encoded as JSON and passed in POST
request (GET will be sent by default)
:param response_key: the key to be looked up in response dictionary,
- e.g., 'servers'
+ e.g., 'servers'. If response_key is None - all response body
+ will be used.
"""
resp = self.client.put(url, json=json)
# PUT requests may not return a body
@@ -185,7 +193,8 @@ class BaseManager(HookableMixin):
:param json: data that will be encoded as JSON and passed in POST
request (GET will be sent by default)
:param response_key: the key to be looked up in response dictionary,
- e.g., 'servers'
+ e.g., 'servers'. If response_key is None - all response body
+ will be used.
"""
body = self.client.patch(url, json=json).json()
if response_key is not None:
@@ -218,7 +227,10 @@ class ManagerWithFind(BaseManager):
matches = self.findall(**kwargs)
num_matches = len(matches)
if num_matches == 0:
- msg = "No %s matching %s." % (self.resource_class.__name__, kwargs)
+ msg = _("No %(name)s matching %(args)s.") % {
+ 'name': self.resource_class.__name__,
+ 'args': kwargs
+ }
raise exceptions.NotFound(msg)
elif num_matches > 1:
raise exceptions.NoUniqueMatch()
@@ -372,7 +384,10 @@ class CrudManager(BaseManager):
num = len(rl)
if num == 0:
- msg = "No %s matching %s." % (self.resource_class.__name__, kwargs)
+ msg = _("No %(name)s matching %(args)s.") % {
+ 'name': self.resource_class.__name__,
+ 'args': kwargs
+ }
raise exceptions.NotFound(404, msg)
elif num > 1:
raise exceptions.NoUniqueMatch
@@ -440,8 +455,10 @@ class Resource(object):
def human_id(self):
"""Human-readable ID which can be used for bash completion.
"""
- if self.NAME_ATTR in self.__dict__ and self.HUMAN_ID:
- return strutils.to_slug(getattr(self, self.NAME_ATTR))
+ if self.HUMAN_ID:
+ name = getattr(self, self.NAME_ATTR, None)
+ if name is not None:
+ return strutils.to_slug(name)
return None
def _add_details(self, info):
@@ -455,7 +472,7 @@ class Resource(object):
def __getattr__(self, k):
if k not in self.__dict__:
- #NOTE(bcwaldon): disallow lazy-loading if already loaded once
+ # NOTE(bcwaldon): disallow lazy-loading if already loaded once
if not self.is_loaded():
self.get()
return self.__getattr__(k)
@@ -465,6 +482,11 @@ class Resource(object):
return self.__dict__[k]
def get(self):
+ """Support for lazy loading details.
+
+ Some clients, such as novaclient have the option to lazy load the
+ details, details which can be loaded with this function.
+ """
# set_loaded() first ... so if we have to bail, we know we tried.
self.set_loaded(True)
if not hasattr(self.manager, 'get'):
@@ -489,3 +511,6 @@ class Resource(object):
def set_loaded(self, val):
self._loaded = val
+
+ def to_dict(self):
+ return copy.deepcopy(self._info)