summaryrefslogtreecommitdiff
path: root/heatclient/common/base.py
diff options
context:
space:
mode:
authorSteve Baker <sbaker@redhat.com>2012-10-10 08:55:03 +1300
committerSteve Baker <sbaker@redhat.com>2012-10-10 08:55:03 +1300
commit1269bb20c770ca9869f54da9e1db9af7173b9809 (patch)
tree2f66d6bb8078a1e765b3215e3a93b7a3e5fa44e4 /heatclient/common/base.py
downloadpython-heatclient-1269bb20c770ca9869f54da9e1db9af7173b9809.tar.gz
Initial import
Diffstat (limited to 'heatclient/common/base.py')
-rw-r--r--heatclient/common/base.py131
1 files changed, 131 insertions, 0 deletions
diff --git a/heatclient/common/base.py b/heatclient/common/base.py
new file mode 100644
index 0000000..3cedd32
--- /dev/null
+++ b/heatclient/common/base.py
@@ -0,0 +1,131 @@
+# Copyright 2012 OpenStack LLC.
+# 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
+
+
+# Python 2.4 compat
+try:
+ all
+except NameError:
+ def all(iterable):
+ return True not in (not x for x in iterable)
+
+
+def getid(obj):
+ """
+ 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 (servers, flavors, images,
+ etc.) and provide CRUD operations for them.
+ """
+ resource_class = None
+
+ def __init__(self, api):
+ self.api = api
+
+ def _list(self, url, response_key, obj_class=None, body=None):
+ resp, body = self.api.json_request('GET', url)
+
+ if obj_class is None:
+ obj_class = self.resource_class
+
+ data = body[response_key]
+ return [obj_class(self, res, loaded=True) for res in data if res]
+
+ def _delete(self, url):
+ self.api.raw_request('DELETE', url)
+
+ def _update(self, url, body, response_key=None):
+ resp, body = self.api.json_request('PUT', url, body=body)
+ # PUT requests may not return a body
+ if body:
+ return self.resource_class(self, body[response_key])
+
+
+class Resource(object):
+ """
+ A resource represents a particular instance of an object (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
+ """
+ def __init__(self, manager, info, loaded=False):
+ self.manager = manager
+ self._info = info
+ self._add_details(info)
+ self._loaded = loaded
+
+ def _add_details(self, info):
+ for (k, v) in info.iteritems():
+ setattr(self, k, v)
+
+ def __getattr__(self, k):
+ if k not in self.__dict__:
+ #NOTE(bcwaldon): disallow lazy-loading if already loaded once
+ if not self.is_loaded():
+ self.get()
+ return self.__getattr__(k)
+
+ raise AttributeError(k)
+ else:
+ return self.__dict__[k]
+
+ def __repr__(self):
+ reprkeys = sorted(k for k in self.__dict__.keys() if k[0] != '_' and
+ k != 'manager')
+ info = ", ".join("%s=%s" % (k, getattr(self, k)) for k in reprkeys)
+ return "<%s %s>" % (self.__class__.__name__, info)
+
+ def get(self):
+ # set_loaded() first ... so if we have to bail, we know we tried.
+ self.set_loaded(True)
+ if not hasattr(self.manager, 'get'):
+ return
+
+ new = self.manager.get(self.id)
+ if new:
+ self._add_details(new._info)
+
+ def __eq__(self, other):
+ if not isinstance(other, self.__class__):
+ return False
+ if hasattr(self, 'id') and hasattr(other, 'id'):
+ return self.id == other.id
+ return self._info == other._info
+
+ def is_loaded(self):
+ return self._loaded
+
+ def set_loaded(self, val):
+ self._loaded = val
+
+ def to_dict(self):
+ return copy.deepcopy(self._info)