Revision f46c95c4 snf-astakos-app/astakos/im/views.py

b/snf-astakos-app/astakos/im/views.py
33 33

  
34 34
import logging
35 35
import calendar
36
import inflect
37

  
38
engine = inflect.engine()
36 39

  
37 40
from urllib import quote
38 41
from functools import wraps
......
47 50
from django.db.models import Q
48 51
from django.db.utils import IntegrityError
49 52
from django.forms.fields import URLField
50
from django.http import HttpResponse, HttpResponseBadRequest, HttpResponseForbidden, \
51
    HttpResponseRedirect, HttpResponseBadRequest, Http404
53
from django.http import (HttpResponse, HttpResponseBadRequest,
54
                         HttpResponseForbidden, HttpResponseRedirect,
55
                         HttpResponseBadRequest, Http404)
52 56
from django.shortcuts import redirect
53 57
from django.template import RequestContext, loader as template_loader
54 58
from django.utils.http import urlencode
......
59 63
from django.http import HttpResponseBadRequest
60 64
from django.core.xheaders import populate_xheaders
61 65

  
62
from astakos.im.models import (
63
    AstakosUser, ApprovalTerms, AstakosGroup, Resource,
64
    EmailChange, GroupKind, Membership, AstakosGroupQuota)
66
from astakos.im.models import (AstakosUser, ApprovalTerms, AstakosGroup,
67
                               Resource, EmailChange, GroupKind, Membership,
68
                               AstakosGroupQuota, RESOURCE_SEPARATOR)
69
from django.views.decorators.http import require_http_methods
70

  
65 71
from astakos.im.activation_backends import get_backend, SimpleBackend
66 72
from astakos.im.util import get_context, prepare_response, set_cookie, get_query
67 73
from astakos.im.forms import (LoginForm, InvitationForm, ProfileForm,
......
72 78
                              AstakosGroupSortForm, MembersSortForm,
73 79
                              TimelineForm, PickResourceForm)
74 80
from astakos.im.functions import (send_feedback, SendMailError,
75
                                  invite as invite_func, logout as auth_logout,
81
                                  logout as auth_logout,
76 82
                                  activate as activate_func,
77 83
                                  switch_account_to_shibboleth,
78
                                  send_admin_notification,
84
                                  send_group_creation_notification,
79 85
                                  SendNotificationError)
80 86
from astakos.im.endpoints.quotaholder import timeline_charge
81
from astakos.im.settings import (
82
    COOKIE_NAME, COOKIE_DOMAIN, SITENAME, LOGOUT_NEXT,
83
    LOGGING_LEVEL, PAGINATE_BY)
87
from astakos.im.settings import (COOKIE_NAME, COOKIE_DOMAIN, LOGOUT_NEXT,
88
                                 LOGGING_LEVEL, PAGINATE_BY)
84 89
from astakos.im.tasks import request_billing
90
from astakos.im.api.callpoint import AstakosDjangoDBCallpoint
85 91

  
86 92
logger = logging.getLogger(__name__)
87 93

  
......
89 95
DB_REPLACE_GROUP_SCHEME = """REPLACE(REPLACE("auth_group".name, 'http://', ''),
90 96
                                     'https://', '')"""
91 97

  
98
callpoint = AstakosDjangoDBCallpoint()
99

  
92 100
def render_response(template, tab=None, status=200, reset_cookie=False,
93 101
                    context_instance=None, **kwargs):
94 102
    """
......
215 223
        if inviter.invitations > 0:
216 224
            if form.is_valid():
217 225
                try:
218
                    invitation = form.save()
219
                    invite_func(invitation, inviter)
220
                    message = _('Invitation sent to %s' % invitation.username)
226
                    email = form.cleaned_data.get('username')
227
                    realname = form.cleaned_data.get('realname')
228
                    inviter.invite(email, realname)
229
                    message = _('Invitation sent to %s' % email)
221 230
                    messages.success(request, message)
222 231
                except SendMailError, e:
223 232
                    message = e.message
......
466 475
        return response
467 476
    messages.success(request, _('You have successfully logged out.'))
468 477
    context = get_context(request, extra_context)
469
    response.write(template_loader.render_to_string(template, context_instance=context))
478
    response.write(
479
        template_loader.render_to_string(template, context_instance=context))
470 480
    return response
471 481

  
472 482

  
......
558 568
            pass
559 569

  
560 570
    if not term:
571
        messages.error(request, 'There are no approval terms.')
561 572
        return HttpResponseRedirect(reverse('index'))
562 573
    f = open(term.location, 'r')
563 574
    terms = f.read()
......
591 602
                           password_change_form=ExtendedPasswordChangeForm)
592 603

  
593 604

  
605
@require_http_methods(["GET", "POST"])
594 606
@signed_terms_required
595 607
@login_required
596 608
@transaction.commit_manually
......
688 700

  
689 701
            # send notification
690 702
            try:
691
                send_admin_notification(
703
                send_group_creation_notification(
692 704
                    template_name='im/group_creation_notification.txt',
693 705
                    dictionary={
694 706
                        'group': new_object,
695 707
                        'owner': request.user,
696 708
                        'policies': policies,
697
                    },
698
                    subject='%s alpha2 testing group creation notification' % SITENAME
709
                    }
699 710
                )
700 711
            except SendNotificationError, e:
701 712
                messages.error(request, e, fail_silently=True)
......
755 766
            d['own'].append(g)
756 767
        else:
757 768
            d['other'].append(g)
758
    
769

  
759 770
    # validate sorting
760 771
    fields = ('own', 'other')
761 772
    for f in fields:
......
765 776
            if not form.is_valid():
766 777
                globals()['%s_sorting' % f] = form.cleaned_data.get('sort_by')
767 778
    return object_list(request, queryset=none,
768
                       extra_context={'is_search':False,
779
                       extra_context={'is_search': False,
769 780
                                      'mine': d['own'],
770 781
                                      'other': d['other'],
771 782
                                      'own_sorting': own_sorting,
......
792 803
                        THEN 1 ELSE 0 END""" % request.user.id,
793 804
        'kindname': """SELECT name FROM im_groupkind
794 805
                       WHERE id = im_astakosgroup.kind_id"""})
795
    
806

  
796 807
    model = q.model
797 808
    context_processors = None
798 809
    mimetype = None
......
801 812
    except AstakosGroup.DoesNotExist:
802 813
        raise Http404("No %s found matching the query" % (
803 814
            model._meta.verbose_name))
804
    
815

  
805 816
    update_form = AstakosGroupUpdateForm(instance=obj)
806 817
    addmembers_form = AddGroupMembersForm()
807 818
    if request.method == 'POST':
808 819
        update_data = {}
809 820
        addmembers_data = {}
810
        for k,v in request.POST.iteritems():
821
        for k, v in request.POST.iteritems():
811 822
            if k in update_form.fields:
812 823
                update_data[k] = v
813 824
            if k in addmembers_form.fields:
......
821 832
        if addmembers_form.is_valid():
822 833
            map(obj.approve_member, addmembers_form.valid_users)
823 834
            addmembers_form = AddGroupMembersForm()
824
    
825
    template_name = "%s/%s_detail.html" % (model._meta.app_label, model._meta.object_name.lower())
835

  
836
    template_name = "%s/%s_detail.html" % (
837
        model._meta.app_label, model._meta.object_name.lower())
826 838
    t = template_loader.get_template(template_name)
827 839
    c = RequestContext(request, {
828 840
        'object': obj,
829 841
    }, context_processors)
830
    
842

  
831 843
    # validate sorting
832
    sorting= request.GET.get('sorting')
844
    sorting = request.GET.get('sorting')
833 845
    if sorting:
834 846
        form = MembersSortForm({'sort_by': sorting})
835 847
        if form.is_valid():
836 848
            sorting = form.cleaned_data.get('sort_by')
837
         
849

  
838 850
    extra_context = {'update_form': update_form,
839 851
                     'addmembers_form': addmembers_form,
840 852
                     'page': request.GET.get('page', 1),
......
845 857
        else:
846 858
            c[key] = value
847 859
    response = HttpResponse(t.render(c), mimetype=mimetype)
848
    populate_xheaders(request, response, model, getattr(obj, obj._meta.pk.name))
860
    populate_xheaders(
861
        request, response, model, getattr(obj, obj._meta.pk.name))
849 862
    return response
850 863

  
851 864

  
......
865 878
        queryset = queryset.filter(name__contains=q)
866 879
        queryset = queryset.filter(approval_date__isnull=False)
867 880
        queryset = queryset.extra(select={
868
                'groupname': DB_REPLACE_GROUP_SCHEME,
869
                'kindname': "im_groupkind.name",
870
                'approved_members_num': """
881
                                  'groupname': DB_REPLACE_GROUP_SCHEME,
882
                                  'kindname': "im_groupkind.name",
883
                                  'approved_members_num': """
871 884
                    SELECT COUNT(*) FROM im_membership
872 885
                    WHERE group_id = im_astakosgroup.group_ptr_id
873 886
                    AND date_joined IS NOT NULL""",
874
                'membership_approval_date': """
887
                                  'membership_approval_date': """
875 888
                    SELECT date_joined FROM im_membership
876 889
                    WHERE group_id = im_astakosgroup.group_ptr_id
877 890
                    AND person_id = %s""" % request.user.id,
878
                'is_member': """
891
                                  'is_member': """
879 892
                    SELECT CASE WHEN EXISTS(
880 893
                    SELECT date_joined FROM im_membership
881 894
                    WHERE group_id = im_astakosgroup.group_ptr_id
882 895
                    AND person_id = %s)
883 896
                    THEN 1 ELSE 0 END""" % request.user.id,
884
                'is_owner': """
897
                                  'is_owner': """
885 898
                    SELECT CASE WHEN EXISTS(
886 899
                    SELECT id FROM im_astakosuser_owner
887 900
                    WHERE astakosgroup_id = im_astakosgroup.group_ptr_id
......
903 916
                           q=q,
904 917
                           sorting=sorting))
905 918

  
919

  
906 920
@signed_terms_required
907 921
@login_required
908 922
def group_all(request, extra_context=None, **kwargs):
......
930 944
        # TODO check sorting value
931 945
        q = q.order_by(sorting)
932 946
    return object_list(
933
                request,
934
                q,
935
                paginate_by=PAGINATE_BY,
936
                page=request.GET.get('page') or 1,
937
                template_name='im/astakosgroup_list.html',
938
                extra_context=dict(form=AstakosGroupSearchForm(),
939
                                   is_search=True,
940
                                   sorting=sorting))
947
        request,
948
        q,
949
        paginate_by=PAGINATE_BY,
950
        page=request.GET.get('page') or 1,
951
        template_name='im/astakosgroup_list.html',
952
        extra_context=dict(form=AstakosGroupSearchForm(),
953
                           is_search=True,
954
                           sorting=sorting))
941 955

  
942 956

  
943 957
@signed_terms_required
......
1031 1045
@signed_terms_required
1032 1046
@login_required
1033 1047
def resource_list(request):
1034
    if request.method == 'POST':
1035
        form = PickResourceForm(request.POST)
1036
        if form.is_valid():
1037
            r = form.cleaned_data.get('resource')
1038
            if r:
1039
                groups = request.user.membership_set.only('group').filter(
1040
                    date_joined__isnull=False)
1041
                groups = [g.group_id for g in groups]
1042
                q = AstakosGroupQuota.objects.select_related().filter(
1043
                    resource=r, group__in=groups)
1044
    else:
1045
        form = PickResourceForm()
1046
        q = AstakosGroupQuota.objects.none()
1047
        
1048
    data ={
1049
        'resources':[{
1050
            'name': 'vm',
1051
            'description': 'Number Of Vms',
1052
            'unit':'',
1053
            'maxValue':'1',
1054
            'currValue':'1'
1055
            },{
1056
            'name': 'ram',
1057
            'description':'Total Ram Usage',
1058
            'unit':'GB',
1059
            'maxValue':'4',
1060
            'currValue':'1' 
1061
            },{
1062
            'name': 'storage', 
1063
            'description':'Total Disk Space Used',
1064
            'unit':'GB',
1065
            'maxValue':'200',
1066
            'currValue':'180'             
1067
            },{
1068
            'name': 'disk', 
1069
            'description':'Disks Used',
1070
            'unit':'GB',
1071
            'maxValue':'16',
1072
            'currValue':'16'
1073
            },{
1074
            'name': 'network', 
1075
            'description':'Private Networks Used',
1076
            'unit':'',
1077
            'maxValue':'2',
1078
            'currValue':'1'
1079
            },{
1080
            'name': 'bandwidth', 
1081
            'description':'Bandwidth Monitoring Device',
1082
            'unit':'Gbps',
1083
            'maxValue':'200',
1084
            'currValue':'50'
1085
            }]              
1086
    } 
1087
    
1048
#     if request.method == 'POST':
1049
#         form = PickResourceForm(request.POST)
1050
#         if form.is_valid():
1051
#             r = form.cleaned_data.get('resource')
1052
#             if r:
1053
#                 groups = request.user.membership_set.only('group').filter(
1054
#                     date_joined__isnull=False)
1055
#                 groups = [g.group_id for g in groups]
1056
#                 q = AstakosGroupQuota.objects.select_related().filter(
1057
#                     resource=r, group__in=groups)
1058
#     else:
1059
#         form = PickResourceForm()
1060
#         q = AstakosGroupQuota.objects.none()
1061
#
1062
#     return object_list(request, q,
1063
#                        template_name='im/astakosuserquota_list.html',
1064
#                        extra_context={'form': form, 'data':data})
1065

  
1088 1066
    def with_class(entry):
1089 1067
        entry['load_class'] = 'red'
1090 1068
        max_value = float(entry['maxValue'])
1091 1069
        curr_value = float(entry['currValue'])
1092
        entry['ratio'] = (curr_value/max_value)*100
1070
        entry['ratio'] = (curr_value / max_value) * 100
1093 1071
        if entry['ratio'] < 66:
1094
            entry['load_class']='yellow'
1072
            entry['load_class'] = 'yellow'
1095 1073
        if entry['ratio'] < 33:
1096
            entry['load_class']='green'
1097
        
1098
        return entry 
1099
    
1074
            entry['load_class'] = 'green'
1075

  
1076
        return entry
1077

  
1100 1078
    def pluralize(entry):
1101
        if entry['unit'] == '':
1102
            entry['plural'] = entry['name']+'s'
1103
        else:
1104
            entry['plural'] = entry['name']
1105
        
1106
        return entry       
1079
        entry['plural'] = engine.plural(entry.get('name'))
1080
        return entry
1081

  
1082
    c = AstakosDjangoDBCallpoint()
1083
    try:
1084
        data = c.get_user_status(request.user.id)
1085
    except Exception, e:
1086
        data = None
1087
        messages.error(request, e)
1088
    else:
1089
        backenddata = map(with_class, data)
1090
        data = map(pluralize, data)
1091
    return render_response('im/resource_list.html',
1092
                           data=data,
1093
                           context_instance=get_context(request))
1107 1094

  
1108
    data['resources'] = map(with_class, data['resources']) 
1109
    data['resources'] = map(pluralize, data['resources'])        
1095
@signed_terms_required
1096
@login_required
1097
def group_create_demo(request, kind_name='default'):
1098
    resources = callpoint.list_resources()
1099
    resource_catalog = {'resources':defaultdict(defaultdict),
1100
                        'groups':defaultdict(list)}
1101
    for r in resources:
1102
        service = r.get('service', '')
1103
        name = r.get('name', '')
1104
        group = r.get('group', '')
1105
        unit = r.get('unit', '')
1106
        fullname = '%s%s%s' % (service, RESOURCE_SEPARATOR, name)
1107
        resource_catalog['resources'][fullname] = dict(unit=unit)
1108
        resource_catalog['groups'][group].append(fullname)
1110 1109
    
1111
    return object_list(request, q,
1112
                       template_name='im/astakosuserquota_list.html',
1113
                       extra_context={'form': form, 'data':data})
1110
    resource_catalog = dict(resource_catalog)
1111
    for k, v in resource_catalog.iteritems():
1112
        resource_catalog[k] = dict(v)
1113
    try:
1114
        kind = GroupKind.objects.get(name=kind_name)
1115
    except:
1116
        return HttpResponseBadRequest(_('No such group kind'))
1114 1117

  
1118
    post_save_redirect = '/im/group/%(id)s/'
1119
    context_processors = None
1120
    model, form_class = get_model_and_form_class(
1121
        model=None,
1122
        form_class=AstakosGroupCreationForm
1123
    )
1124
    
1125
    if request.method == 'POST':
1126
        form = form_class(request.POST, request.FILES)
1127
        if form.is_valid():
1128
            new_object = form.save()
1129
            new_object.policies = form.policies()
1115 1130

  
1131
            # save owner
1132
            new_object.owners = [request.user]
1133
            
1134
            msg = _("The %(verbose_name)s was created successfully.") %\
1135
                {"verbose_name": model._meta.verbose_name}
1136
            messages.success(request, msg, fail_silently=True)
1116 1137

  
1117
def group_create_demo(request):
1118
    
1119
    resource_catalog = {
1120
        'groups': {
1121
            'compute': {
1122
                'cyclades.vm':  { 'unit': 'number' }, 
1123
                'cyclades.ram': { 'unit': 'bytes' }, 
1124
                'cyclades.cpu': { 'unit': 'number' }
1125
            },
1126
            'storage': {
1127
                'pithos.diskspace' : { 'unit': 'mebibytes' }
1128
            }
1138
            # send notification
1139
            try:
1140
                send_group_creation_notification(
1141
                    template_name='im/group_creation_notification.txt',
1142
                    dictionary={
1143
                        'group': new_object,
1144
                        'owner': request.user,
1145
                        'policies': list(form.policies()),
1146
                    }
1147
                )
1148
            except SendNotificationError, e:
1149
                messages.error(request, e, fail_silently=True)
1150
            return HttpResponseRedirect(post_save_redirect % new_object.__dict__)
1151
    else:
1152
        now = datetime.now()
1153
        data = {
1154
            'kind': kind
1129 1155
        }
1130
    }
1131
    
1132
    
1133
    return render_response(
1134
        template='im/astakosgroup_form_demo.html',
1135
        context_instance=get_context(request),
1136
        resource_catalog=resource_catalog,
1137
        groups=resource_catalog['groups'] )
1138
     
1156
        form = form_class(data)
1157

  
1158
    # Create the template, context, response
1159
    template_name = "%s/%s_form_demo.html" % (
1160
        model._meta.app_label,
1161
        model._meta.object_name.lower()
1162
    )
1163
    t = template_loader.get_template(template_name)
1164
    c = RequestContext(request, {
1165
        'form': form,
1166
        'kind': kind,
1167
        'resource_catalog':resource_catalog
1168
    }, context_processors)
1169
    return HttpResponse(t.render(c))
1139 1170

  
1140 1171

  
1141 1172
def group_create_list(request):
1142
    form = PickResourceForm()
1173
    form = P ickResourceForm()
1143 1174
    return render_response(
1144 1175
        template='im/astakosgroup_create_list.html',
1145 1176
        context_instance=get_context(request),)
......
1148 1179
@signed_terms_required
1149 1180
@login_required
1150 1181
def billing(request):
1151
    
1182

  
1152 1183
    today = datetime.today()
1153
    month_last_day= calendar.monthrange(today.year, today.month)[1]
1154
    data['resources'] = map(with_class,data['resources'])        
1184
    month_last_day = calendar.monthrange(today.year, today.month)[1]
1185
    data['resources'] = map(with_class, data['resources'])
1155 1186
    start = request.POST.get('datefrom', None)
1156 1187
    if start:
1157 1188
        today = datetime.fromtimestamp(int(start))
1158
        month_last_day= calendar.monthrange(today.year, today.month)[1]
1159
    
1189
        month_last_day = calendar.monthrange(today.year, today.month)[1]
1190

  
1160 1191
    start = datetime(today.year, today.month, 1).strftime("%s")
1161 1192
    end = datetime(today.year, today.month, month_last_day).strftime("%s")
1162 1193
    r = request_billing.apply(args=('pgerakios@grnet.gr',
1163 1194
                                    int(start) * 1000,
1164 1195
                                    int(end) * 1000))
1165 1196
    data = {}
1166
    
1197

  
1167 1198
    try:
1168 1199
        status, data = r.result
1169
        data=_clear_billing_data(data)
1200
        data = _clear_billing_data(data)
1170 1201
        if status != 200:
1171 1202
            messages.error(request, _('Service response status: %d' % status))
1172 1203
    except:
1173 1204
        messages.error(request, r.result)
1174
    
1205

  
1175 1206
    print type(start)
1176
    
1207

  
1177 1208
    return render_response(
1178 1209
        template='im/billing.html',
1179 1210
        context_instance=get_context(request),
1180 1211
        data=data,
1181
        zerodate=datetime(month=1,year=1970, day=1),
1212
        zerodate=datetime(month=1, year=1970, day=1),
1182 1213
        today=today,
1183 1214
        start=int(start),
1184
        month_last_day=month_last_day)  
1185
    
1215
        month_last_day=month_last_day)
1216

  
1217

  
1186 1218
def _clear_billing_data(data):
1187
    
1219

  
1188 1220
    # remove addcredits entries
1189 1221
    def isnotcredit(e):
1190 1222
        return e['serviceName'] != "addcredits"
1191
    
1192
    
1193
    
1194
    # separate services    
1223

  
1224
    # separate services
1195 1225
    def servicefilter(service_name):
1196 1226
        service = service_name
1227

  
1197 1228
        def fltr(e):
1198 1229
            return e['serviceName'] == service
1199 1230
        return fltr
1200
        
1201
    
1231

  
1202 1232
    data['bill_nocredits'] = filter(isnotcredit, data['bill'])
1203 1233
    data['bill_vmtime'] = filter(servicefilter('vmtime'), data['bill'])
1204 1234
    data['bill_diskspace'] = filter(servicefilter('diskspace'), data['bill'])
1205 1235
    data['bill_addcredits'] = filter(servicefilter('addcredits'), data['bill'])
1206
        
1236

  
1207 1237
    return data
1208 1238

  
1209 1239

  
1240
def group_create_demo(request):
1241
    return render_response(
1242
        template='im/astakosgroup_form_demo.html',
1243
        context_instance=get_context(request))
1244

  
1245
    return data
1210 1246
     
1211 1247
     
1212 1248
@signed_terms_required
......
1226 1262
                               'event name', 'event date',
1227 1263
                               'incremental cost', 'total cost')
1228 1264
            timeline_body = timeline_charge(
1229
                                    data['entity'],     data['resource'],
1230
                                    data['start_date'], data['end_date'],
1231
                                    data['details'],    data['operation'])
1232
        
1265
                data['entity'], data['resource'],
1266
                data['start_date'], data['end_date'],
1267
                data['details'], data['operation'])
1268

  
1233 1269
    return render_response(template='im/timeline.html',
1234 1270
                           context_instance=get_context(request),
1235 1271
                           form=form,

Also available in: Unified diff