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