key is now just an attribute of the user model. Added 'creator' field to sliver model
[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', '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             inline.model.creator = request.user
337             yield inline.get_formset(request, obj)
338
339     def get_queryset(self, request):
340         qs = super(SliceAdmin, self).get_queryset(request)
341         if request.user.is_superuser:
342             return qs
343         # users can only see slices at their site
344         return qs.filter(site=request.user.site) 
345
346 class SliceMembershipAdmin(PlanetStackBaseAdmin):
347     fieldsets = [
348         (None, {'fields': ['user', 'slice', 'role']})
349     ]
350     list_display = ('user', 'slice', 'role')
351
352     def formfield_for_foreignkey(self, db_field, request, **kwargs):
353         if db_field.name == 'slice':
354             if not request.user.is_admin:
355                 # only show slices at sites where caller has admin or pi role
356                 roles = Role.objects.filter(role_type__in=['admin', 'pi'])
357                 site_privileges = SitePrivilege.objects.filter(user=request.user).filter(role__in=roles)
358                 sites = [site_privilege.site for site_privilege in site_privileges]
359                 slices = Slice.objects.filter(site__in=sites)
360                 kwargs['queryset'] = slices
361         
362         if db_field.name == 'user':
363             if not request.user.is_admin:
364                 # only show users from sites where caller has admin or pi role
365                 roles = Role.objects.filter(role_type__in=['admin', 'pi'])
366                 site_privileges = SitePrivilege.objects.filter(user=request.user).filter(role__in=roles)
367                 sites = [site_privilege.site for site_privilege in site_privileges]
368                 site_privileges = SitePrivilege.objects.filter(site__in=sites)
369                 emails = [site_privilege.user.email for site_privilege in site_privileges]
370                 users = User.objects.filter(email__in=emails)
371                 kwargs['queryset'] = users
372
373         return super(SliceMembershipAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)
374
375     def queryset(self, request):
376         # admins can see all memberships. Users can only see memberships of
377         # slices where they have the admin role.
378         qs = super(SliceMembershipAdmin, self).queryset(request)
379         if not request.user.is_admin:
380             roles = Role.objects.filter(role_type__in=['admin', 'pi'])
381             site_privileges = SitePrivilege.objects.filter(user=request.user).filter(role__in=roles)
382             login_bases = [site_privilege.site.login_base for site_privilege in site_privileges]
383             sites = Site.objects.filter(login_base__in=login_bases)
384             slices = Slice.objects.filter(site__in=sites)
385             qs = qs.filter(slice__in=slices)
386         return qs
387
388     def save_model(self, request, obj, form, change):
389         # update openstack connection to use this site/tenant
390         auth = request.session.get('auth', {})
391         auth['tenant'] = obj.slice.name
392         obj.os_manager = OpenStackManager(auth=auth, caller=request.user)
393         obj.save()
394
395     def delete_model(self, request, obj):
396         # update openstack connection to use this site/tenant
397         auth = request.session.get('auth', {})
398         auth['tenant'] = obj.slice.name
399         obj.os_manager = OpenStackManager(auth=auth, caller=request.user)
400         obj.delete()
401
402
403 class ImageAdmin(admin.ModelAdmin):
404     fields = ['image_id', 'name', 'disk_format', 'container_format']
405
406 class NodeAdmin(admin.ModelAdmin):
407     list_display = ('name', 'site', 'deployment')
408     list_filter = ('deployment',)
409
410
411 class SliverForm(forms.ModelForm):
412     class Meta:
413         model = Sliver
414         ip = forms.CharField(widget=PlainTextWidget)
415         instance_name = forms.CharField(widget=PlainTextWidget)
416         widgets = {
417             'ip': PlainTextWidget(),
418             'instance_name': PlainTextWidget(),
419         }
420
421 class SliverAdmin(PlanetStackBaseAdmin):
422     form = SliverForm
423     fieldsets = [
424         ('Sliver', {'fields': ['ip', 'instance_name', 'slice', 'numberCores', 'image', 'key', 'node', 'deploymentNetwork']})
425     ]
426     list_display = ['ip', 'instance_name', 'slice', 'numberCores', 'image', 'key', 'node', 'deploymentNetwork']
427
428     def formfield_for_foreignkey(self, db_field, request, **kwargs):
429         if db_field.name == 'slice':
430             if not request.user.is_admin:
431                 slices = set([sm.slice.name for sm in SliceMembership.objects.filter(user=request.user)]) 
432                 kwargs['queryset'] = Slice.objects.filter(name__in=list(slices))
433
434         return super(SliverAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)
435
436     def queryset(self, request):
437         # admins can see all slivers. Users can only see slivers of 
438         # the slices they belong to.
439         qs = super(SliverAdmin, self).queryset(request)
440         if not request.user.is_admin:
441             tenants = []
442             roles = request.user.get_roles()
443             for tenant_list in roles.values():
444                 tenants.extend(tenant_list)
445             valid_slices = Slice.objects.filter(name__in=tenants)
446             qs = qs.filter(slice__in=valid_slices)
447         return qs
448
449     def get_formsets(self, request, obj=None):
450         # make some fields read only if we are updating an existing record
451         if obj == None:
452             #self.readonly_fields = ('ip', 'instance_name') 
453             self.readonly_fields = () 
454         else:
455             self.readonly_fields = () 
456             #self.readonly_fields = ('ip', 'instance_name', 'slice', 'image', 'key') 
457
458         for inline in self.get_inline_instances(request, obj):
459             # hide MyInline in the add view
460             if obj is None:
461                 continue
462             # give inline object access to driver and caller
463             auth = request.session.get('auth', {})
464             auth['tenant'] = obj.name       # meed to connect using slice's tenant
465             inline.model.os_manager = OpenStackManager(auth=auth, caller=request.user)
466             yield inline.get_formset(request, obj)
467
468     def save_model(self, request, obj, form, change):
469         # update openstack connection to use this site/tenant
470         auth = request.session.get('auth', {})
471         auth['tenant'] = obj.slice.name
472         obj.os_manager = OpenStackManager(auth=auth, caller=request.user)
473         obj.creator = request.user
474         obj.save()
475
476     def delete_model(self, request, obj):
477         # update openstack connection to use this site/tenant
478         auth = request.session.get('auth', {})
479         auth['tenant'] = obj.slice.name
480         obj.os_manager = OpenStackManager(auth=auth, caller=request.user)
481         obj.delete()
482
483 class UserCreationForm(forms.ModelForm):
484     """A form for creating new users. Includes all the required
485     fields, plus a repeated password."""
486     password1 = forms.CharField(label='Password', widget=forms.PasswordInput)
487     password2 = forms.CharField(label='Password confirmation', widget=forms.PasswordInput)
488
489     class Meta:
490         model = User
491         fields = ('email', 'firstname', 'lastname', 'phone', 'public_key', 'site')
492
493     def clean_password2(self):
494         # Check that the two password entries match
495         password1 = self.cleaned_data.get("password1")
496         password2 = self.cleaned_data.get("password2")
497         if password1 and password2 and password1 != password2:
498             raise forms.ValidationError("Passwords don't match")
499         return password2
500
501     def save(self, commit=True):
502         # Save the provided password in hashed format
503         user = super(UserCreationForm, self).save(commit=False)
504         user.password = self.cleaned_data["password1"]
505         #user.set_password(self.cleaned_data["password1"])
506         if commit:
507             user.save()
508         return user
509
510
511 class UserChangeForm(forms.ModelForm):
512     """A form for updating users. Includes all the fields on
513     the user, but replaces the password field with admin's
514     password hash display field.
515     """
516     password = ReadOnlyPasswordHashField()
517
518     class Meta:
519         model = User
520
521     def clean_password(self):
522         # Regardless of what the user provides, return the initial value.
523         # This is done here, rather than on the field, because the
524         # field does not have access to the initial value
525         return self.initial["password"]
526
527
528 class UserAdmin(UserAdmin, OSModelAdmin):
529     class Meta:
530         app_label = "core"
531
532     # The forms to add and change user instances
533     form = UserChangeForm
534     add_form = UserCreationForm
535
536     # The fields to be used in displaying the User model.
537     # These override the definitions on the base UserAdmin
538     # that reference specific fields on auth.User.
539     list_display = ('email', 'site', 'firstname', 'lastname', 'is_admin', 'last_login')
540     list_filter = ('site',)
541     inlines = [SitePrivilegeInline, SliceMembershipInline]
542     fieldsets = (
543         (None, {'fields': ('email', 'password', 'site', 'is_admin', 'timezone')}),
544         ('Personal info', {'fields': ('firstname','lastname','phone', 'public_key')}),
545         #('Important dates', {'fields': ('last_login',)}),
546     )
547     add_fieldsets = (
548         (None, {
549             'classes': ('wide',),
550             'fields': ('email', 'firstname', 'lastname', 'phone', 'site', 'public_key','password1', 'password2', 'is_admin')}
551         ),
552     )
553     search_fields = ('email',)
554     ordering = ('email',)
555     filter_horizontal = ()
556
557     def formfield_for_foreignkey(self, db_field, request, **kwargs):
558         if db_field.name == 'site':
559             if not request.user.is_admin:
560                 # show sites where caller is an admin or pi 
561                 sites = []
562                 for site_privilege in SitePrivilege.objects.filer(user=request.user):
563                     if site_privilege.role.role_type in ['admin', 'pi']:
564                         sites.append(site_privilege.site.login_base)  
565                 kwargs['queryset'] = Site.objects.filter(login_base__in(list(sites)))
566
567         return super(UserAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)
568
569 class ServiceResourceInline(admin.TabularInline):
570     model = ServiceResource
571     extra = 0
572
573 class ServiceClassAdmin(admin.ModelAdmin):
574     list_display = ('name', 'commitment', 'membershipFee')
575     inlines = [ServiceResourceInline]
576
577 class ReservedResourceInline(admin.TabularInline):
578     model = ReservedResource
579     extra = 0
580
581     def formfield_for_foreignkey(self, db_field, request=None, **kwargs):
582         field = super(ReservedResourceInline, self).formfield_for_foreignkey(db_field, request, **kwargs)
583
584         if db_field.name == 'resource':
585             # restrict resources to those that the slice's service class allows
586             if request._slice is not None:
587                 field.queryset = field.queryset.filter(serviceClass = request._slice.serviceClass, calendarReservable=True)
588                 if len(field.queryset) > 0:
589                     field.initial = field.queryset.all()[0]
590             else:\r
591                 field.queryset = field.queryset.none()\r
592         elif db_field.name == 'sliver':\r
593             # restrict slivers to those that belong to the slice\r
594             if request._slice is not None:\r
595                 field.queryset = field.queryset.filter(slice = request._slice)
596             else:
597                 field.queryset = field.queryset.none()\r
598 \r
599         return field
600
601 class ReservationChangeForm(forms.ModelForm):
602     class Meta:
603         model = Reservation
604
605 class ReservationAddForm(forms.ModelForm):
606     slice = forms.ModelChoiceField(queryset=Slice.objects.all(), widget=forms.Select(attrs={"onChange":"document.getElementById('id_refresh').value=1; submit()"}))
607     refresh = forms.CharField(widget=forms.HiddenInput())
608
609     class Media:
610        css = {'all': ('planetstack.css',)}   # .field-refresh { display: none; }
611
612     def clean_slice(self):
613         slice = self.cleaned_data.get("slice")
614         x = ServiceResource.objects.filter(serviceClass = slice.serviceClass, calendarReservable=True)
615         if len(x) == 0:
616             raise forms.ValidationError("The slice you selected does not have a service class that allows reservations")
617         return slice
618
619     class Meta:
620         model = Reservation
621
622 class ReservationAddRefreshForm(ReservationAddForm):
623     """ This form is displayed when the Reservation Form receives an update
624         from the Slice dropdown onChange handler. It doesn't validate the
625         data and doesn't save the data. This will cause the form to be
626         redrawn.
627     """
628
629     """ don't validate anything other than slice """
630     dont_validate_fields = ("startTime", "duration")
631
632     def full_clean(self):
633         result = super(ReservationAddForm, self).full_clean()
634
635         for fieldname in self.dont_validate_fields:
636             if fieldname in self._errors:
637                 del self._errors[fieldname]
638
639         return result
640
641     """ don't save anything """
642     def is_valid(self):
643         return False
644
645 class ReservationAdmin(admin.ModelAdmin):
646     list_display = ('startTime', 'duration')
647     inlines = [ReservedResourceInline]
648     form = ReservationAddForm
649
650     def add_view(self, request, form_url='', extra_context=None):
651         timezone.activate(request.user.timezone)
652         request._refresh = False
653         request._slice = None
654         if request.method == 'POST':
655             # "refresh" will be set to "1" if the form was submitted due to
656             # a change in the Slice dropdown.
657             if request.POST.get("refresh","1") == "1":
658                 request._refresh = True
659                 request.POST["refresh"] = "0"
660
661             # Keep track of the slice that was selected, so the
662             # reservedResource inline can filter items for the slice.
663             request._slice = request.POST.get("slice",None)
664             if (request._slice is not None):
665                 request._slice = Slice.objects.get(id=request._slice)
666
667         result =  super(ReservationAdmin, self).add_view(request, form_url, extra_context)
668         return result
669
670     def changelist_view(self, request, extra_context = None):
671         timezone.activate(request.user.timezone)
672         return super(ReservationAdmin, self).changelist_view(request, extra_context)
673
674     def get_form(self, request, obj=None, **kwargs):
675         request._obj_ = obj\r
676         if obj is not None:\r
677             # For changes, set request._slice to the slice already set in the\r
678             # object.\r
679             request._slice = obj.slice\r
680             self.form = ReservationChangeForm\r
681         else:\r
682             if getattr(request, "_refresh", False):\r
683                 self.form = ReservationAddRefreshForm\r
684             else:\r
685                 self.form = ReservationAddForm\r
686         return super(ReservationAdmin, self).get_form(request, obj, **kwargs)\r
687 \r
688     def get_readonly_fields(self, request, obj=None):
689         if (obj is not None):\r
690             # Prevent slice from being changed after the reservation has been\r
691             # created.\r
692             return ['slice']\r
693         else:\r
694             return []
695
696 # register a signal that caches the user's credentials when they log in
697 def cache_credentials(sender, user, request, **kwds):
698     auth = {'username': request.POST['username'],
699             'password': request.POST['password']}
700     request.session['auth'] = auth
701 user_logged_in.connect(cache_credentials)
702
703 # Now register the new UserAdmin...
704 admin.site.register(User, UserAdmin)
705 # ... and, since we're not using Django's builtin permissions,
706 # unregister the Group model from admin.
707 admin.site.unregister(Group)
708
709 #Do not show django evolution in the admin interface
710 from django_evolution.models import Version, Evolution
711 admin.site.unregister(Version)
712 admin.site.unregister(Evolution)
713
714
715 # When debugging it is often easier to see all the classes, but for regular use 
716 # only the top-levels should be displayed
717 showAll = False
718
719 admin.site.register(Deployment, DeploymentAdmin)
720 admin.site.register(Site, SiteAdmin)
721 admin.site.register(Slice, SliceAdmin)
722 #admin.site.register(Subnet)
723 admin.site.register(Key, KeyAdmin)
724
725
726 if showAll:
727     admin.site.register(Node, NodeAdmin)
728     admin.site.register(SliceMembership, SliceMembershipAdmin)
729     admin.site.register(SitePrivilege, SitePrivilegeAdmin)
730     admin.site.register(Role, RoleAdmin)
731     admin.site.register(Sliver, SliverAdmin)
732     admin.site.register(ServiceClass, ServiceClassAdmin)
733     admin.site.register(Reservation, ReservationAdmin)
734     admin.site.register(Image, ImageAdmin)
735