User create_groups api call in group creation
authorSofia Papagiannaki <papagian@gmail.com>
Wed, 7 Nov 2012 00:53:40 +0000 (02:53 +0200)
committerSofia Papagiannaki <papagian@gmail.com>
Wed, 7 Nov 2012 00:53:40 +0000 (02:53 +0200)
snf-astakos-app/astakos/im/api/backends/base.py
snf-astakos-app/astakos/im/api/backends/errors.py [new file with mode: 0644]
snf-astakos-app/astakos/im/api/backends/lib/django/__init__.py
snf-astakos-app/astakos/im/api/callpoint.py
snf-astakos-app/astakos/im/api/spec.py
snf-astakos-app/astakos/im/forms.py
snf-astakos-app/astakos/im/management/commands/quotaholder-sync.py
snf-astakos-app/astakos/im/migrations/0030_populate_resource_data.py
snf-astakos-app/astakos/im/urls.py
snf-astakos-app/astakos/im/views.py

index 080634f..db1514e 100644 (file)
@@ -1,18 +1,23 @@
-class ItemNotExists(NameError):
-    pass
-
-
-class ItemExists(NameError):
-    pass
+import astakos.im.api.backends.errors
 
+(SUCCESS, FAILURE) = range(2)
 
-class MissingIdentifier(IOError):
+class BaseBackend(object):
+    #TODO filled
     pass
 
+class SuccessResult():
+    def __init__(self, data):
+        self.data = data
+    
+    @property
+    def is_success(self):
+        return True
 
-class BaseBackend(object):
-    def update_user():
-        pass
-
-    def create_user():
-        pass
+class FailureResult():
+    def __init__(self, reason):
+        self.reason = reason
+    
+    @property
+    def is_success(self):
+        return False
diff --git a/snf-astakos-app/astakos/im/api/backends/errors.py b/snf-astakos-app/astakos/im/api/backends/errors.py
new file mode 100644 (file)
index 0000000..042aac2
--- /dev/null
@@ -0,0 +1,53 @@
+# 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.
+
+class ItemNotExists(ValueError):
+    def __init__(self, type, **kwargs):
+        fields = " and ".join('%s=%s' % (k,v) for k,v in kwargs.iteritems())
+        msg = "%(type)s with %(fields)s does not exist."
+        super(ItemNotExists, self).__init__(msg % locals())
+
+class ItemExists(ValueError):
+    def __init__(self, type, **kwargs):
+        fields = " and ".join('%s=%s' % (k,v) for k,v in kwargs.iteritems())
+        msg = "%(type)s with %(fields)s already exists."
+        super(ItemExists, self).__init__(msg % locals())
+
+class MultipleItemsExist(ValueError):
+    def __init__(self, type, **kwargs):
+        fields = " and ".join('%s=%s' % (k,v) for k,v in kwargs.iteritems())
+        msg = "There are mulptiple %(type)s with %(fields)s."
+        super(MultipleItemsExist, self).__init__(msg % locals())
+
+class MissingIdentifier(IOError):
+    pass
\ No newline at end of file
index 1fe9ac8..bf67ea6 100644 (file)
@@ -37,9 +37,13 @@ from django.core.exceptions import ObjectDoesNotExist
 from functools import wraps
 from smtplib import SMTPException
 
-from astakos.im.models import AstakosUser, Resource, Service, RESOURCE_SEPARATOR
-from astakos.im.api.backends.base import (BaseBackend, ItemNotExists,
-                                          ItemExists, MissingIdentifier)
+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
 
@@ -50,55 +54,53 @@ logger = logging.getLogger(__name__)
 DEFAULT_CONTENT_TYPE = None
 
 
-def safe(propagate_exceptions=False):
+def safe(func):
     """Decorator function for views that implement an API method."""
-
-    def decorator(func):
-        @transaction.commit_manually
-        @wraps(func)
-        def wrapper(self, *args, **kwargs):
-            logger.debug('%s %s %s' % (func, args, kwargs))
-            try:
-                r = func(self, *args, **kwargs) or ()
-            except Exception, e:
-                logger.exception(e)
-                transaction.rollback()
-                if propagate_exceptions:
-                    raise e
-                else:
-                    args = list(args)
-                    args.append(e)
-                    r = args
-            else:
-                transaction.commit()
-            r = filter(bool, r) # filter out None elements
-            return list(r)
-        return wrapper
-    return decorator
+    @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 having this id.
+        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()
+            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=()):
@@ -108,7 +110,7 @@ class DjangoBackend(BaseBackend):
         return map(lambda o: model_to_dict(o, exclude=[]), q)
 
     def _create_object(self, model, **kwargs):
-        o = model(**kwargs)
+        o = model.objects.create(**kwargs)
         o.save()
         return o
 
@@ -120,7 +122,7 @@ class DjangoBackend(BaseBackend):
             o.save()
         return o
 
-    @safe()
+    @safe
     def update_user(self, user_id, renew_token=False, **kwargs):
         user = self._update_object(AstakosUser, user_id, save=False, **kwargs)
         if renew_token:
@@ -128,7 +130,7 @@ class DjangoBackend(BaseBackend):
         if kwargs or renew_token:
             user.save()
 
-    @safe()
+    @safe
     def create_user(self, **kwargs):
         policies = kwargs.pop('policies', ())
         permissions = kwargs.pop('permissions', ())
@@ -142,8 +144,9 @@ class DjangoBackend(BaseBackend):
         u.permissions = permissions
         u.policies = policies
         u.extended_groups = groups
+        return self._list(AstakosUser, filter=(u.id,))
 
-    @safe()
+    @safe
     def add_policies(self, user_id, update=False, policies=()):
         user = self._lookup_user(user_id)
         rejected = []
@@ -156,10 +159,9 @@ class DjangoBackend(BaseBackend):
                 user.add_policy(service, resource, uplimit, update)
             except (ObjectDoesNotExist, IntegrityError), e:
                 append((service, resource, e))
-        if rejected:
-            raise Exception(rejected)
-
-    @safe()
+        return rejected
+    
+    @safe
     def remove_policies(self, user_id, policies=()):
         user = self._lookup_user(user_id)
         if not user:
@@ -173,10 +175,8 @@ class DjangoBackend(BaseBackend):
                 user.delete_policy(service, resource)
             except ObjectDoesNotExist, e:
                 append((service, resource, e))
-        if rejected:
-            raise Exception(rejected)
-
-    @safe()
+        return rejected
+    @safe
     def add_permissions(self, user_id, permissions=()):
         user = self._lookup_user(user_id)
         rejected = []
@@ -186,10 +186,9 @@ class DjangoBackend(BaseBackend):
                 user.add_permission(p)
             except IntegrityError, e:
                 append((p, e))
-        if rejected:
-            raise Exception(rejected)
-
-    @safe()
+        return rejected
+    
+    @safe
     def remove_permissions(self, user_id, permissions=()):
         user = self._lookup_user(user_id)
         rejected = []
@@ -199,10 +198,9 @@ class DjangoBackend(BaseBackend):
                 user.remove_permission(p)
             except (ObjectDoesNotExist, IntegrityError), e:
                 append((p, e))
-        if rejected:
-            raise Exception(rejected)
-
-    @safe()
+        return rejected
+    
+    @safe
     def invite_users(self, senderid, recipients=()):
         user = self._lookup_user(senderid)
         rejected = []
@@ -212,14 +210,13 @@ class DjangoBackend(BaseBackend):
                 user.invite(r.get('email'), r.get('realname'))
             except (IntegrityError, SMTPException), e:
                 append((email, e))
-        if rejected:
-            raise Exception(rejected)
-
-    @safe(propagate_exceptions=True)
+        return rejected
+    
+    @safe
     def list_users(self, filter=()):
         return self._list(AstakosUser, filter=filter)
 
-    @safe(propagate_exceptions=True)
+    @safe
     def get_resource_usage(self, user_id):
         user = self._lookup_user(user_id)
         c, data = get_quota((user,))
@@ -240,23 +237,24 @@ class DjangoBackend(BaseBackend):
             append(d)
         return resources
 
-    @safe(propagate_exceptions=True)
+    @safe
     def list_resources(self, filter=()):
         return self._list(Resource, filter=filter)
 
-    @safe()
+    @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()
+    @safe
     def remove_services(self, ids=()):
         # TODO return information for unknown ids
         q = Service.objects.filter(id__in=ids)
         q.delete()
     
-    @safe()
+    @safe
     def update_service(self, service_id, renew_token=False, **kwargs):
         s = self._update_object(Service, service_id, save=False, **kwargs)
         if renew_token:
@@ -265,7 +263,7 @@ class DjangoBackend(BaseBackend):
         if kwargs or renew_token:
             s.save()
 
-    @safe()
+    @safe
     def add_resources(self, service_id, update=False, resources=()):
         s = self._lookup_service(service_id)
         rejected = []
@@ -282,26 +280,29 @@ class DjangoBackend(BaseBackend):
                     resource = self._create_object(Resource, service=s, **rr)
             except Exception, e:
                 append((r, e))
-        if rejected:
-            raise Exception(rejected)
+        return rejected
     
-    @safe()
+    @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()
+    @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
\ No newline at end of file
+#         g.members = members
+        g.owners = owners
+        return self._list(AstakosGroup, filter=(g.id,))
\ No newline at end of file
index 31711dc..5779abd 100644 (file)
@@ -32,7 +32,7 @@
 # or implied, of GRNET S.A.
 
 from astakos.im.api.spec import AstakosAPI
-from backends import get_backend
+from astakos.im.api.backends import get_backend
 
 from commissioning import (Callpoint,
                            #                             CommissionException,
@@ -49,7 +49,7 @@ from commissioning import (Callpoint,
 # from .models import (Holder, Entity, Policy, Holding,
 #                      Commission, Provision, ProvisionLog, now)
 
-class AstakosDjangoDBCallpoint():
+class AstakosCallpoint():
 
     api_spec = AstakosAPI()
 
@@ -159,4 +159,4 @@ class AstakosDjangoDBCallpoint():
         rejected = (b.create_group(**g) for g in groups)
         return rejected
 
-API_Callpoint = AstakosDjangoDBCallpoint
+API_Callpoint = AstakosCallpoint
index 5b3ecc2..60a8681 100644 (file)
@@ -42,10 +42,10 @@ class Boolean(Integer):
 Boolean = Boolean()
 
 
-class GroupKind(Integer):
-    def init(self):
-        self.opts.update({'minimum': 1, 'maximum': 5})
-GroupKind = GroupKind()
+# class GroupKind(Integer):
+#     def init(self):
+#         self.opts.update({'minimum': 1, 'maximum': 5})
+# GroupKind = GroupKind()
 
 Timepoint = Text(classname='Timepoint', maxlen=24)
 
@@ -280,7 +280,7 @@ class AstakosAPI(Specificator):
         self,
         groups=ListOf(
             name=Name,
-            kind=GroupKind,
+            kind=Name,
             homepage=Url,
             desc=Text(),
             policies=ListOf(resource=Name, upimit=Nonnegative),
@@ -303,7 +303,7 @@ class AstakosAPI(Specificator):
     def search_groups(self, key=Name):
         return ListOf(
             group=Name,
-            kind=GroupKind,
+            kind=Nonnegative,
             homepage=Url,
             desc=Text(),
             creation_date=Timepoint,
@@ -319,7 +319,7 @@ class AstakosAPI(Specificator):
     def list_groups(self):
         return ListOf(
             group=Name,
-            kind=GroupKind,
+            kind=Nonnegative,
             homepage=Url,
             desc=Text(),
             creation_date=Timepoint,
index cbeffa3..4bf3586 100644 (file)
@@ -572,18 +572,22 @@ class AstakosGroupCreationForm(forms.ModelForm):
         map(add_field,
             ((k, v) for k,v in qd.iteritems() if k.endswith('_uplimit'))
         )
-        
-    def policies(self):
+    
+    def clean(self):
+        self.cleaned_data['policies'] = []
+        append = self.cleaned_data['policies'].append
+        tbd = []
         for name, uplimit in self.cleaned_data.iteritems():
             subs = name.split('_uplimit')
             if len(subs) == 2:
+                tbd.append(name)
                 prefix, suffix = subs
-#               # yield only those having a value
-#                    if not value:
-#                        continue
                 s, r = prefix.split(RESOURCE_SEPARATOR)
-                yield dict(service=s, resource=r, uplimit=uplimit)
-
+                append(dict(service=s, resource=r, uplimit=uplimit))
+        for name in tbd:
+            del self.cleaned_data[name]
+        return self.cleaned_data
+        
 
 class AstakosGroupUpdateForm(forms.ModelForm):
     class Meta:
index e23fb22..69decb6 100644 (file)
@@ -47,7 +47,7 @@ class Command(BaseCommand):
     def handle(self, *args, **options):
         try:
             register_resources(Resource.objects.all())
-            register_users(AstakosUser.objects.filter(disturbed_quota=True))
+            register_users(AstakosUser.objects.all())
         except BaseException, e:
             logger.exception(e)
             raise CommandError("Syncing failed.")
index f4620a7..439fdcd 100644 (file)
@@ -22,12 +22,11 @@ class Migration(DataMigration):
             sn, dict = args
             url = dict.get('url')
             resources = dict.get('resources') or ()
-            s, created = orm.Service.objects.get_or_create(name=sn,
-                                                           defaults={'url': url})
-            if not created and not s.url:
-                s.url = url
-            s.save()
-
+            s, created = orm.Service.objects.get_or_create(
+                name=sn,
+                defaults={'url': url}
+            )
+            
             for r in resources:
                 try:
                     rn = r.pop('name', '')
@@ -43,8 +42,10 @@ class Migration(DataMigration):
                 q, created = orm.AstakosGroupQuota.objects.get_or_create(
                     group=default,
                     resource=r,
-                    uplimit=uplimit,
-                    limit=0)
+                    defaults={
+                        'uplimit':uplimit,
+                    }
+                )
         map(create_policies, SERVICES.iteritems())
 
     def backwards(self, orm):
index a2f68c8..3b31e02 100644 (file)
@@ -85,8 +85,6 @@ urlpatterns = patterns('astakos.im.views',
                            'disapprove_member', {}, name='disapprove_member'),
                        url(r'^group/create/?$', 'group_create_list', {},
                            name='group_create_list'),
-                       url(r'^group/create_demo/?$', 'group_create_demo', {},
-                           name='group_create_demo'),
                        )
 
 if EMAILCHANGE_ENABLED:
index 933f0fa..6f40b48 100644 (file)
@@ -87,7 +87,7 @@ from astakos.im.endpoints.quotaholder 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
-from astakos.im.api.callpoint import AstakosDjangoDBCallpoint
+from astakos.im.api.callpoint import AstakosCallpoint
 
 logger = logging.getLogger(__name__)
 
@@ -95,7 +95,7 @@ logger = logging.getLogger(__name__)
 DB_REPLACE_GROUP_SCHEME = """REPLACE(REPLACE("auth_group".name, 'http://', ''),
                                      'https://', '')"""
 
-callpoint = AstakosDjangoDBCallpoint()
+callpoint = AstakosCallpoint()
 
 def render_response(template, tab=None, status=200, reset_cookie=False,
                     context_instance=None, **kwargs):
@@ -667,10 +667,53 @@ def change_email(request, activation_key=None,
 @signed_terms_required
 @login_required
 def group_add(request, kind_name='default'):
+    result = callpoint.list_resources()
+    resource_catalog = {'resources':defaultdict(defaultdict),
+                        'groups':defaultdict(list)}
+    if result.is_success:
+        for r in result.data:
+            service = r.get('service', '')
+            name = r.get('name', '')
+            group = r.get('group', '')
+            unit = r.get('unit', '')
+            fullname = '%s%s%s' % (service, RESOURCE_SEPARATOR, name)
+            resource_catalog['resources'][fullname] = dict(unit=unit)
+            resource_catalog['groups'][group].append(fullname)
+        
+        resource_catalog = dict(resource_catalog)
+        for k, v in resource_catalog.iteritems():
+            resource_catalog[k] = dict(v)
+    else:
+        messages.error(
+            request,
+            'Unable to retrieve system resources: %s' % result.reason
+    )
+    
     try:
         kind = GroupKind.objects.get(name=kind_name)
     except:
         return HttpResponseBadRequest(_('No such group kind'))
+    
+    resource_presentation = {
+       'compute': {
+            'help_text':'group compute help text',
+        },
+        'storage': {
+            'help_text':'group storage help text',
+        },
+        'pithos+.diskspace': {
+            'help_text':'resource pithos+.diskspace help text',
+        },
+        'cyclades.vm': {
+            'help_text':'resource cyclades.vm help text resource cyclades.vm help text resource cyclades.vm help text resource cyclades.vm help text',
+        },
+        'cyclades.disksize': {
+            'help_text':'resource cyclades.disksize help text',
+        },
+        'cyclades.ram': {
+            'help_text':'resource cyclades.ram help text',
+        }
+    }
 
     post_save_redirect = '/im/group/%(id)s/'
     context_processors = None
@@ -678,57 +721,46 @@ def group_add(request, kind_name='default'):
         model=None,
         form_class=AstakosGroupCreationForm
     )
-    resources = dict(
-        (str(r.id), r) for r in Resource.objects.select_related().all())
-    policies = []
+    
     if request.method == 'POST':
-        form = form_class(request.POST, request.FILES, resources=resources)
+        form = form_class(request.POST, request.FILES)
         if form.is_valid():
-            new_object = form.save()
-
-            # save owner
-            new_object.owners = [request.user]
-
-            # save quota policies
-            for (rid, uplimit) in form.resources():
-                try:
-                    r = resources[rid]
-                except KeyError, e:
-                    logger.exception(e)
-                    # TODO Should I stay or should I go???
-                    continue
-                else:
-                    new_object.astakosgroupquota_set.create(
-                        resource=r,
-                        uplimit=uplimit
-                    )
-                policies.append('%s %d' % (r, uplimit))
-            msg = _("The %(verbose_name)s was created successfully.") %\
-                {"verbose_name": model._meta.verbose_name}
-            messages.success(request, msg, fail_silently=True)
-
-            # send notification
-            try:
-                send_group_creation_notification(
-                    template_name='im/group_creation_notification.txt',
-                    dictionary={
-                        'group': new_object,
-                        'owner': request.user,
-                        'policies': policies,
-                    }
-                )
-            except SendNotificationError, e:
-                messages.error(request, e, fail_silently=True)
-            return HttpResponseRedirect(post_save_redirect % new_object.__dict__)
+            d = form.cleaned_data.copy()
+            d['owners'] = [request.user]
+            result = callpoint.create_groups((d,)).next()
+            if result.is_success:
+                new_object = result.data[0]
+                msg = _("The %(verbose_name)s was created successfully.") %\
+                    {"verbose_name": model._meta.verbose_name}
+                messages.success(request, msg, fail_silently=True)
+
+#                # send notification
+#                 try:
+#                     send_group_creation_notification(
+#                         template_name='im/group_creation_notification.txt',
+#                         dictionary={
+#                             'group': new_object,
+#                             'owner': request.user,
+#                             'policies': list(form.cleaned_data['policies']),
+#                         }
+#                     )
+#                 except SendNotificationError, e:
+#                     messages.error(request, e, fail_silently=True)
+                return HttpResponseRedirect(post_save_redirect % new_object)
+            else:
+                msg = _("The %(verbose_name)s creation failed: %(reason)s.") %\
+                    {"verbose_name": model._meta.verbose_name,
+                     "reason":result.reason}
+                messages.error(request, msg, fail_silently=True)
     else:
         now = datetime.now()
         data = {
             'kind': kind
         }
-        form = form_class(data, resources=resources)
+        form = form_class(data)
 
     # Create the template, context, response
-    template_name = "%s/%s_form.html" % (
+    template_name = "%s/%s_form_demo.html" % (
         model._meta.app_label,
         model._meta.object_name.lower()
     )
@@ -736,10 +768,11 @@ def group_add(request, kind_name='default'):
     c = RequestContext(request, {
         'form': form,
         'kind': kind,
+        'resource_catalog':resource_catalog,
+        'resource_presentation':resource_presentation,
     }, context_processors)
     return HttpResponse(t.render(c))
 
-
 @signed_terms_required
 @login_required
 def group_list(request):
@@ -1087,123 +1120,17 @@ def resource_list(request):
         entry['plural'] = engine.plural(entry.get('name'))
         return entry
 
-    try:
-        data = callpoint.get_user_status(request.user.id)
-    except Exception, e:
-        data = None
-        messages.error(request, e)
+    result = callpoint.get_user_status(request.user.id)
+    if result.is_success:
+        backenddata = map(with_class, result.data)
+        data = map(pluralize, result.data)
     else:
-        backenddata = map(with_class, data)
-        data = map(pluralize, data)
+        data = None
+        messages.error(request, result.reason)
     return render_response('im/resource_list.html',
                            data=data,
                            context_instance=get_context(request))
 
-@signed_terms_required
-@login_required
-def group_create_demo(request, kind_name='default'):
-    resources = callpoint.list_resources()
-    resource_catalog = {'resources':defaultdict(defaultdict),
-                        'groups':defaultdict(list)}
-    for r in resources:
-        service = r.get('service', '')
-        name = r.get('name', '')
-        group = r.get('group', '')
-        unit = r.get('unit', '')
-        fullname = '%s%s%s' % (service, RESOURCE_SEPARATOR, name)
-        resource_catalog['resources'][fullname] = dict(unit=unit)
-        resource_catalog['groups'][group].append(fullname)
-    
-    resource_catalog = dict(resource_catalog)
-    for k, v in resource_catalog.iteritems():
-        resource_catalog[k] = dict(v)
-    try:
-        kind = GroupKind.objects.get(name=kind_name)
-    except:
-        return HttpResponseBadRequest(_('No such group kind'))
-
-    post_save_redirect = '/im/group/%(id)s/'
-    context_processors = None
-    model, form_class = get_model_and_form_class(
-        model=None,
-        form_class=AstakosGroupCreationForm
-    )
-    
-    if request.method == 'POST':
-        form = form_class(request.POST, request.FILES)
-        if form.is_valid():
-            new_object = form.save()
-            new_object.policies = form.policies()
-
-            # save owner
-            new_object.owners = [request.user]
-            
-            msg = _("The %(verbose_name)s was created successfully.") %\
-                {"verbose_name": model._meta.verbose_name}
-            messages.success(request, msg, fail_silently=True)
-
-            # send notification
-            try:
-                send_group_creation_notification(
-                    template_name='im/group_creation_notification.txt',
-                    dictionary={
-                        'group': new_object,
-                        'owner': request.user,
-                        'policies': list(form.policies()),
-                    }
-                )
-            except SendNotificationError, e:
-                messages.error(request, e, fail_silently=True)
-            return HttpResponseRedirect(post_save_redirect % new_object.__dict__)
-    else:
-        now = datetime.now()
-        data = {
-            'kind': kind
-        }
-        form = form_class(data)
-
-    resource_presentation = {
-       'compute': {
-            'help_text':'group compute help text',
-                     
-        },
-        'storage': {
-            'help_text':'group storage help text',
-                      
-        },  
-        'pithos+.diskspace': {
-            'help_text':'resource pithos+.diskspace help text',
-                      
-        },  
-        'cyclades.vm': {
-            'help_text':'resource cyclades.vm help text resource cyclades.vm help text resource cyclades.vm help text resource cyclades.vm help text',
-                      
-        },  
-        'cyclades.disksize': {
-            'help_text':'resource cyclades.disksize help text',
-                      
-        },  
-        'cyclades.ram': {
-            'help_text':'resource cyclades.ram help text',
-                      
-        }                        
-                             
-    }
-    
-    # Create the template, context, response
-    template_name = "%s/%s_form_demo.html" % (
-        model._meta.app_label,
-        model._meta.object_name.lower()
-    )
-    t = template_loader.get_template(template_name)
-    c = RequestContext(request, {
-        'form': form,
-        'kind': kind,
-        'resource_catalog':resource_catalog,
-        'resource_presentation':resource_presentation
-    }, context_processors)
-    return HttpResponse(t.render(c))
-
 
 def group_create_list(request):
     form = PickResourceForm()