1
# Copyright 2012 OpenStack Foundation
4
# Licensed under the Apache License, Version 2.0 (the "License"); you may
5
# not use this file except in compliance with the License. You may obtain
6
# a copy of the License at
8
# http://www.apache.org/licenses/LICENSE-2.0
10
# Unless required by applicable law or agreed to in writing, software
11
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13
# License for the specific language governing permissions and limitations
17
Base utilities to build API operation managers and objects on top of.
29
return True not in (not x for x in iterable)
33
"""Get by object or ID.
35
Abstracts the common pattern of allowing both an object or an object's ID
36
(UUID) as a parameter when dealing with relationships.
40
except AttributeError:
44
class Manager(object):
45
"""Managers interact with a particular type of API.
47
For example servers, flavors and images.
48
It provides CRUD operations for these objects.
52
def __init__(self, api):
55
def _list(self, url, response_key, obj_class=None, body=None):
56
resp, body = self.api.json_request('GET', url)
59
obj_class = self.resource_class
61
data = body[response_key]
62
return [obj_class(self, res, loaded=True) for res in data if res]
64
def _delete(self, url):
65
self.api.raw_request('DELETE', url)
67
def _update(self, url, body, response_key=None):
68
resp, body = self.api.json_request('PUT', url, body=body)
69
# PUT requests may not return a body
71
return self.resource_class(self, body[response_key])
74
class Resource(object):
75
"""A resource represents a particular instance of an object.
77
For example tenant or user. This is pretty much just a bag for attributes.
79
:param manager: Manager object
80
:param info: dictionary representing resource attributes
81
:param loaded: prevent lazy-loading if set to True
83
def __init__(self, manager, info, loaded=False):
84
self.manager = manager
86
self._add_details(info)
89
def _add_details(self, info):
90
for (k, v) in six.iteritems(info):
93
def __getattr__(self, k):
94
if k not in self.__dict__:
95
#NOTE(bcwaldon): disallow lazy-loading if already loaded once
96
if not self.is_loaded():
98
return self.__getattr__(k)
100
raise AttributeError(k)
102
return self.__dict__[k]
105
reprkeys = sorted(k for k in self.__dict__.keys()
106
if k[0] != '_' and k != 'manager')
107
info = ", ".join("%s=%s" % (k, getattr(self, k)) for k in reprkeys)
108
return "<%s %s>" % (self.__class__.__name__, info)
111
# set_loaded() first ... so if we have to bail, we know we tried.
112
self.set_loaded(True)
113
if not hasattr(self.manager, 'get'):
116
new = self.manager.get(self.id)
118
self._add_details(new._info)
120
def __eq__(self, other):
121
if not isinstance(other, self.__class__):
123
if hasattr(self, 'id') and hasattr(other, 'id'):
124
return self.id == other.id
125
return self._info == other._info
130
def set_loaded(self, val):
134
return copy.deepcopy(self._info)