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