Files
python-cloudkittyclient/cloudkittyclient/common/base.py
Aaron-DH 5c188a2306 Fix name not defined error
Add the missing import packages and format the log messages
Move i18n to package(cloudkittyclient)

Change-Id: I77e7059e8eb91aef131713f0720f58d23ae7c11f
Closes-Bug: #1524680
2016-01-02 20:55:12 +08:00

175 lines
4.9 KiB
Python

# Copyright 2012 OpenStack Foundation
# Copyright 2015 Objectif Libre
# 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.
"""
Base utilities to build API operation managers and objects on top of.
"""
import copy
from six.moves.urllib import parse
from cloudkittyclient import exc
from cloudkittyclient.i18n import _
from cloudkittyclient.openstack.common.apiclient import base
def getid(obj):
"""Extracts object ID.
Abstracts the common pattern of allowing both an object or an
object's ID (UUID) as a parameter when dealing with relationships.
"""
try:
return obj.id
except AttributeError:
return obj
class Manager(object):
"""Managers interact with a particular type of API.
It works with samples, meters, alarms, etc. and provide CRUD operations for
them.
"""
resource_class = None
def __init__(self, api):
self.api = api
@property
def client(self):
"""Compatible with latest oslo-incubator.apiclient code."""
return self.api
def _create(self, url, body):
body = self.api.post(url, json=body).json()
if body:
return self.resource_class(self, body)
def _list(self, url, response_key=None, obj_class=None, body=None,
expect_single=False):
resp = self.api.get(url)
if not resp.content:
raise exc.HTTPNotFound
body = resp.json()
if obj_class is None:
obj_class = self.resource_class
if response_key:
try:
data = body[response_key]
except KeyError:
return []
else:
data = body
if expect_single:
data = [data]
return [obj_class(self, res, loaded=True) for res in data if res]
def _update(self, url, item, response_key=None):
if not item.dirty_fields:
return item
item = self.api.put(url, json=item.dirty_fields).json()
# PUT requests may not return a item
if item:
return self.resource_class(self, item)
def _delete(self, url):
self.api.delete(url)
class CrudManager(base.CrudManager):
"""A CrudManager that automatically gets its base URL."""
base_url = None
def build_url(self, base_url=None, **kwargs):
base_url = base_url or self.base_url
return super(CrudManager, self).build_url(base_url, **kwargs)
def get(self, **kwargs):
kwargs = self._filter_kwargs(kwargs)
return self._get(
self.build_url(**kwargs))
def create(self, **kwargs):
kwargs = self._filter_kwargs(kwargs)
return self._post(
self.build_url(**kwargs), kwargs)
def update(self, **kwargs):
kwargs = self._filter_kwargs(kwargs)
params = kwargs.copy()
return self._put(
self.build_url(**kwargs), params)
def findall(self, base_url=None, **kwargs):
"""Find multiple items with attributes matching ``**kwargs``.
:param base_url: if provided, the generated URL will be appended to it
"""
kwargs = self._filter_kwargs(kwargs)
rl = self._list(
'%(base_url)s%(query)s' % {
'base_url': self.build_url(base_url=base_url, **kwargs),
'query': '?%s' % parse.urlencode(kwargs) if kwargs else '',
},
self.collection_key)
num = len(rl)
if num == 0:
msg = _("No %(name)s matching %(args)s.") % {
'name': self.resource_class.__name__,
'args': kwargs
}
raise exc.HTTPNotFound(msg)
return rl
class Resource(base.Resource):
"""A resource represents a particular instance of an object.
Resource might be tenant, user, etc.
This is pretty much just a bag for attributes.
:param manager: Manager object
:param info: dictionary representing resource attributes
:param loaded: prevent lazy-loading if set to True
"""
key = None
def to_dict(self):
return copy.deepcopy(self._info)
@property
def dirty_fields(self):
out = self.to_dict()
for k, v in self._info.items():
if self.__dict__[k] != v:
out[k] = self.__dict__[k]
return out
def update(self):
try:
return self.manager.update(**self.dirty_fields)
except AttributeError:
raise exc.NotUpdatableError(self)