d54387f37eb29c1b96cf7f2d8d90250835816f53
[plstackapi.git] / planetstack / core / admin.py
1 from core.models import Site
2 from core.models import *
3 from openstack.manager import OpenStackManager
4
5 from django.contrib import admin
6 from django.contrib.auth.models import Group
7 from django import forms
8 from django.utils.safestring import mark_safe
9 from django.contrib.auth.admin import UserAdmin
10 from django.contrib.admin.widgets import FilteredSelectMultiple
11 from django.contrib.auth.forms import ReadOnlyPasswordHashField
12 from django.contrib.auth.signals import user_logged_in
13 from django.utils import timezone
14 import django_evolution 
15
16
17 class ReadonlyTabularInline(admin.TabularInline):
18     can_delete = False
19     extra = 0
20     editable_fields = []
21
22     def get_readonly_fields(self, request, obj=None):
23         fields = []
24         for field in self.model._meta.get_all_field_names():
25             if (not field == 'id'):
26                 if (field not in self.editable_fields):
27                     fields.append(field)
28         return fields
29
30     def has_add_permission(self, request):
31         return False
32
33 class SliverInline(admin.TabularInline):
34     model = Sliver
35     fields = ['ip', 'instance_name', 'slice', 'numberCores', 'image', 'key', 'node', 'deploymentNetwork']
36     extra = 0
37     #readonly_fields = ['ip', 'instance_name', 'image']
38     readonly_fields = ['ip', 'instance_name']
39     
40
41 class SiteInline(admin.TabularInline):
42     model = Site
43     extra = 0
44
45 class UserInline(admin.TabularInline):
46     model = User
47     fields = ['email', 'firstname', 'lastname']
48     extra = 0
49
50 class SliceInline(admin.TabularInline):
51     model = Slice
52     extra = 0
53
54 class RoleInline(admin.TabularInline):
55     model = Role
56     extra = 0 
57
58 class NodeInline(admin.TabularInline):
59     model = Node
60     extra = 0
61
62 class SitePrivilegeInline(admin.TabularInline):
63     model = SitePrivilege
64     extra = 0
65
66     def formfield_for_foreignkey(self, db_field, request, **kwargs):
67         if db_field.name == 'site':
68             if not request.user.is_admin:
69                 # only show sites where user is an admin or pi
70                 roles = Role.objects.filter(role_type__in=['admin', 'pi'])
71                 site_privileges = SitePrivilege.objects.filter(user=request.user).filter(role__in=roles)
72                 login_bases = [site_privilege.site.login_base for site_privilege in site_privileges]
73                 sites = Site.objects.filter(login_base__in=login_bases)
74                 kwargs['queryset'] = sites
75
76         if db_field.name == 'user':
77             if not request.user.is_admin:
78                 # only show users from sites where caller has admin or pi role
79                 roles = Role.objects.filter(role_type__in=['admin', 'pi'])
80                 site_privileges = SitePrivilege.objects.filter(user=request.user).filter(role__in=roles)
81                 sites = [site_privilege.site for site_privilege in site_privileges]
82                 site_privileges = SitePrivilege.objects.filter(site__in=sites)
83                 emails = [site_privilege.user.email for site_privilege in site_privileges]
84                 users = User.objects.filter(email__in=emails)
85                 kwargs['queryset'] = users
86         return super(SitePrivilegeInline, self).formfield_for_foreignkey(db_field, request, **kwargs)
87
88 class SliceMembershipInline(admin.TabularInline):
89     model = SliceMembership
90     extra = 0
91
92     def formfield_for_foreignkey(self, db_field, request, **kwargs):
93         if db_field.name == 'slice':
94             if not request.user.is_admin:
95                 # only show slices at sites where caller has admin or pi role
96                 roles = Role.objects.filter(role_type__in=['admin', 'pi'])
97                 site_privileges = SitePrivilege.objects.filter(user=request.user).filter(role__in=roles)
98                 sites = [site_privilege.site for site_privilege in site_privileges]
99                 slices = Slice.objects.filter(site__in=sites)
100                 kwargs['queryset'] = slices 
101         if db_field.name == 'user':
102             if not request.user.is_admin:
103                 # only show users from sites where caller has admin or pi role
104                 roles = Role.objects.filter(role_type__in=['admin', 'pi'])
105                 site_privileges = SitePrivilege.objects.filter(user=request.user).filter(role__in=roles)
106                 sites = [site_privilege.site for site_privilege in site_privileges]
107                 site_privileges = SitePrivilege.objects.filter(site__in=sites)
108                 emails = [site_privilege.user.email for site_privilege in site_privileges]   
109                 users = User.objects.filter(email__in=emails) 
110                 kwargs['queryset'] = list(users)
111
112         return super(SliceMembershipInline, self).formfield_for_foreignkey(db_field, request, **kwargs)
113
114 class SliceTagInline(admin.TabularInline):
115     model = SliceTag
116     extra = 0
117
118 class PlainTextWidget(forms.HiddenInput):
119     input_type = 'hidden'
120
121     def render(self, name, value, attrs=None):
122         if value is None:
123             value = ''
124         return mark_safe(str(value) + super(PlainTextWidget, self).render(name, value, attrs))
125
126 class PlanetStackBaseAdmin(admin.ModelAdmin):
127     save_on_top = False
128
129 class OSModelAdmin(PlanetStackBaseAdmin):
130     """Attach client connection to openstack on delete() and save()"""
131
132     def save_model(self, request, obj, form, change):
133         if request.user.site:
134             auth = request.session.get('auth', {})
135             auth['tenant'] = request.user.site.login_base
136             obj.os_manager = OpenStackManager(auth=auth, caller=request.user)
137         obj.save()
138
139     def delete_model(self, request, obj):
140         if request.user.site:
141             auth = request.session.get('auth', {})
142             auth['tenant'] = request.user.site.login_base
143             obj.os_manager = OpenStackManager(auth=auth, caller=request.user)
144         obj.delete() 
145
146 class RoleAdmin(OSModelAdmin):
147     fieldsets = [
148         ('Role', {'fields': ['role_type']})
149     ]
150     list_display = ('role_type',)
151
152
153 class DeploymentAdminForm(forms.ModelForm):
154     sites = forms.ModelMultipleChoiceField(
155         queryset=Site.objects.all(),
156         required=False,
157         widget=FilteredSelectMultiple(
158             verbose_name=('Sites'), is_stacked=False
159         )
160     )
161     class Meta:
162         model = Deployment
163
164     def __init__(self, *args, **kwargs):
165         super(DeploymentAdminForm, self).__init__(*args, **kwargs)
166
167         if self.instance and self.instance.pk:
168             self.fields['sites'].initial = self.instance.sites.all()
169
170     def save(self, commit=True):
171         deploymentNetwork = super(DeploymentAdminForm, self).save(commit=False)
172         if commit:
173             deploymentNetwork.save()
174
175         if deploymentNetwork.pk:
176             deploymentNetwork.sites = self.cleaned_data['sites']
177             self.save_m2m()
178
179         return deploymentNetwork
180
181 class DeploymentAdmin(PlanetStackBaseAdmin):
182     form = DeploymentAdminForm
183     inlines = [NodeInline,SliverInline]
184
185     def get_formsets(self, request, obj=None):
186         for inline in self.get_inline_instances(request, obj):
187             # hide MyInline in the add view
188             if obj is None:
189                 continue
190             # give inline object access to driver and caller
191             auth = request.session.get('auth', {})
192             if request.user.site:
193                 auth['tenant'] = request.user.site.login_base
194             inline.model.os_manager = OpenStackManager(auth=auth, caller=request.user)
195             yield inline.get_formset(request, obj)
196
197 class SiteAdmin(OSModelAdmin):
198     fieldsets = [
199         (None, {'fields': ['name', 'site_url', 'enabled', 'is_public', 'login_base']}),
200         ('Location', {'fields': ['latitude', 'longitude']}),
201         ('Deployment Networks', {'fields': ['deployments']})
202     ]
203     list_display = ('name', 'login_base','site_url', 'enabled')
204     filter_horizontal = ('deployments',)
205     inlines = [NodeInline, UserInline, SitePrivilegeInline]
206     search_fields = ['name']
207
208     def queryset(self, request):
209         # admins can see all keys. Users can only see sites they belong to.
210         qs = super(SiteAdmin, self).queryset(request)
211         if not request.user.is_admin:
212             valid_sites = [request.user.site.login_base]
213             roles = request.user.get_roles()
214             for tenant_list in roles.values():
215                 valid_sites.extend(tenant_list)
216             qs = qs.filter(login_base__in=valid_sites)
217         return qs
218
219     def get_formsets(self, request, obj=None):
220         for inline in self.get_inline_instances(request, obj):
221             # hide MyInline in the add view
222             if obj is None:
223                 continue
224             # give inline object access to driver and caller
225             auth = request.session.get('auth', {})
226             #auth['tenant'] = request.user.site.login_base
227             inline.model.os_manager = OpenStackManager(auth=auth, caller=request.user)
228             yield inline.get_formset(request, obj)
229
230 class SitePrivilegeAdmin(PlanetStackBaseAdmin):
231     fieldsets = [
232         (None, {'fields': ['user', 'site', 'role']})
233     ]
234     list_display = ('user', 'site', 'role')
235
236     def formfield_for_foreignkey(self, db_field, request, **kwargs):
237         if db_field.name == 'site':
238             if not request.user.is_admin:
239                 # only show sites where user is an admin or pi
240                 sites = set()
241                 for site_privilege in SitePrivilege.objects.filer(user=request.user):
242                     if site_privilege.role.role_type in ['admin', 'pi']:
243                         sites.add(site_privilege.site)
244                 kwargs['queryset'] = Site.objects.filter(site__in=list(sites))
245
246         if db_field.name == 'user':
247             if not request.user.is_admin:
248                 # only show users from sites where caller has admin or pi role
249                 roles = Role.objects.filter(role_type__in=['admin', 'pi'])
250                 site_privileges = SitePrivilege.objects.filter(user=request.user).filter(role__in=roles)
251                 sites = [site_privilege.site for site_privilege in site_privileges]
252                 site_privileges = SitePrivilege.objects.filter(site__in=sites)
253                 emails = [site_privilege.user.email for site_privilege in site_privileges]
254                 users = User.objects.filter(email__in=emails)
255                 kwargs['queryset'] = users
256
257         return super(SitePrivilegeAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)
258
259     def queryset(self, request):
260         # admins can see all privileges. Users can only see privileges at sites
261         # where they have the admin role or pi role.
262         qs = super(SitePrivilegeAdmin, self).queryset(request)
263         if not request.user.is_admin:
264             roles = Role.objects.filter(role_type__in=['admin', 'pi'])
265             site_privileges = SitePrivilege.objects.filter(user=request.user).filter(role__in=roles)
266             login_bases = [site_privilege.site.login_base for site_privilege in site_privileges]
267             sites = Site.objects.filter(login_base__in=login_bases)
268             qs = qs.filter(site__in=sites)
269         return qs
270
271     def save_model(self, request, obj, form, change):
272         # update openstack connection to use this site/tenant   
273         auth = request.session.get('auth', {})
274         #auth['tenant'] = obj.site.login_base
275         obj.os_manager = OpenStackManager(auth=auth, caller=request.user)
276         obj.save()
277
278     def delete_model(self, request, obj):
279         # update openstack connection to use this site/tenant   
280         auth = request.session.get('auth', {})
281         #auth['tenant'] = obj.site.login_base
282         obj.os_manager = OpenStackManager(auth=auth, caller=request.user)
283         obj.delete()
284
285 class KeyAdmin(OSModelAdmin):
286     fieldsets = [
287         ('Key', {'fields': ['key', 'type', 'blacklisted']})
288     ]
289     list_display = ['key', 'type', 'blacklisted']
290
291     #def queryset(self, request):
292         # admins can see all keys. Users can only see their own key.
293         #if request.user.is_admin:
294         #    qs = super(KeyAdmin, self).queryset(request) 
295         #else:
296         #    qs = Key.objects.filter(user=request.user)
297         #return qs
298
299 class SliceAdmin(OSModelAdmin):
300     fields = ['name', 'site', 'serviceClass', 'description', 'slice_url']
301     list_display = ('name', 'site','serviceClass', 'slice_url')
302     inlines = [SliverInline, SliceMembershipInline, SliceTagInline]
303
304     def formfield_for_foreignkey(self, db_field, request, **kwargs):
305         if db_field.name == 'site':
306             if not request.user.is_admin:
307                 # only show sites where user is a pi or admin 
308                 roles = Role.objects.filter(role_type__in=['admin', 'pi'])
309                 site_privileges = SitePrivilege.objects.filter(user=request.user).filter(role__in=roles)
310                 login_bases = [site_privilege.site.login_base for site_privilege in site_privileges]
311                 sites = Site.objects.filter(login_base__in=login_bases)
312                 kwargs['queryset'] = sites
313
314         return super(SliceAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)
315
316     def queryset(self, request):
317         # admins can see all keys. Users can only see slices they belong to.
318         qs = super(SliceAdmin, self).queryset(request)
319         if not request.user.is_admin:
320             valid_slices = []
321             roles = request.user.get_roles()
322             for tenant_list in roles.values():
323                 valid_slices.extend(tenant_list)
324             qs = qs.filter(name__in=valid_slices)
325         return qs
326
327     def get_formsets(self, request, obj=None):
328         for inline in self.get_inline_instances(request, obj):
329             # hide MyInline in the add view
330             if obj is None:
331                 continue
332             # give inline object access to driver and caller
333             auth = request.session.get('auth', {})
334             auth['tenant'] = obj.name       # meed to connect using slice's tenant
335             inline.model.os_manager = OpenStackManager(auth=auth, caller=request.user)
336             yield inline.get_formset(request, obj)
337
338     def get_queryset(self, request):
339         qs = super(SliceAdmin, self).get_queryset(request)
340         if request.user.is_superuser:
341             return qs
342         # users can only see slices at their site
343         return qs.filter(site=request.user.site) 
344
345 class SliceMembershipAdmin(PlanetStackBaseAdmin):
346     fieldsets = [
347         (None, {'fields': ['user', 'slice', 'role']})
348     ]
349     list_display = ('user', 'slice', 'role')
350
351     def formfield_for_foreignkey(self, db_field, request, **kwargs):
352         if db_field.name == 'slice':
353             if not request.user.is_admin:
354                 # only show slices at sites where caller has admin or pi role
355                 roles = Role.objects.filter(role_type__in=['admin', 'pi'])
356                 site_privileges = SitePrivilege.objects.filter(user=request.user).filter(role__in=roles)
357                 sites = [site_privilege.site for site_privilege in site_privileges]
358                 slices = Slice.objects.filter(site__in=sites)
359                 kwargs['queryset'] = slices
360         
361         if db_field.name == 'user':
362             if not request.user.is_admin:
363                 # only show users from sites where caller has admin or pi role
364                 roles = Role.objects.filter(role_type__in=['admin', 'pi'])
365                 site_privileges = SitePrivilege.objects.filter(user=request.user).filter(role__in=roles)
366                 sites = [site_privilege.site for site_privilege in site_privileges]
367                 site_privileges = SitePrivilege.objects.filter(site__in=sites)
368                 emails = [site_privilege.user.email for site_privilege in site_privileges]
369                 users = User.objects.filter(email__in=emails)
370                 kwargs['queryset'] = users
371
372         return super(SliceMembershipAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)
373
374     def queryset(self, request):
375         # admins can see all memberships. Users can only see memberships of
376         # slices where they have the admin role.
377         qs = super(SliceMembershipAdmin, self).queryset(request)
378         if not request.user.is_admin:
379             roles = Role.objects.filter(role_type__in=['admin', 'pi'])
380             site_privileges = SitePrivilege.objects.filter(user=request.user).filter(role__in=roles)
381             login_bases = [site_privilege.site.login_base for site_privilege in site_privileges]
382             sites = Site.objects.filter(login_base__in=login_bases)
383             slices = Slice.objects.filter(site__in=sites)
384             qs = qs.filter(slice__in=slices)
385         return qs
386
387     def save_model(self, request, obj, form, change):
388         # update openstack connection to use this site/tenant
389         auth = request.session.get('auth', {})
390         auth['tenant'] = obj.slice.name
391         obj.os_manager = OpenStackManager(auth=auth, caller=request.user)
392         obj.save()
393
394     def delete_model(self, request, obj):
395         # update openstack connection to use this site/tenant
396         auth = request.session.get('auth', {})
397         auth['tenant'] = obj.slice.name
398         obj.os_manager = OpenStackManager(auth=auth, caller=request.user)
399         obj.delete()
400
401
402 class ImageAdmin(admin.ModelAdmin):
403     fields = ['image_id', 'name', 'disk_format', 'container_format']
404
405 class NodeAdmin(admin.ModelAdmin):
406     list_display = ('name', 'site', 'deployment')
407     list_filter = ('deployment',)
408
409
410 class SliverForm(forms.ModelForm):
411     class Meta:
412         model = Sliver
413         ip = forms.CharField(widget=PlainTextWidget)
414         instance_name = forms.CharField(widget=PlainTextWidget)
415         widgets = {
416             'ip': PlainTextWidget(),
417             'instance_name': PlainTextWidget(),
418         }
419
420 class SliverAdmin(PlanetStackBaseAdmin):
421     form = SliverForm
422     fieldsets = [
423         ('Sliver', {'fields': ['ip', 'instance_name', 'slice', 'numberCores', 'image', 'key', 'node', 'deploymentNetwork']})
424     ]
425     list_display = ['ip', 'instance_name', 'slice', 'numberCores', 'image', 'key', 'node', 'deploymentNetwork']
426
427     def formfield_for_foreignkey(self, db_field, request, **kwargs):
428         if db_field.name == 'slice':
429             if not request.user.is_admin:
430                 slices = set([sm.slice.name for sm in SliceMembership.objects.filter(user=request.user)]) 
431                 kwargs['queryset'] = Slice.objects.filter(name__in=list(slices))
432
433         return super(SliverAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)
434
435     def queryset(self, request):
436         # admins can see all slivers. Users can only see slivers of 
437         # the slices they belong to.
438         qs = super(SliverAdmin, self).queryset(request)
439         if not request.user.is_admin:
440             tenants = []
441             roles = request.user.get_roles()
442             for tenant_list in roles.values():
443                 tenants.extend(tenant_list)
444             valid_slices = Slice.objects.filter(name__in=tenants)
445             qs = qs.filter(slice__in=valid_slices)
446         return qs
447
448     def get_formsets(self, request, obj=None):
449         # make some fields read only if we are updating an existing record
450         if obj == None:
451             #self.readonly_fields = ('ip', 'instance_name') 
452             self.readonly_fields = () 
453         else:
454             self.readonly_fields = () 
455             #self.readonly_fields = ('ip', 'instance_name', 'slice', 'image', 'key') 
456
457         for inline in self.get_inline_instances(request, obj):
458             # hide MyInline in the add view
459             if obj is None:
460                 continue
461             # give inline object access to driver and caller
462             auth = request.session.get('auth', {})
463             auth['tenant'] = obj.name       # meed to connect using slice's tenant
464             inline.model.os_manager = OpenStackManager(auth=auth, caller=request.user)
465             yield inline.get_formset(request, obj)
466
467     def save_model(self, request, obj, form, change):
468         # update openstack connection to use this site/tenant
469         auth = request.session.get('auth', {})
470         auth['tenant'] = obj.slice.name
471         obj.os_manager = OpenStackManager(auth=auth, caller=request.user)
472         obj.save()
473
474     def delete_model(self, request, obj):
475         # update openstack connection to use this site/tenant
476         auth = request.session.get('auth', {})
477         auth['tenant'] = obj.slice.name
478         obj.os_manager = OpenStackManager(auth=auth, caller=request.user)
479         obj.delete()
480
481 class UserCreationForm(forms.ModelForm):
482     """A form for creating new users. Includes all the required
483     fields, plus a repeated password."""
484     password1 = forms.CharField(label='Password', widget=forms.PasswordInput)
485     password2 = forms.CharField(label='Password confirmation', widget=forms.PasswordInput)
486
487     class Meta:
488         model = User
489         fields = ('email', 'firstname', 'lastname', 'phone', 'key', 'site')
490
491     def clean_password2(self):
492         # Check that the two password entries match
493         password1 = self.cleaned_data.get("password1")
494         password2 = self.cleaned_data.get("password2")
495         if password1 and password2 and password1 != password2:
496             raise forms.ValidationError("Passwords don't match")
497         return password2
498
499     def save(self, commit=True):
500         # Save the provided password in hashed format
501         user = super(UserCreationForm, self).save(commit=False)
502         user.password = self.cleaned_data["password1"]
503         #user.set_password(self.cleaned_data["password1"])
504         if commit:
505             user.save()
506         return user
507
508
509 class UserChangeForm(forms.ModelForm):
510     """A form for updating users. Includes all the fields on
511     the user, but replaces the password field with admin's
512     password hash display field.
513     """
514     password = ReadOnlyPasswordHashField()
515
516     class Meta:
517         model = User
518
519     def clean_password(self):
520         # Regardless of what the user provides, return the initial value.
521         # This is done here, rather than on the field, because the
522         # field does not have access to the initial value
523         return self.initial["password"]
524
525
526 class UserAdmin(UserAdmin, OSModelAdmin):
527     class Meta:
528         app_label = "core"
529
530     # The forms to add and change user instances
531     form = UserChangeForm
532     add_form = UserCreationForm
533
534     # The fields to be used in displaying the User model.
535     # These override the definitions on the base UserAdmin
536     # that reference specific fields on auth.User.
537     list_display = ('email', 'site', 'firstname', 'lastname', 'is_admin', 'last_login')
538     list_filter = ('site',)
539     inlines = [SitePrivilegeInline, SliceMembershipInline]
540     fieldsets = (
541         (None, {'fields': ('email', 'password', 'site', 'is_admin', 'timezone')}),
542         ('Personal info', {'fields': ('firstname','lastname','phone', 'key')}),
543         #('Important dates', {'fields': ('last_login',)}),
544     )
545     add_fieldsets = (
546         (None, {
547             'classes': ('wide',),
548             'fields': ('email', 'firstname', 'lastname', 'phone', 'site', 'key','password1', 'password2', 'is_admin')}
549         ),
550     )
551     search_fields = ('email',)
552     ordering = ('email',)
553     filter_horizontal = ()
554
555     def formfield_for_foreignkey(self, db_field, request, **kwargs):
556         if db_field.name == 'site':
557             if not request.user.is_admin:
558                 # show sites where caller is an admin or pi 
559                 sites = []
560                 for site_privilege in SitePrivilege.objects.filer(user=request.user):
561                     if site_privilege.role.role_type in ['admin', 'pi']:
562                         sites.append(site_privilege.site.login_base)  
563                 kwargs['queryset'] = Site.objects.filter(login_base__in(list(sites)))
564
565         return super(UserAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)
566
567 class ServiceResourceInline(admin.TabularInline):
568     model = ServiceResource
569     extra = 0
570
571 class ServiceClassAdmin(admin.ModelAdmin):
572     list_display = ('name', 'commitment', 'membershipFee')
573     inlines = [ServiceResourceInline]
574
575 class ReservedResourceInline(admin.TabularInline):
576     model = ReservedResource
577     extra = 0
578
579     def formfield_for_foreignkey(self, db_field, request=None, **kwargs):
580         field = super(ReservedResourceInline, self).formfield_for_foreignkey(db_field, request, **kwargs)
581
582         if db_field.name == 'resource':
583             # restrict resources to those that the slice's service class allows
584             if request._slice is not None:
585                 field.queryset = field.queryset.filter(serviceClass = request._slice.serviceClass, calendarReservable=True)
586                 if len(field.queryset) > 0:
587                     field.initial = field.queryset.all()[0]
588             else:\r
589                 field.queryset = field.queryset.none()\r
590         elif db_field.name == 'sliver':\r
591             # restrict slivers to those that belong to the slice\r
592             if request._slice is not None:\r
593                 field.queryset = field.queryset.filter(slice = request._slice)
594             else:
595                 field.queryset = field.queryset.none()\r
596 \r
597         return field
598
599 class ReservationChangeForm(forms.ModelForm):
600     class Meta:
601         model = Reservation
602
603 class ReservationAddForm(forms.ModelForm):
604     slice = forms.ModelChoiceField(queryset=Slice.objects.all(), widget=forms.Select(attrs={"onChange":"document.getElementById('id_refresh').value=1; submit()"}))
605     refresh = forms.CharField(widget=forms.HiddenInput())
606
607     class Media:
608        css = {'all': ('planetstack.css',)}   # .field-refresh { display: none; }
609
610     def clean_slice(self):
611         slice = self.cleaned_data.get("slice")
612         x = ServiceResource.objects.filter(serviceClass = slice.serviceClass, calendarReservable=True)
613         if len(x) == 0:
614             raise forms.ValidationError("The slice you selected does not have a service class that allows reservations")
615         return slice
616
617     class Meta:
618         model = Reservation
619
620 class ReservationAddRefreshForm(ReservationAddForm):
621     """ This form is displayed when the Reservation Form receives an update
622         from the Slice dropdown onChange handler. It doesn't validate the
623         data and doesn't save the data. This will cause the form to be
624         redrawn.
625     """
626
627     """ don't validate anything other than slice """
628     dont_validate_fields = ("startTime", "duration")
629
630     def full_clean(self):
631         result = super(ReservationAddForm, self).full_clean()
632
633         for fieldname in self.dont_validate_fields:
634             if fieldname in self._errors:
635                 del self._errors[fieldname]
636
637         return result
638
639     """ don't save anything """
640     def is_valid(self):
641         return False
642
643 class ReservationAdmin(admin.ModelAdmin):
644     list_display = ('startTime', 'duration')
645     inlines = [ReservedResourceInline]
646     form = ReservationAddForm
647
648     def add_view(self, request, form_url='', extra_context=None):
649         timezone.activate(request.user.timezone)
650         request._refresh = False
651         request._slice = None
652         if request.method == 'POST':
653             # "refresh" will be set to "1" if the form was submitted due to
654             # a change in the Slice dropdown.
655             if request.POST.get("refresh","1") == "1":
656                 request._refresh = True
657                 request.POST["refresh"] = "0"
658
659             # Keep track of the slice that was selected, so the
660             # reservedResource inline can filter items for the slice.
661             request._slice = request.POST.get("slice",None)
662             if (request._slice is not None):
663                 request._slice = Slice.objects.get(id=request._slice)
664
665         result =  super(ReservationAdmin, self).add_view(request, form_url, extra_context)
666         return result
667
668     def changelist_view(self, request, extra_context = None):
669         timezone.activate(request.user.timezone)
670         return super(ReservationAdmin, self).changelist_view(request, extra_context)
671
672     def get_form(self, request, obj=None, **kwargs):
673         request._obj_ = obj\r
674         if obj is not None:\r
675             # For changes, set request._slice to the slice already set in the\r
676             # object.\r
677             request._slice = obj.slice\r
678             self.form = ReservationChangeForm\r
679         else:\r
680             if getattr(request, "_refresh", False):\r
681                 self.form = ReservationAddRefreshForm\r
682             else:\r
683                 self.form = ReservationAddForm\r
684         return super(ReservationAdmin, self).get_form(request, obj, **kwargs)\r
685 \r
686     def get_readonly_fields(self, request, obj=None):
687         if (obj is not None):\r
688             # Prevent slice from being changed after the reservation has been\r
689             # created.\r
690             return ['slice']\r
691         else:\r
692             return []
693
694 # register a signal that caches the user's credentials when they log in
695 def cache_credentials(sender, user, request, **kwds):
696     auth = {'username': request.POST['username'],
697             'password': request.POST['password']}
698     request.session['auth'] = auth
699 user_logged_in.connect(cache_credentials)
700
701 # Now register the new UserAdmin...
702 admin.site.register(User, UserAdmin)
703 # ... and, since we're not using Django's builtin permissions,
704 # unregister the Group model from admin.
705 admin.site.unregister(Group)
706
707 #Do not show django evolution in the admin interface
708 from django_evolution.models import Version, Evolution
709 admin.site.unregister(Version)
710 admin.site.unregister(Evolution)
711
712
713 # When debugging it is often easier to see all the classes, but for regular use 
714 # only the top-levels should be displayed
715 showAll = False
716
717 admin.site.register(Deployment, DeploymentAdmin)
718 admin.site.register(Site, SiteAdmin)
719 admin.site.register(Slice, SliceAdmin)
720 #admin.site.register(Subnet)
721 admin.site.register(Key, KeyAdmin)
722
723
724 if showAll:
725     admin.site.register(Node, NodeAdmin)
726     admin.site.register(SliceMembership, SliceMembershipAdmin)
727     admin.site.register(SitePrivilege, SitePrivilegeAdmin)
728     admin.site.register(Role, RoleAdmin)
729     admin.site.register(Sliver, SliverAdmin)
730     admin.site.register(ServiceClass, ServiceClassAdmin)
731     admin.site.register(Reservation, ReservationAdmin)
732     admin.site.register(Image, ImageAdmin)
733