Skip to content

Commit

Permalink
Merge pull request #10 from alvarolopez/refactor_rendering
Browse files Browse the repository at this point in the history
Refactor rendering
  • Loading branch information
enolfc committed Apr 8, 2015
2 parents e443785 + 4cd9b74 commit 8ab4be5
Show file tree
Hide file tree
Showing 21 changed files with 379 additions and 144 deletions.
54 changes: 53 additions & 1 deletion ooi/api/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@
# License for the specific language governing permissions and limitations
# under the License.

from ooi.wsgi import utils
from ooi import utils

import webob.exc


class Controller(object):
Expand All @@ -31,3 +33,53 @@ def _get_req(self, req, path=None, content_type=None, body=None):
if body is not None:
req.body = utils.utf8(body)
return req

@staticmethod
def get_from_response(response, element, default):
"""Get a JSON element from a valid response or raise an exception.
This method will extract an element a JSON response (falling back to a
default value) if the response has a code of 200, otherwise it will
raise a webob.exc.exception
:param response: The webob.Response object
:param element: The element to look for in the JSON body
:param default: The default element to be returned if not found.
"""
if response.status_int == 200:
return response.json_body.get(element, default)
else:
raise exception_from_response(response)


def exception_from_response(response):
"""Convert an OpenStack V2 Fault into a webob exception.
Since we are calling the OpenStack API we should process the Faults
produced by them. Extract the Fault information according to [1] and
convert it back to a webob exception.
[1] http://docs.openstack.org/developer/nova/v2/faults.html
:param response: a webob.Response containing an exception
:returns: a webob.exc.exception object
"""
exceptions = {
400: webob.exc.HTTPBadRequest,
401: webob.exc.HTTPUnauthorized,
403: webob.exc.HTTPForbidden,
404: webob.exc.HTTPNotFound,
405: webob.exc.HTTPMethodNotAllowed,
406: webob.exc.HTTPNotAcceptable,
409: webob.exc.HTTPConflict,
413: webob.exc.HTTPRequestEntityTooLarge,
415: webob.exc.HTTPUnsupportedMediaType,
429: webob.exc.HTTPTooManyRequests,
501: webob.exc.HTTPNotImplemented,
503: webob.exc.HTTPServiceUnavailable,
}
code = response.status_int
message = response.json_body.popitem()[1].get("message")

exc = exceptions.get(code, webob.exc.HTTPInternalServerError)
return exc(explanation=message)
10 changes: 5 additions & 5 deletions ooi/api/compute.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ def index(self, req):
tenant_id = req.environ["keystone.token_auth"].user.project_id
req = self._get_req(req, path="/%s/servers" % tenant_id)
response = req.get_response(self.app)
servers = response.json_body.get("servers", [])
servers = self.get_from_response(response, "servers", [])
occi_compute_resources = self._get_compute_resources(servers)

return collection.Collection(resources=occi_compute_resources)
Expand All @@ -63,7 +63,7 @@ def create(self, req, headers, params, body):
}}))
response = req.get_response(self.app)
# We only get one server
server = response.json_body.get("server", {})
server = self.get_from_response(response, "server", {})

# The returned JSON does not contain the server name
server["name"] = params["/occi/infrastructure"]
Expand All @@ -77,13 +77,13 @@ def show(self, id, req):
# get info from server
req = self._get_req(req, path="/%s/servers/%s" % (tenant_id, id))
response = req.get_response(self.app)
s = response.json_body.get("server", {})
s = self.get_from_response(response, "server", {})

# get info from flavor
req = self._get_req(req, path="/%s/flavors/%s" % (tenant_id,
s["flavor"]["id"]))
response = req.get_response(self.app)
flavor = response.json_body.get("flavor", {})
flavor = self.get_from_response(response, "flavor", {})
res_tpl = templates.OpenStackResourceTemplate(flavor["name"],
flavor["vcpus"],
flavor["ram"],
Expand All @@ -93,7 +93,7 @@ def show(self, id, req):
req = self._get_req(req, path="/%s/images/%s" % (tenant_id,
s["image"]["id"]))
response = req.get_response(self.app)
image = response.json_body.get("image", {})
image = self.get_from_response(response, "image", {})
os_tpl = templates.OpenStackOSTemplate(image["id"],
image["name"])

Expand Down
4 changes: 2 additions & 2 deletions ooi/api/query.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ def _resource_tpls(self, req):
tenant_id = req.environ["keystone.token_auth"].user.project_id
req = self._get_req(req, path="/%s/flavors/detail" % tenant_id)
response = req.get_response(self.app)
flavors = response.json_body.get("flavors", [])
flavors = self.get_from_response(response, "flavors", [])
occi_resource_templates = []
if flavors:
for f in flavors:
Expand All @@ -44,7 +44,7 @@ def _os_tpls(self, req):
tenant_id = req.environ["keystone.token_auth"].user.project_id
req = self._get_req(req, path="/%s/images/detail" % tenant_id)
response = req.get_response(self.app)
images = response.json_body.get("images", [])
images = self.get_from_response(response, "images", [])
occi_os_templates = []
if images:
for i in images:
Expand Down
5 changes: 5 additions & 0 deletions ooi/occi/core/action.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,5 +24,10 @@ class Action(category.Category):
instance.
"""

def __init__(self, scheme, term, title, attributes=None, location=None):
super(Action, self).__init__(scheme, term, title,
attributes=attributes,
location="?action=%s" % term)

def _class_name(self):
return "action"
18 changes: 0 additions & 18 deletions ooi/occi/core/attribute.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,24 +35,6 @@ def name(self):
def value(self):
return self._value

def _as_str(self):
value_str = ''
if isinstance(self._value, six.string_types):
value_str = '"%s"' % self._value
elif isinstance(self._value, bool):
value_str = '"%s"' % str(self._value).lower()
else:
value_str = "%s" % self._value
return "%s=%s" % (self.name, value_str)

def __str__(self):
"""Render the attribute to text/plain."""
return ": ".join(self.headers()[0])

def headers(self):
"""Render the attribute to text/occi."""
return [("X-OCCI-Attribute", self._as_str())]


class MutableAttribute(Attribute):
@Attribute.value.setter
Expand Down
20 changes: 7 additions & 13 deletions ooi/occi/core/category.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
# under the License.

from ooi.occi.core import attribute
from ooi import utils


class Category(object):
Expand All @@ -37,17 +38,10 @@ def _class_name(self):
"""Returns this class name (see OCCI v1.1 rendering)."""
raise ValueError

def _as_str(self):
d = {
"term": self.term,
"scheme": self.scheme,
"class": self._class_name()
}
@property
def occi_class(self):
return self._class_name()

return '%(term)s; scheme="%(scheme)s"; class="%(class)s"' % d

def headers(self):
return [("Category", self._as_str())]

def __str__(self):
return ": ".join(self.headers()[0])
@property
def type_id(self):
return utils.join_url(self.scheme, "#%s" % self.term)
24 changes: 0 additions & 24 deletions ooi/occi/core/collection.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,27 +30,3 @@ def __init__(self, kinds=[], mixins=[], actions=[],
self.actions = actions
self.resources = resources
self.links = links

def __str__(self):
"""Render the collection to text/plain."""
# NOTE(aloga): This is unfinished, we need to check what is inside the
# collection and render it properly. For example, if we have a
# collection of resources, we should render only their locations.
ret = []
for what in [self.kinds, self.mixins, self.actions,
self.resources, self.links]:
for el in what:
ret.append("X-OCCI-Location: %s" % el.location)
return "\n".join(ret)

def headers(self):
"""Render the collection to text/occi."""
# NOTE(aloga): This is unfinished, we need to check what is inside the
# collection and render it properly. For example, if we have a
# collection of resources, we should render only their locations.
headers = []
for what in [self.kinds, self.mixins, self.actions,
self.resources, self.links]:
for el in what:
headers.append(("X-OCCI-Location", el.location))
return headers
20 changes: 2 additions & 18 deletions ooi/occi/core/entity.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
from ooi.occi.core import kind
from ooi.occi.core import mixin
from ooi.occi import helpers
from ooi import utils


class EntityMeta(type):
Expand Down Expand Up @@ -94,21 +95,4 @@ def title(self, value):

@property
def location(self):
return helpers.join_url(self.kind.location, self.id)

def headers(self):
"""Render the entity to text/occi."""
h = self.kind.headers()
for m in self.mixins:
h.extend(m.headers())
for attr_name in self.attributes:
if self.attributes[attr_name].value is not None:
h.extend(self.attributes[attr_name].headers())
return h

def __str__(self):
"""Render the entity to text/plain."""
ret = []
for h in self.headers():
ret.append(": ".join(h))
return "\n".join(ret)
return utils.join_url(self.kind.location, self.id)
7 changes: 0 additions & 7 deletions ooi/occi/core/resource.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,10 +60,3 @@ def summary(self):
@summary.setter
def summary(self, value):
self.attributes["occi.core.summary"].value = value

def __str__(self):
"""Render the resource to text/plain."""
ret = [super(Resource, self).__str__()]
for link in self.links:
ret.append("%s" % link)
return "\n".join(ret)
6 changes: 0 additions & 6 deletions ooi/occi/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,3 @@ def check_type(obj_list, obj_type):

if not all([isinstance(i, obj_type) for i in obj_list]):
raise TypeError('object must be of class %s' % obj_type)


def join_url(prefix, remainder, fragments=None):
if fragments:
remainder = "%s#%s" % (remainder, fragments)
return urlparse.urljoin(prefix, remainder)
Empty file added ooi/occi/rendering/__init__.py
Empty file.
Loading

0 comments on commit 8ab4be5

Please sign in to comment.