From fd5d5fa32a498f653d609aebc0b565dcf63b2db4 Mon Sep 17 00:00:00 2001 From: Ed Cranford Date: Thu, 29 Mar 2012 11:21:05 -0500 Subject: [PATCH] Fixed the Flavors API so the URLs returned are correct and all tests are passed. --- reddwarf/flavor/models.py | 63 +++++++++++++++++++++++++++++------- reddwarf/flavor/service.py | 45 ++++++++++++++++++++------ reddwarf/flavor/views.py | 23 ++++++------- reddwarf/instance/service.py | 2 +- 4 files changed, 100 insertions(+), 33 deletions(-) diff --git a/reddwarf/flavor/models.py b/reddwarf/flavor/models.py index 6b169647..4e16dc00 100644 --- a/reddwarf/flavor/models.py +++ b/reddwarf/flavor/models.py @@ -27,50 +27,89 @@ from reddwarf.common import config from reddwarf.common import exception as rd_exceptions from reddwarf.common import utils from reddwarf.common.models import NovaRemoteModelBase +from reddwarf.common.remote import create_nova_client CONFIG = config.Config LOG = logging.getLogger('reddwarf.database.models') -class Flavor(NovaRemoteModelBase): +class Flavor(object): _data_fields = ['id', 'links', 'name', 'ram'] def __init__(self, flavor=None, context=None, flavor_id=None): if flavor: - self._data_object = flavor + self.flavor = flavor + LOG.debug("FLAVOR IS NOW %s" % self.flavor) return if flavor_id and context: try: - client = self.get_client(context) - self._data_object = client.flavors.get(flavor_id) + client = create_nova_client(context) + self.flavor = client.flavors.get(flavor_id) except nova_exceptions.NotFound, e: raise rd_exceptions.NotFound(uuid=flavor_id) except nova_exceptions.ClientException, e: raise rd_exceptions.ReddwarfError(str(e)) - # Now modify the links return msg = ("Flavor is not defined, and" " context and flavor_id were not specified.") raise InvalidModelError(msg) + @property + def id(self): + return self.flavor.id + + @property + def name(self): + return self.flavor.name + + @property + def ram(self): + return self.flavor.ram + + @property + def vcpus(self): + return self.flavor.vcpus + @property def links(self): return self._build_links() def _build_links(self): - # TODO(ed-): Fix this URL: Change the endpoint, port, auth version, - # and the presence of the tenant id. - return self._data_object.links + if self.req is None: + # If there's no request available, don't modify the links. + return self.flavor.links + result = [] + scheme = self.req.scheme + endpoint = self.req.host + path = self.req.path + href_template = "%(scheme)s://%(endpoint)s%(path)s" + for link in self.flavor.links: + rlink = link + href = rlink['href'] + if rlink['rel'] == 'self': + path = path.split('/') + path.pop(2) # Remove the instance id. + path = '/'.join(path) + href = href_template % locals() + elif rlink['rel'] == 'bookmark': + path = path.split('/') + path.pop(1) # Remove the version. + path = '/'.join(path) + href = href_template % locals() + + rlink['href'] = href + result.append(rlink) + return result + class Flavors(NovaRemoteModelBase): - # Flavors HASA list of Flavor objects. def __init__(self, context): - nova_flavors = self.get_client(context).flavors.list() - self._data_object = [Flavor(flavor=item).data() for item in nova_flavors] + nova_flavors = create_nova_client(context).flavors.list() + self.flavors = [Flavor(flavor=item) for item in nova_flavors] def __iter__(self): - for item in self._data_object: + for item in self.flavors: yield item diff --git a/reddwarf/flavor/service.py b/reddwarf/flavor/service.py index 432effe8..757ab1be 100644 --- a/reddwarf/flavor/service.py +++ b/reddwarf/flavor/service.py @@ -19,16 +19,44 @@ import logging import routes import webob.exc -from reddwarf.common import BaseController from reddwarf.common import config from reddwarf.common import context as rd_context from reddwarf.common import exception from reddwarf.common import wsgi +from reddwarf.flavor import models +from reddwarf.flavor import views CONFIG = config.Config LOG = logging.getLogger(__name__) +class BaseController(wsgi.Controller): + """Base controller class.""" + + exclude_attr = [] + exception_map = { + webob.exc.HTTPUnprocessableEntity: [ + ], + webob.exc.HTTPBadRequest: [ + exception.BadRequest, + ], + webob.exc.HTTPNotFound: [ + exception.NotFound, + ], + webob.exc.HTTPConflict: [ + ], + } + + def __init__(self): + pass + + def _extract_required_params(self, params, model_name): + params = params or {} + model_params = params.get(model_name, {}) + return utils.stringify_keys(utils.exclude(model_params, + *self.exclude_attr)) + + class FlavorController(BaseController): """Controller for flavor functionality""" @@ -38,11 +66,11 @@ class FlavorController(BaseController): auth_tok=req.headers["X-Auth-Token"], tenant=tenant_id) try: - flavor = flavormodels.Flavor(context=context, flavor_id=id).data() - print "Flavor in show: %s" % flavor + flavor = models.Flavor(context=context, flavor_id=id) except exception.ReddwarfError, e: return wsgi.Result(str(e), 404) - return wsgi.Result(flavorviews.FlavorView(flavor).data(), 201) + # Pass in the request to build accurate links. + return wsgi.Result(views.FlavorView(flavor).data(req), 201) def detail(self, req, tenant_id): """Return a list of flavors, with additional data about each flavor.""" @@ -50,19 +78,18 @@ class FlavorController(BaseController): auth_tok=req.headers["X-Auth-Token"], tenant=tenant_id) try: - flavors = flavormodels.Flavors(context=context) + flavors = models.Flavors(context=context) except exception.ReddwarfError, e: return wsgi.Result(str(e), 404) - return wsgi.Result(flavorviews.FlavorsView(flavors).data(), 201) + return wsgi.Result(views.FlavorsView(flavors).data(req, detailed=True), 201) def index(self, req, tenant_id): """Return all flavors.""" context = rd_context.ReddwarfContext( auth_tok=req.headers["X-Auth-Token"], tenant=tenant_id) - flavors = flavormodels.Flavors(context) - return wsgi.Result(flavorviews.FlavorsView(flavors).data(), 201) - + flavors = models.Flavors(context) + return wsgi.Result(views.FlavorsView(flavors).data(req), 201) class API(wsgi.Router): """API""" diff --git a/reddwarf/flavor/views.py b/reddwarf/flavor/views.py index d7ea739e..a7086780 100644 --- a/reddwarf/flavor/views.py +++ b/reddwarf/flavor/views.py @@ -20,21 +20,22 @@ class FlavorView(object): def __init__(self, flavor): self.flavor = flavor - def data(self): + def data(self, req=None): + self.flavor.req = req # For building the links. return {"flavor": { - "id": self.flavor['id'], - "links": self.flavor['links'], - "name": self.flavor['name'], - "ram": self.flavor['ram'], + 'id': self.flavor.id, + 'links': self.flavor.links, + 'name': self.flavor.name, + 'ram': self.flavor.ram, }} class FlavorDetailView(FlavorView): - def data(self): - result = super(FlavorDetailView, self).data() + def data(self, req=None): + result = super(FlavorDetailView, self).data(req) details = { - "vcpus": self.flavor['vcpus'], + "vcpus": self.flavor.vcpus, } result["flavor"].update(details) return result @@ -45,12 +46,12 @@ class FlavorsView(object): def __init__(self, flavors): self.flavors = flavors - def data(self, detailed=False): + def data(self, req=None, detailed=False): data = [] for flavor in self.flavors: if detailed: - data.append(FlavorDetailView(flavor).data()['flavor']) + data.append(FlavorDetailView(flavor).data(req)['flavor']) else: - data.append(FlavorView(flavor).data()['flavor']) + data.append(FlavorView(flavor).data(req)['flavor']) return {"flavors": data} diff --git a/reddwarf/instance/service.py b/reddwarf/instance/service.py index 6d3c76fc..5f21f423 100644 --- a/reddwarf/instance/service.py +++ b/reddwarf/instance/service.py @@ -26,7 +26,7 @@ from reddwarf.common import wsgi from reddwarf.instance import models, views from reddwarf.common import exception as rd_exceptions -#TODO(ed-): Import these properly after baz restructures +#TODO(ed-): Import these properly after this is restructured from reddwarf.flavor import models as flavormodels from reddwarf.flavor import views as flavorviews from reddwarf.flavor import service as flavorservice