From bea1d1ae29f4167d2836d3be403dde9f13c7a46f Mon Sep 17 00:00:00 2001 From: Sofia Papagiannaki Date: Mon, 19 Nov 2012 17:10:22 +0200 Subject: [PATCH] Integration with updated quotaholder component --- .../astakos/im/api/backends/lib/django/__init__.py | 6 +- .../im/api/backends/lib/django/__init__.py~ | 308 -------------------- snf-astakos-app/astakos/im/api/spec.py | 2 +- .../astakos/im/endpoints/{quotaholder.py => qh.py} | 14 +- .../im/management/commands/quotaholder-sync.py | 2 +- snf-astakos-app/astakos/im/models.py | 2 +- snf-astakos-app/astakos/im/tasks.py | 2 +- snf-astakos-app/astakos/im/views.py | 2 +- snf-astakos-app/setup.py | 3 +- 9 files changed, 16 insertions(+), 325 deletions(-) delete mode 100644 snf-astakos-app/astakos/im/api/backends/lib/django/__init__.py~ rename snf-astakos-app/astakos/im/endpoints/{quotaholder.py => qh.py} (96%) diff --git a/snf-astakos-app/astakos/im/api/backends/lib/django/__init__.py b/snf-astakos-app/astakos/im/api/backends/lib/django/__init__.py index cb6da93..8ac1a66 100644 --- a/snf-astakos-app/astakos/im/api/backends/lib/django/__init__.py +++ b/snf-astakos-app/astakos/im/api/backends/lib/django/__init__.py @@ -45,7 +45,7 @@ from astakos.im.api.backends.errors import ( ItemNotExists, ItemExists, MissingIdentifier, MultipleItemsExist ) from astakos.im.util import reserved_email, model_to_dict -from astakos.im.endpoints.quotaholder import get_quota +from astakos.im.endpoints.qh import get_quota import logging @@ -219,9 +219,7 @@ class DjangoBackend(BaseBackend): @safe def get_resource_usage(self, user_id): user = self._lookup_user(user_id) - r = get_quota((user,)) - print '>>>', r - c, data = r + c, data = get_quota((user,)) resources = [] append = resources.append for t in data: diff --git a/snf-astakos-app/astakos/im/api/backends/lib/django/__init__.py~ b/snf-astakos-app/astakos/im/api/backends/lib/django/__init__.py~ deleted file mode 100644 index bf67ea6..0000000 --- a/snf-astakos-app/astakos/im/api/backends/lib/django/__init__.py~ +++ /dev/null @@ -1,308 +0,0 @@ -# Copyright 2011-2012 GRNET S.A. All rights reserved. -# -# Redistribution and use in source and binary forms, with or -# without modification, are permitted provided that the following -# conditions are met: -# -# 1. Redistributions of source code must retain the above -# copyright notice, this list of conditions and the following -# disclaimer. -# -# 2. Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following -# disclaimer in the documentation and/or other materials -# provided with the distribution. -# -# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS -# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR -# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF -# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED -# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -# POSSIBILITY OF SUCH DAMAGE. -# -# The views and conclusions contained in the software and -# documentation are those of the authors and should not be -# interpreted as representing official policies, either expressed -# or implied, of GRNET S.A. - -from django.db import IntegrityError, transaction -from django.core.exceptions import ObjectDoesNotExist - -from functools import wraps -from smtplib import SMTPException - -from astakos.im.models import ( - AstakosUser, AstakosGroup, GroupKind, Resource, Service, RESOURCE_SEPARATOR -) -from astakos.im.api.backends.base import BaseBackend, SuccessResult, FailureResult -from astakos.im.api.backends.errors import ( - ItemNotExists, ItemExists, MissingIdentifier, MultipleItemsExist -) -from astakos.im.util import reserved_email, model_to_dict -from astakos.im.endpoints.quotaholder import get_quota - -import logging - -logger = logging.getLogger(__name__) - -DEFAULT_CONTENT_TYPE = None - - -def safe(func): - """Decorator function for views that implement an API method.""" - @transaction.commit_manually - @wraps(func) - def wrapper(self, *args, **kwargs): - logger.debug('%s %s %s' % (func, args, kwargs)) - try: - data = func(self, *args, **kwargs) or () - except Exception, e: - logger.exception(e) - transaction.rollback() - return FailureResult(getattr(e, 'message', e)) - else: - transaction.commit() - return SuccessResult(data) - return wrapper - - -class DjangoBackend(BaseBackend): - def _lookup_object(self, model, **kwargs): - """ - Returns an object of the specific model matching the given lookup - parameters. - """ - if not kwargs: - raise MissingIdentifier - try: - return model.objects.get(**kwargs) - except model.DoesNotExist: - raise ItemNotExists(model._meta.verbose_name, **kwargs) - except model.MultipleObjectsReturned: - raise MultipleItemsExist(model._meta.verbose_name, **kwargs) - - def _lookup_user(self, id): - """ - Returns an AstakosUser having this id. - """ - if not isinstance(id, int): - raise TypeError('User id should be of type int') - return self._lookup_object(AstakosUser, id=id) - - def _lookup_service(self, id): - """ - Returns an Service having this id. - """ - if not isinstance(id, int): - raise TypeError('Service id should be of type int') - return self._lookup_object(Service, id=id) - - def _list(self, model, filter=()): - q = model.objects.all() - if filter: - q = q.filter(id__in=filter) - return map(lambda o: model_to_dict(o, exclude=[]), q) - - def _create_object(self, model, **kwargs): - o = model.objects.create(**kwargs) - o.save() - return o - - def _update_object(self, model, id, save=True, **kwargs): - o = self._lookup_object(model, id=id) - if kwargs: - o.__dict__.update(kwargs) - if save: - o.save() - return o - - @safe - def update_user(self, user_id, renew_token=False, **kwargs): - user = self._update_object(AstakosUser, user_id, save=False, **kwargs) - if renew_token: - user.renew_token() - if kwargs or renew_token: - user.save() - - @safe - def create_user(self, **kwargs): - policies = kwargs.pop('policies', ()) - permissions = kwargs.pop('permissions', ()) - groups = kwargs.pop('groups', ()) - password = kwargs.pop('password', None) - - u = self._create_object(AstakosUser, **kwargs) - - if password: - u.set_password(password) - u.permissions = permissions - u.policies = policies - u.extended_groups = groups - return self._list(AstakosUser, filter=(u.id,)) - - @safe - def add_policies(self, user_id, update=False, policies=()): - user = self._lookup_user(user_id) - rejected = [] - append = rejected.append - for p in policies: - service = p.get('service') - resource = p.get('resource') - uplimit = p.get('uplimit') - try: - user.add_policy(service, resource, uplimit, update) - except (ObjectDoesNotExist, IntegrityError), e: - append((service, resource, e)) - return rejected - - @safe - def remove_policies(self, user_id, policies=()): - user = self._lookup_user(user_id) - if not user: - return user_id - rejected = [] - append = rejected.append - for p in policies: - service = p.get('service') - resource = p.get('resource') - try: - user.delete_policy(service, resource) - except ObjectDoesNotExist, e: - append((service, resource, e)) - return rejected - @safe - def add_permissions(self, user_id, permissions=()): - user = self._lookup_user(user_id) - rejected = [] - append = rejected.append - for p in permissions: - try: - user.add_permission(p) - except IntegrityError, e: - append((p, e)) - return rejected - - @safe - def remove_permissions(self, user_id, permissions=()): - user = self._lookup_user(user_id) - rejected = [] - append = rejected.append - for p in permissions: - try: - user.remove_permission(p) - except (ObjectDoesNotExist, IntegrityError), e: - append((p, e)) - return rejected - - @safe - def invite_users(self, senderid, recipients=()): - user = self._lookup_user(senderid) - rejected = [] - append = rejected.append - for r in recipients: - try: - user.invite(r.get('email'), r.get('realname')) - except (IntegrityError, SMTPException), e: - append((email, e)) - return rejected - - @safe - def list_users(self, filter=()): - return self._list(AstakosUser, filter=filter) - - @safe - def get_resource_usage(self, user_id): - user = self._lookup_user(user_id) - c, data = get_quota((user,)) - resources = [] - append = resources.append - for t in data: - t = (i if i else 0 for i in t) - (entity, name, quantity, capacity, importLimit, exportLimit, - imported, exported, returned, released, flags) = t - service, sep, resource = name.partition(RESOURCE_SEPARATOR) - resource = Resource.objects.select_related().get( - service__name=service, name=resource) - d = dict(name=name, - description=resource.desc, - unit=resource.unit or '', - maxValue=quantity + capacity, - currValue=quantity + imported - released - exported + returned) - append(d) - return resources - - @safe - def list_resources(self, filter=()): - return self._list(Resource, filter=filter) - - @safe - def create_service(self, **kwargs): - resources = kwargs.pop('resources', ()) - s = self._create_object(Service, **kwargs) - s.resources = resources - return self._list(Service, filter=(s.id,)) - - @safe - def remove_services(self, ids=()): - # TODO return information for unknown ids - q = Service.objects.filter(id__in=ids) - q.delete() - - @safe - def update_service(self, service_id, renew_token=False, **kwargs): - s = self._update_object(Service, service_id, save=False, **kwargs) - if renew_token: - s.renew_token() - - if kwargs or renew_token: - s.save() - - @safe - def add_resources(self, service_id, update=False, resources=()): - s = self._lookup_service(service_id) - rejected = [] - append = rejected.append - for r in resources: - try: - rr = r.copy() - resource_id = rr.pop('id', None) - if update: - if not resource_id: - raise MissingIdentifier - resource = self._update_object(Resource, resource_id, **rr) - else: - resource = self._create_object(Resource, service=s, **rr) - except Exception, e: - append((r, e)) - return rejected - - @safe - def remove_resources(self, service_id, ids=()): - # TODO return information for unknown ids - q = Resource.objects.filter(service__id=service_id, - id__in=ids) - q.delete() - - @safe - def create_group(self, **kwargs): - policies = kwargs.pop('policies', ()) - permissions = kwargs.pop('permissions', ()) - members = kwargs.pop('members', ()) - owners = kwargs.pop('owners', ()) - kwargs['kind'] = self._lookup_object( - GroupKind, name=kwargs.get('kind', 'course') - ) - - g = self._create_object(AstakosGroup, **kwargs) - - g.permissions = permissions - g.policies = policies -# g.members = members - g.owners = owners - return self._list(AstakosGroup, filter=(g.id,)) \ No newline at end of file diff --git a/snf-astakos-app/astakos/im/api/spec.py b/snf-astakos-app/astakos/im/api/spec.py index 60a8681..161feda 100644 --- a/snf-astakos-app/astakos/im/api/spec.py +++ b/snf-astakos-app/astakos/im/api/spec.py @@ -1,4 +1,4 @@ -from commissioning.api.specificator import ( +from commissioning.specificator import ( CanonifyException, SpecifyException, Specificator, Null, Integer, Text, Tuple, ListOf, Dict, Args) diff --git a/snf-astakos-app/astakos/im/endpoints/quotaholder.py b/snf-astakos-app/astakos/im/endpoints/qh.py similarity index 96% rename from snf-astakos-app/astakos/im/endpoints/quotaholder.py rename to snf-astakos-app/astakos/im/endpoints/qh.py index e908f39..fc5d27a 100644 --- a/snf-astakos-app/astakos/im/endpoints/quotaholder.py +++ b/snf-astakos-app/astakos/im/endpoints/qh.py @@ -43,7 +43,7 @@ from django.utils.translation import ugettext as _ from astakos.im.settings import QUOTA_HOLDER_URL, LOGGING_LEVEL if QUOTA_HOLDER_URL: - from commissioning.clients.quotaholder import QuotaholderHTTP + from quotaholder.clients.kamaki import quotaholder_client ENTITY_KEY = '1' @@ -54,20 +54,20 @@ logger = logging.getLogger(__name__) inf = float('inf') def call(func_name): - """Decorator function for QuotaholderHTTP client calls.""" + """Decorator function for Quotaholder client calls.""" def decorator(payload_func): @wraps(payload_func) def wrapper(entities=(), client=None, **kwargs): if not entities: - return () + return client, () if not QUOTA_HOLDER_URL: - return () + return client, () - c = client or QuotaholderHTTP(QUOTA_HOLDER_URL) + c = client or quotaholder_client(QUOTA_HOLDER_URL) func = c.__dict__.get(func_name) if not func: - return c, + return c, () data = payload_func(entities, client, **kwargs) if not data: @@ -287,7 +287,7 @@ def timeline_charge(entity, resource, after, before, details, charge_type): m = 'charge type %s not supported' % charge_type raise ValueError(m) - quotaholder = QuotaholderHTTP(QUOTA_HOLDER_URL) + quotaholder = quotaholder_client(QUOTA_HOLDER_URL) timeline = quotaholder.get_timeline( context={}, after=after, diff --git a/snf-astakos-app/astakos/im/management/commands/quotaholder-sync.py b/snf-astakos-app/astakos/im/management/commands/quotaholder-sync.py index 69decb6..fb76504 100644 --- a/snf-astakos-app/astakos/im/management/commands/quotaholder-sync.py +++ b/snf-astakos-app/astakos/im/management/commands/quotaholder-sync.py @@ -35,7 +35,7 @@ from django.core.management.base import BaseCommand, CommandError from django.db.utils import IntegrityError from astakos.im.models import AstakosUser, Resource -from astakos.im.endpoints.quotaholder import register_users, register_resources +from astakos.im.endpoints.qh import register_users, register_resources import logging logger = logging.getLogger(__name__) diff --git a/snf-astakos-app/astakos/im/models.py b/snf-astakos-app/astakos/im/models.py index 2b6e6f3..d815134 100644 --- a/snf-astakos-app/astakos/im/models.py +++ b/snf-astakos-app/astakos/im/models.py @@ -57,7 +57,7 @@ from django.db.models import Q from astakos.im.settings import (DEFAULT_USER_LEVEL, INVITATIONS_PER_LEVEL, AUTH_TOKEN_DURATION, BILLING_FIELDS, EMAILCHANGE_ACTIVATION_DAYS, LOGGING_LEVEL) -from astakos.im.endpoints.quotaholder import (register_users, send_quota, +from astakos.im.endpoints.qh import (register_users, send_quota, register_resources) from astakos.im.endpoints.aquarium.producer import report_user_event from astakos.im.functions import send_invitation diff --git a/snf-astakos-app/astakos/im/tasks.py b/snf-astakos-app/astakos/im/tasks.py index a5c4f24..954c445 100644 --- a/snf-astakos-app/astakos/im/tasks.py +++ b/snf-astakos-app/astakos/im/tasks.py @@ -36,7 +36,7 @@ from celery.schedules import crontab from functools import wraps -from astakos.im.endpoints.quotaholder import send_quota +from astakos.im.endpoints.qh import send_quota from astakos.im.endpoints.aquarium.producer import (report_credits_event, report_user_event ) diff --git a/snf-astakos-app/astakos/im/views.py b/snf-astakos-app/astakos/im/views.py index c81c635..539dd5a 100644 --- a/snf-astakos-app/astakos/im/views.py +++ b/snf-astakos-app/astakos/im/views.py @@ -85,7 +85,7 @@ from astakos.im.functions import (send_feedback, SendMailError, switch_account_to_shibboleth, send_group_creation_notification, SendNotificationError) -from astakos.im.endpoints.quotaholder import timeline_charge +from astakos.im.endpoints.qh import timeline_charge from astakos.im.settings import (COOKIE_NAME, COOKIE_DOMAIN, LOGOUT_NEXT, LOGGING_LEVEL, PAGINATE_BY) from astakos.im.tasks import request_billing diff --git a/snf-astakos-app/setup.py b/snf-astakos-app/setup.py index a5fe173..97bc56b 100644 --- a/snf-astakos-app/setup.py +++ b/snf-astakos-app/setup.py @@ -81,9 +81,10 @@ INSTALL_REQUIRES = [ 'recaptcha-client>=1.0.5', 'django-ratelimit==0.1', 'commissioning', + 'quotaholder', 'celery', 'requests', - 'inflect', + 'inflect' #TODO add commissioning ] -- 1.7.10.4