1 from core.models import Site
2 from core.models import *
3 from openstack.manager import OpenStackManager
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 from suit.widgets import LinkedSelect
17 import django_evolution
19 class SingletonAdmin (admin.ModelAdmin):
20 def has_add_permission(self, request):
21 num_objects = self.model.objects.count()
28 class PlStackTabularInline(admin.TabularInline):
31 class ReservationInline(PlStackTabularInline):
34 suit_classes = 'suit-tab suit-tab-reservations'
37 class ReadonlyTabularInline(PlStackTabularInline):
42 def get_readonly_fields(self, request, obj=None):
44 for field in self.model._meta.get_all_field_names():
45 if (not field == 'id'):
46 if (field not in self.editable_fields):
50 def has_add_permission(self, request):
53 class TagInline(generic.GenericTabularInline):
56 suit_classes = 'suit-tab suit-tab-tags'
58 class NetworkLookerUpper:
59 """ This is a callable that looks up a network name in a sliver and returns
60 the ip address for that network.
63 def __init__(self, name):
64 self.short_description = name
66 self.network_name = name
68 def __call__(self, obj):
70 for nbs in obj.networksliver_set.all():
71 if (nbs.network.name == self.network_name):
76 return self.network_name
78 class SliverInline(PlStackTabularInline):
80 fields = ['ip', 'instance_name', 'slice', 'numberCores', 'image', 'node', 'deploymentNetwork']
82 readonly_fields = ['ip', 'instance_name']
83 suit_classes = 'suit-tab suit-tab-slivers'
85 # Note this is breaking in the admin.py when trying to use an inline to add a node/image
86 # def _declared_fieldsets(self):
87 # # Return None so django will call get_fieldsets and we can insert our
91 # def get_readonly_fields(self, request, obj=None):
92 # readonly_fields = super(SliverInline, self).get_readonly_fields(request, obj)
94 # # Lookup the networks that are bound to the slivers, and add those
95 # # network names to the list of readonly fields.
97 # for sliver in obj.slivers.all():
98 # for nbs in sliver.networksliver_set.all():
100 # network_name = nbs.network.name
101 # if network_name not in [str(x) for x in readonly_fields]:
102 # readonly_fields.append(NetworkLookerUpper(network_name))
104 # return readonly_fields
106 # def get_fieldsets(self, request, obj=None):
107 # form = self.get_formset(request, obj).form
108 # # fields = the read/write files + the read-only fields
109 # fields = self.fields
110 # for fieldName in self.get_readonly_fields(request,obj):
111 # if not fieldName in fields:
112 # fields.append(fieldName)
114 # return [(None, {'fields': fields})]
118 class SiteInline(PlStackTabularInline):
121 suit_classes = 'suit-tab suit-tab-sites'
123 class UserInline(PlStackTabularInline):
125 fields = ['email', 'firstname', 'lastname']
127 suit_classes = 'suit-tab suit-tab-users'
129 class SliceInline(PlStackTabularInline):
131 fields = ['name','site', 'serviceClass', 'service']
133 suit_classes = 'suit-tab suit-tab-slices'
136 class RoleInline(PlStackTabularInline):
139 suit_classes = 'suit-tab suit-tab-roles'
141 class NodeInline(PlStackTabularInline):
144 suit_classes = 'suit-tab suit-tab-nodes'
146 class SlicePrivilegeInline(PlStackTabularInline):
147 model = SlicePrivilege
149 suit_classes = 'suit-tab suit-tab-sliceprivileges'
151 class DeploymentPrivilegeInline(PlStackTabularInline):
152 model = DeploymentPrivilege
154 suit_classes = 'suit-tab suit-tab-deploymentprivileges'
156 class SitePrivilegeInline(PlStackTabularInline):
157 model = SitePrivilege
159 suit_classes = 'suit-tab suit-tab-siteprivileges'
161 def formfield_for_foreignkey(self, db_field, request, **kwargs):
162 if db_field.name == 'site':
163 if not request.user.is_admin:
164 # only show sites where user is an admin or pi
165 roles = Role.objects.filter(role_type__in=['admin', 'pi'])
166 site_privileges = SitePrivilege.objects.filter(user=request.user).filter(role__in=roles)
167 login_bases = [site_privilege.site.login_base for site_privilege in site_privileges]
168 sites = Site.objects.filter(login_base__in=login_bases)
169 kwargs['queryset'] = sites
171 if db_field.name == 'user':
172 if not request.user.is_admin:
173 # only show users from sites where caller has admin or pi role
174 roles = Role.objects.filter(role_type__in=['admin', 'pi'])
175 site_privileges = SitePrivilege.objects.filter(user=request.user).filter(role__in=roles)
176 sites = [site_privilege.site for site_privilege in site_privileges]
177 site_privileges = SitePrivilege.objects.filter(site__in=sites)
178 emails = [site_privilege.user.email for site_privilege in site_privileges]
179 users = User.objects.filter(email__in=emails)
180 kwargs['queryset'] = users
181 return super(SitePrivilegeInline, self).formfield_for_foreignkey(db_field, request, **kwargs)
183 class SitePrivilegeInline(PlStackTabularInline):
184 model = SitePrivilege
185 suit_classes = 'suit-tab suit-tab-siteprivileges'
187 fields = ('user', 'site','role')
189 class SlicePrivilegeInline(PlStackTabularInline):
190 model = SlicePrivilege
191 suit_classes = 'suit-tab suit-tab-sliceprivileges'
193 fields = ('user', 'slice','role')
195 def formfield_for_foreignkey(self, db_field, request, **kwargs):
196 if db_field.name == 'slice':
197 if not request.user.is_admin:
198 # only show slices at sites where caller has admin or pi role
199 roles = Role.objects.filter(role_type__in=['admin', 'pi'])
200 site_privileges = SitePrivilege.objects.filter(user=request.user).filter(role__in=roles)
201 sites = [site_privilege.site for site_privilege in site_privileges]
202 slices = Slice.objects.filter(site__in=sites)
203 kwargs['queryset'] = slices
204 if db_field.name == 'user':
205 if not request.user.is_admin:
206 # only show users from sites where caller has admin or pi role
207 roles = Role.objects.filter(role_type__in=['admin', 'pi'])
208 site_privileges = SitePrivilege.objects.filter(user=request.user).filter(role__in=roles)
209 sites = [site_privilege.site for site_privilege in site_privileges]
210 site_privileges = SitePrivilege.objects.filter(site__in=sites)
211 emails = [site_privilege.user.email for site_privilege in site_privileges]
212 users = User.objects.filter(email__in=emails)
213 kwargs['queryset'] = list(users)
215 return super(SlicePrivilegeInline, self).formfield_for_foreignkey(db_field, request, **kwargs)
217 class SliceNetworkInline(PlStackTabularInline):
218 model = Network.slices.through
220 verbose_name = "Network Connection"
221 verbose_name_plural = "Network Connections"
222 suit_classes = 'suit-tab suit-tab-slicenetworks'
224 class SliceTagInline(PlStackTabularInline):
228 class PlainTextWidget(forms.HiddenInput):
229 input_type = 'hidden'
231 def render(self, name, value, attrs=None):
234 return mark_safe(str(value) + super(PlainTextWidget, self).render(name, value, attrs))
236 class PlanetStackBaseAdmin(admin.ModelAdmin):
239 class SliceRoleAdmin(PlanetStackBaseAdmin):
243 class SiteRoleAdmin(PlanetStackBaseAdmin):
247 class DeploymentAdminForm(forms.ModelForm):
248 sites = forms.ModelMultipleChoiceField(
249 queryset=Site.objects.all(),
251 widget=FilteredSelectMultiple(
252 verbose_name=('Sites'), is_stacked=False
259 class DeploymentAdmin(PlanetStackBaseAdmin):
260 form = DeploymentAdminForm
261 inlines = [DeploymentPrivilegeInline,NodeInline,TagInline]
263 (None, {'fields': ['sites'], 'classes':['suit-tab suit-tab-sites']}),]
264 suit_form_tabs =(('sites', 'Sites'),('nodes','Nodes'),('deploymentprivileges','Privileges'),('tags','Tags'))
266 class ServiceAttrAsTabInline(PlStackTabularInline):
267 model = ServiceAttribute
268 fields = ['name','value']
270 suit_classes = 'suit-tab suit-tab-serviceattrs'
272 class ServiceAttributeInline(PlStackTabularInline):
273 model = ServiceAttribute
274 fields = ['name','value']
277 class ServiceAdmin(PlanetStackBaseAdmin):
278 list_display = ("name","enabled")
279 fieldsets = [(None, {'fields': ['name','enabled','description']})]
280 inlines = [ServiceAttributeInline,]
282 class SiteAdmin(PlanetStackBaseAdmin):
284 (None, {'fields': ['name', 'site_url', 'enabled', 'is_public', 'login_base', 'location'], 'classes':['suit-tab suit-tab-general']}),
285 ('Deployment Networks', {'fields': ['deployments'], 'classes':['suit-tab suit-tab-deployments']}),
287 suit_form_tabs =(('general', 'Site Details'),
289 ('siteprivileges','Privileges'),
290 ('deployments','Deployments'),
295 list_display = ('name', 'login_base','site_url', 'enabled')
296 filter_horizontal = ('deployments',)
297 inlines = [SliceInline,UserInline,TagInline, NodeInline, SitePrivilegeInline]
298 search_fields = ['name']
300 def queryset(self, request):
301 # admins can see all keys. Users can only see sites they belong to.
302 qs = super(SiteAdmin, self).queryset(request)
303 if not request.user.is_admin:
304 valid_sites = [request.user.site.login_base]
305 roles = request.user.get_roles()
306 for tenant_list in roles.values():
307 valid_sites.extend(tenant_list)
308 qs = qs.filter(login_base__in=valid_sites)
311 def get_formsets(self, request, obj=None):
312 for inline in self.get_inline_instances(request, obj):
313 # hide MyInline in the add view
316 if isinstance(inline, SliceInline):
317 inline.model.caller = request.user
318 yield inline.get_formset(request, obj)
320 def get_formsets(self, request, obj=None):
321 for inline in self.get_inline_instances(request, obj):
322 # hide MyInline in the add view
325 if isinstance(inline, SliverInline):
326 inline.model.caller = request.user
327 yield inline.get_formset(request, obj)
329 class SitePrivilegeAdmin(PlanetStackBaseAdmin):
331 (None, {'fields': ['user', 'site', 'role'], 'classes':['collapse']})
333 list_display = ('user', 'site', 'role')
335 def formfield_for_foreignkey(self, db_field, request, **kwargs):
336 if db_field.name == 'site':
337 if not request.user.is_admin:
338 # only show sites where user is an admin or pi
340 for site_privilege in SitePrivilege.objects.filer(user=request.user):
341 if site_privilege.role.role_type in ['admin', 'pi']:
342 sites.add(site_privilege.site)
343 kwargs['queryset'] = Site.objects.filter(site__in=list(sites))
345 if db_field.name == 'user':
346 if not request.user.is_admin:
347 # only show users from sites where caller has admin or pi role
348 roles = Role.objects.filter(role_type__in=['admin', 'pi'])
349 site_privileges = SitePrivilege.objects.filter(user=request.user).filter(role__in=roles)
350 sites = [site_privilege.site for site_privilege in site_privileges]
351 site_privileges = SitePrivilege.objects.filter(site__in=sites)
352 emails = [site_privilege.user.email for site_privilege in site_privileges]
353 users = User.objects.filter(email__in=emails)
354 kwargs['queryset'] = users
356 return super(SitePrivilegeAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)
358 def queryset(self, request):
359 # admins can see all privileges. Users can only see privileges at sites
360 # where they have the admin role or pi role.
361 qs = super(SitePrivilegeAdmin, self).queryset(request)
362 if not request.user.is_admin:
363 roles = Role.objects.filter(role_type__in=['admin', 'pi'])
364 site_privileges = SitePrivilege.objects.filter(user=request.user).filter(role__in=roles)
365 login_bases = [site_privilege.site.login_base for site_privilege in site_privileges]
366 sites = Site.objects.filter(login_base__in=login_bases)
367 qs = qs.filter(site__in=sites)
370 class SliceForm(forms.ModelForm):
374 'service': LinkedSelect
377 class SliceAdmin(PlanetStackBaseAdmin):
379 fieldsets = [('Slice Details', {'fields': ['name', 'site', 'serviceClass', 'enabled','description', 'service', 'slice_url'], 'classes':['suit-tab suit-tab-general']}),]
380 list_display = ('name', 'site','serviceClass', 'slice_url')
381 inlines = [SlicePrivilegeInline,SliverInline, TagInline, ReservationInline,SliceNetworkInline]
384 #inlines = [SliverInline, SliceMembershipInline, TagInline, SliceTagInline, SliceNetworkInline]
385 suit_form_tabs =(('general', 'Slice Details'),
386 ('slicenetworks','Networks'),
387 ('sliceprivileges','Privileges'),
388 ('slivers','Slivers'),
390 ('reservations','Reservations'),
393 def formfield_for_foreignkey(self, db_field, request, **kwargs):
394 if db_field.name == 'site':
395 if not request.user.is_admin:
396 # only show sites where user is a pi or admin
397 roles = Role.objects.filter(role_type__in=['admin', 'pi'])
398 site_privileges = SitePrivilege.objects.filter(user=request.user).filter(role__in=roles)
399 login_bases = [site_privilege.site.login_base for site_privilege in site_privileges]
400 sites = Site.objects.filter(login_base__in=login_bases)
401 kwargs['queryset'] = sites
403 return super(SliceAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)
405 def queryset(self, request):
406 # admins can see all keys. Users can only see slices they belong to.
407 qs = super(SliceAdmin, self).queryset(request)
408 if not request.user.is_admin:
410 roles = request.user.get_roles()
411 for tenant_list in roles.values():
412 valid_slices.extend(tenant_list)
413 qs = qs.filter(name__in=valid_slices)
416 def get_formsets(self, request, obj=None):
417 for inline in self.get_inline_instances(request, obj):
418 # hide MyInline in the add view
421 if isinstance(inline, SliverInline):
422 inline.model.caller = request.user
423 yield inline.get_formset(request, obj)
425 def get_queryset(self, request):
426 qs = super(SliceAdmin, self).get_queryset(request)
427 if request.user.is_superuser:
429 # users can only see slices at their site
430 return qs.filter(site=request.user.site)
432 def save_model(self, request, obj, form, change):
433 # update openstack connection to use this site/tenant
434 obj.caller = request.user
437 class SlicePrivilegeAdmin(PlanetStackBaseAdmin):
439 (None, {'fields': ['user', 'slice', 'role']})
441 list_display = ('user', 'slice', 'role')
443 def formfield_for_foreignkey(self, db_field, request, **kwargs):
444 if db_field.name == 'slice':
445 if not request.user.is_admin:
446 # only show slices at sites where caller has admin or pi role
447 roles = Role.objects.filter(role_type__in=['admin', 'pi'])
448 site_privileges = SitePrivilege.objects.filter(user=request.user).filter(role__in=roles)
449 sites = [site_privilege.site for site_privilege in site_privileges]
450 slices = Slice.objects.filter(site__in=sites)
451 kwargs['queryset'] = slices
453 if db_field.name == 'user':
454 if not request.user.is_admin:
455 # only show users from sites where caller has admin or pi role
456 roles = Role.objects.filter(role_type__in=['admin', 'pi'])
457 site_privileges = SitePrivilege.objects.filter(user=request.user).filter(role__in=roles)
458 sites = [site_privilege.site for site_privilege in site_privileges]
459 site_privileges = SitePrivilege.objects.filter(site__in=sites)
460 emails = [site_privilege.user.email for site_privilege in site_privileges]
461 users = User.objects.filter(email__in=emails)
462 kwargs['queryset'] = users
464 return super(SlicePrivilegeAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)
466 def queryset(self, request):
467 # admins can see all memberships. Users can only see memberships of
468 # slices where they have the admin role.
469 qs = super(SlicePrivilegeAdmin, self).queryset(request)
470 if not request.user.is_admin:
471 roles = Role.objects.filter(role_type__in=['admin', 'pi'])
472 site_privileges = SitePrivilege.objects.filter(user=request.user).filter(role__in=roles)
473 login_bases = [site_privilege.site.login_base for site_privilege in site_privileges]
474 sites = Site.objects.filter(login_base__in=login_bases)
475 slices = Slice.objects.filter(site__in=sites)
476 qs = qs.filter(slice__in=slices)
479 def save_model(self, request, obj, form, change):
480 # update openstack connection to use this site/tenant
481 auth = request.session.get('auth', {})
482 auth['tenant'] = obj.slice.name
483 obj.os_manager = OpenStackManager(auth=auth, caller=request.user)
486 def delete_model(self, request, obj):
487 # update openstack connection to use this site/tenant
488 auth = request.session.get('auth', {})
489 auth['tenant'] = obj.slice.name
490 obj.os_manager = OpenStackManager(auth=auth, caller=request.user)
494 class ImageAdmin(PlanetStackBaseAdmin):
496 fieldsets = [('Image Details',
497 {'fields': ['image_id', 'name', 'disk_format', 'container_format'],
498 'classes': ['suit-tab suit-tab-general']})
501 suit_form_tabs =(('general','Image Details'),('slivers','Slivers'))
503 inlines = [SliverInline]
505 class NodeForm(forms.ModelForm):
508 'site': LinkedSelect,
509 'deployment': LinkedSelect
512 class NodeAdmin(admin.ModelAdmin):
514 list_display = ('name', 'site', 'deployment')
515 list_filter = ('deployment',)
516 inlines = [TagInline,SliverInline]
517 fieldsets = [('Node Details', {'fields': ['name','site','deployment'], 'classes':['suit-tab suit-tab-details']})]
519 suit_form_tabs =(('details','Node Details'),('slivers','Slivers'),('tags','Tags'))
522 class SliverForm(forms.ModelForm):
525 ip = forms.CharField(widget=PlainTextWidget)
526 instance_name = forms.CharField(widget=PlainTextWidget)
528 'ip': PlainTextWidget(),
529 'instance_name': PlainTextWidget(),
530 'slice': LinkedSelect,
531 'deploymentNetwork': LinkedSelect,
532 'node': LinkedSelect,
533 'image': LinkedSelect
536 class TagAdmin(admin.ModelAdmin):
537 list_display = ['service', 'name', 'value', 'content_type', 'content_object',]
539 class SliverAdmin(PlanetStackBaseAdmin):
542 ('Sliver Details', {'fields': ['slice', 'deploymentNetwork', 'node', 'ip', 'instance_name', 'numberCores', 'image', ], 'classes': ['suit-tab suit-tab-general'], })
544 list_display = ['ip', 'instance_name', 'slice', 'numberCores', 'image', 'node', 'deploymentNetwork']
546 suit_form_tabs =(('general', 'Sliver Details'),
550 inlines = [TagInline]
552 def formfield_for_foreignkey(self, db_field, request, **kwargs):
553 if db_field.name == 'slice':
554 if not request.user.is_admin:
555 slices = set([sm.slice.name for sm in SlicePrivilege.objects.filter(user=request.user)])
556 kwargs['queryset'] = Slice.objects.filter(name__in=list(slices))
558 return super(SliverAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)
560 def queryset(self, request):
561 # admins can see all slivers. Users can only see slivers of
562 # the slices they belong to.
563 qs = super(SliverAdmin, self).queryset(request)
564 if not request.user.is_admin:
566 roles = request.user.get_roles()
567 for tenant_list in roles.values():
568 tenants.extend(tenant_list)
569 valid_slices = Slice.objects.filter(name__in=tenants)
570 qs = qs.filter(slice__in=valid_slices)
573 def get_formsets(self, request, obj=None):
574 # make some fields read only if we are updating an existing record
576 #self.readonly_fields = ('ip', 'instance_name')
577 self.readonly_fields = ()
579 self.readonly_fields = ()
580 #self.readonly_fields = ('ip', 'instance_name', 'slice', 'image', 'key')
582 for inline in self.get_inline_instances(request, obj):
583 # hide MyInline in the add view
586 # give inline object access to driver and caller
587 auth = request.session.get('auth', {})
588 auth['tenant'] = obj.name # meed to connect using slice's tenant
589 inline.model.os_manager = OpenStackManager(auth=auth, caller=request.user)
590 yield inline.get_formset(request, obj)
592 def save_model(self, request, obj, form, change):
593 # update openstack connection to use this site/tenant
594 auth = request.session.get('auth', {})
595 auth['tenant'] = obj.slice.name
596 obj.os_manager = OpenStackManager(auth=auth, caller=request.user)
597 obj.creator = request.user
600 def delete_model(self, request, obj):
601 # update openstack connection to use this site/tenant
602 auth = request.session.get('auth', {})
603 auth['tenant'] = obj.slice.name
604 obj.os_manager = OpenStackManager(auth=auth, caller=request.user)
607 class UserCreationForm(forms.ModelForm):
608 """A form for creating new users. Includes all the required
609 fields, plus a repeated password."""
610 password1 = forms.CharField(label='Password', widget=forms.PasswordInput)
611 password2 = forms.CharField(label='Password confirmation', widget=forms.PasswordInput)
615 fields = ('email', 'firstname', 'lastname', 'phone', 'public_key')
617 def clean_password2(self):
618 # Check that the two password entries match
619 password1 = self.cleaned_data.get("password1")
620 password2 = self.cleaned_data.get("password2")
621 if password1 and password2 and password1 != password2:
622 raise forms.ValidationError("Passwords don't match")
625 def save(self, commit=True):
626 # Save the provided password in hashed format
627 user = super(UserCreationForm, self).save(commit=False)
628 user.password = self.cleaned_data["password1"]
629 #user.set_password(self.cleaned_data["password1"])
635 class UserChangeForm(forms.ModelForm):
636 """A form for updating users. Includes all the fields on
637 the user, but replaces the password field with admin's
638 password hash display field.
640 password = ReadOnlyPasswordHashField()
645 def clean_password(self):
646 # Regardless of what the user provides, return the initial value.
647 # This is done here, rather than on the field, because the
648 # field does not have access to the initial value
649 return self.initial["password"]
652 class UserAdmin(UserAdmin):
656 # The forms to add and change user instances
657 form = UserChangeForm
658 add_form = UserCreationForm
660 # The fields to be used in displaying the User model.
661 # These override the definitions on the base UserAdmin
662 # that reference specific fields on auth.User.
663 list_display = ('email', 'firstname', 'lastname', 'is_admin', 'last_login')
664 #list_display = ('email', 'username','firstname', 'lastname', 'is_admin', 'last_login')
666 inlines = [SlicePrivilegeInline,SitePrivilegeInline,DeploymentPrivilegeInline]
668 ('Login Details', {'fields': ('email', 'site','password', 'is_admin', 'public_key'), 'classes':['suit-tab suit-tab-general']}),
669 ('Contact Information', {'fields': ('firstname','lastname','phone', 'timezone'), 'classes':['suit-tab suit-tab-contact']}),
670 #('Important dates', {'fields': ('last_login',)}),
674 'classes': ('wide',),
675 'fields': ('email', 'firstname', 'lastname', 'phone', 'public_key','password1', 'password2')}
678 search_fields = ('email',)
679 ordering = ('email',)
680 filter_horizontal = ()
682 suit_form_tabs =(('general','Login Details'),('contact','Contact Information'),('sliceprivileges','Slice Privileges'),('siteprivileges','Site Privileges'),('deploymentprivileges','Deployment Privileges'))
684 def formfield_for_foreignkey(self, db_field, request, **kwargs):
685 if db_field.name == 'site':
686 if not request.user.is_admin:
687 # show sites where caller is an admin or pi
689 for site_privilege in SitePrivilege.objects.filer(user=request.user):
690 if site_privilege.role.role_type in ['admin', 'pi']:
691 sites.append(site_privilege.site.login_base)
692 kwargs['queryset'] = Site.objects.filter(login_base__in(list(sites)))
694 return super(UserAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)
696 class ServiceResourceInline(admin.TabularInline):
697 model = ServiceResource
700 class ServiceClassAdmin(admin.ModelAdmin):
701 list_display = ('name', 'commitment', 'membershipFee')
702 inlines = [ServiceResourceInline]
704 class ReservedResourceInline(admin.TabularInline):
705 model = ReservedResource
707 suit_classes = 'suit-tab suit-tab-reservedresources'
709 def formfield_for_foreignkey(self, db_field, request=None, **kwargs):
710 field = super(ReservedResourceInline, self).formfield_for_foreignkey(db_field, request, **kwargs)
712 if db_field.name == 'resource':
713 # restrict resources to those that the slice's service class allows
714 if request._slice is not None:
715 field.queryset = field.queryset.filter(serviceClass = request._slice.serviceClass, calendarReservable=True)
716 if len(field.queryset) > 0:
717 field.initial = field.queryset.all()[0]
719 field.queryset = field.queryset.none()
\r
720 elif db_field.name == 'sliver':
\r
721 # restrict slivers to those that belong to the slice
\r
722 if request._slice is not None:
\r
723 field.queryset = field.queryset.filter(slice = request._slice)
725 field.queryset = field.queryset.none()
\r
729 class ReservationChangeForm(forms.ModelForm):
733 'slice' : LinkedSelect
736 class ReservationAddForm(forms.ModelForm):
737 slice = forms.ModelChoiceField(queryset=Slice.objects.all(), widget=forms.Select(attrs={"onChange":"document.getElementById('id_refresh').value=1; submit()"}))
738 refresh = forms.CharField(widget=forms.HiddenInput())
741 css = {'all': ('planetstack.css',)} # .field-refresh { display: none; }
743 def clean_slice(self):
744 slice = self.cleaned_data.get("slice")
745 x = ServiceResource.objects.filter(serviceClass = slice.serviceClass, calendarReservable=True)
747 raise forms.ValidationError("The slice you selected does not have a service class that allows reservations")
753 'slice' : LinkedSelect
757 class ReservationAddRefreshForm(ReservationAddForm):
758 """ This form is displayed when the Reservation Form receives an update
759 from the Slice dropdown onChange handler. It doesn't validate the
760 data and doesn't save the data. This will cause the form to be
764 """ don't validate anything other than slice """
765 dont_validate_fields = ("startTime", "duration")
767 def full_clean(self):
768 result = super(ReservationAddForm, self).full_clean()
770 for fieldname in self.dont_validate_fields:
771 if fieldname in self._errors:
772 del self._errors[fieldname]
776 """ don't save anything """
780 class ReservationAdmin(admin.ModelAdmin):
781 fieldsets = [('Reservation Details', {'fields': ['slice', 'startTime', 'duration'], 'classes': ['suit-tab suit-tab-general']})]
782 list_display = ('startTime', 'duration')
783 form = ReservationAddForm
785 suit_form_tabs = (('general','Reservation Details'), ('reservedresources','Reserved Resources'))
787 inlines = [ReservedResourceInline]
789 def add_view(self, request, form_url='', extra_context=None):
790 timezone.activate(request.user.timezone)
791 request._refresh = False
792 request._slice = None
793 if request.method == 'POST':
794 # "refresh" will be set to "1" if the form was submitted due to
795 # a change in the Slice dropdown.
796 if request.POST.get("refresh","1") == "1":
797 request._refresh = True
798 request.POST["refresh"] = "0"
800 # Keep track of the slice that was selected, so the
801 # reservedResource inline can filter items for the slice.
802 request._slice = request.POST.get("slice",None)
803 if (request._slice is not None):
804 request._slice = Slice.objects.get(id=request._slice)
806 result = super(ReservationAdmin, self).add_view(request, form_url, extra_context)
809 def changelist_view(self, request, extra_context = None):
810 timezone.activate(request.user.timezone)
811 return super(ReservationAdmin, self).changelist_view(request, extra_context)
813 def get_form(self, request, obj=None, **kwargs):
816 # For changes, set request._slice to the slice already set in the
818 request._slice = obj.slice
819 self.form = ReservationChangeForm
821 if getattr(request, "_refresh", False):
822 self.form = ReservationAddRefreshForm
824 self.form = ReservationAddForm
825 return super(ReservationAdmin, self).get_form(request, obj, **kwargs)
827 def get_readonly_fields(self, request, obj=None):
828 if (obj is not None):
829 # Prevent slice from being changed after the reservation has been
835 class NetworkParameterTypeAdmin(admin.ModelAdmin):
836 list_display = ("name", )
838 class RouterAdmin(admin.ModelAdmin):
839 list_display = ("name", )
841 class RouterInline(admin.TabularInline):
842 model = Router.networks.through
844 verbose_name_plural = "Routers"
845 verbose_name = "Router"
846 suit_classes = 'suit-tab suit-tab-routers'
848 class NetworkParameterInline(generic.GenericTabularInline):
849 model = NetworkParameter
851 verbose_name_plural = "Parameters"
852 verbose_name = "Parameter"
853 suit_classes = 'suit-tab suit-tab-netparams'
855 class NetworkSliversInline(admin.TabularInline):
856 readonly_fields = ("ip", )
857 model = NetworkSliver
859 verbose_name_plural = "Slivers"
860 verbose_name = "Sliver"
861 suit_classes = 'suit-tab suit-tab-networkslivers'
863 class NetworkSlicesInline(admin.TabularInline):
866 verbose_name_plural = "Slices"
867 verbose_name = "Slice"
868 suit_classes = 'suit-tab suit-tab-networkslices'
870 class NetworkAdmin(admin.ModelAdmin):
871 list_display = ("name", "subnet", "ports", "labels")
872 readonly_fields = ("subnet", )
874 inlines = [NetworkParameterInline, NetworkSliversInline, NetworkSlicesInline, RouterInline]
877 (None, {'fields': ['name','template','ports','labels','owner','guaranteedBandwidth', 'permitAllSlices','permittedSlices','network_id','router_id','subnet_id','subnet'], 'classes':['suit-tab suit-tab-general']}),]
880 ('general','Network Details'),
881 ('netparams', 'Parameters'),
882 ('networkslivers','Slivers'),
883 ('networkslices','Slices'),
884 ('routers','Routers'),
886 class NetworkTemplateAdmin(admin.ModelAdmin):
887 list_display = ("name", "guaranteedBandwidth", "visibility")
889 # register a signal that caches the user's credentials when they log in
890 def cache_credentials(sender, user, request, **kwds):
891 auth = {'username': request.POST['username'],
892 'password': request.POST['password']}
893 request.session['auth'] = auth
894 user_logged_in.connect(cache_credentials)
897 # Now register the new UserAdmin...
898 admin.site.register(User, UserAdmin)
899 # ... and, since we're not using Django's builtin permissions,
900 # unregister the Group model from admin.
901 #admin.site.unregister(Group)
903 #Do not show django evolution in the admin interface
904 from django_evolution.models import Version, Evolution
905 admin.site.unregister(Version)
906 admin.site.unregister(Evolution)
909 # When debugging it is often easier to see all the classes, but for regular use
910 # only the top-levels should be displayed
913 admin.site.register(Deployment, DeploymentAdmin)
914 admin.site.register(Site, SiteAdmin)
915 admin.site.register(Slice, SliceAdmin)
916 admin.site.register(ServiceClass, ServiceClassAdmin)
917 admin.site.register(Service, ServiceAdmin)
918 admin.site.register(Reservation, ReservationAdmin)
919 admin.site.register(Network, NetworkAdmin)
920 admin.site.register(Router, RouterAdmin)
921 admin.site.register(NetworkParameterType, NetworkParameterTypeAdmin)
922 admin.site.register(NetworkTemplate, NetworkTemplateAdmin)
925 #admin.site.register(PlanetStack)
926 admin.site.register(Tag, TagAdmin)
927 admin.site.register(DeploymentRole)
928 admin.site.register(SiteRole)
929 admin.site.register(SliceRole)
930 admin.site.register(PlanetStackRole)
931 admin.site.register(Node, NodeAdmin)
932 #admin.site.register(SlicePrivilege, SlicePrivilegeAdmin)
933 #admin.site.register(SitePrivilege, SitePrivilegeAdmin)
934 admin.site.register(Sliver, SliverAdmin)
935 admin.site.register(Image, ImageAdmin)