blob: d229a1746ddce2b63339cafbec4ea6d7cda90b38 [file] [log] [blame]
Siobhan Tully30fd4292013-05-10 08:59:56 -04001from core.models import Site
2from core.models import *
3from openstack.manager import OpenStackManager
Tony Macke59a7c82013-04-27 11:08:10 -04004
Tony Mack7130ac32013-03-22 21:58:00 -04005from django.contrib import admin
Siobhan Tully53437282013-04-26 19:30:27 -04006from django.contrib.auth.models import Group
Siobhan Tully4bc09f22013-04-10 21:15:21 -04007from django import forms
Tony Mackd90cdbf2013-04-16 22:48:40 -04008from django.utils.safestring import mark_safe
Tony Mack7130ac32013-03-22 21:58:00 -04009from django.contrib.auth.admin import UserAdmin
Siobhan Tully4bc09f22013-04-10 21:15:21 -040010from django.contrib.admin.widgets import FilteredSelectMultiple
Siobhan Tully53437282013-04-26 19:30:27 -040011from django.contrib.auth.forms import ReadOnlyPasswordHashField
Scott Bakeracd45142013-05-19 16:19:16 -070012from django.contrib.auth.signals import user_logged_in
13from django.utils import timezone
Siobhan Tullyde5450d2013-06-21 11:35:33 -040014from django.contrib.contenttypes import generic
Siobhan Tullybfd11dc2013-09-03 12:59:24 -040015from suit.widgets import LinkedSelect
Siobhan Tullycf04fb62014-01-11 11:25:57 -050016from django.core.exceptions import PermissionDenied
17from django.core.urlresolvers import reverse
Tony Mack7130ac32013-03-22 21:58:00 -040018
Siobhan Tullyde5450d2013-06-21 11:35:33 -040019import django_evolution
Siobhan Tully4bc09f22013-04-10 21:15:21 -040020
Siobhan Tullycf04fb62014-01-11 11:25:57 -050021class ReadOnlyAwareAdmin(admin.ModelAdmin):
22
23 def has_add_permission(self, request, obj=None):
24 return (not self.__user_is_readonly(request))
25
26 def has_delete_permission(self, request, obj=None):
27 return (not self.__user_is_readonly(request))
28
29 def save_model(self, request, obj, form, change):
30 if self.__user_is_readonly(request):
31 raise PermissionDenied
32 #pass
33 else:
34 return super(ReadOnlyAwareAdmin, self).save_model(request, obj, form, change)
35
36 def get_actions(self,request):
37 actions = super(ReadOnlyAwareAdmin,self).get_actions(request)
38
39 if self.__user_is_readonly(request):
40 if 'delete_selected' in actions:
41 del actions['delete_selected']
42
43 return actions
44
45 def change_view(self,request,object_id, extra_context=None):
46
47 if self.__user_is_readonly(request):
48 self.readonly_fields=self.user_readonly_fields
49 self.inlines = self.user_readonly_inlines
50
51 try:
52 return super(ReadOnlyAwareAdmin, self).change_view(request, object_id, extra_context=extra_context)
53 except PermissionDenied:
54 pass
55 if request.method == 'POST':
56 raise PermissionDenied
57 request.readonly = True
58 return super(ReadOnlyAwareAdmin, self).change_view(request, object_id, extra_context=extra_context)
59
60
61 def __user_is_readonly(self, request):
62 return request.user.isReadOnlyUser()
63
Siobhan Tullyce652d02013-10-08 21:52:35 -040064class SingletonAdmin (admin.ModelAdmin):
65 def has_add_permission(self, request):
66 num_objects = self.model.objects.count()
67 if num_objects >= 1:
68 return False
69 else:
70 return True
71
72
Siobhan Tullyd3515752013-06-21 16:34:53 -040073class PlStackTabularInline(admin.TabularInline):
Siobhan Tully2c780ad2013-09-06 11:22:40 -040074 pass
Siobhan Tullyd3515752013-06-21 16:34:53 -040075
Siobhan Tullycf04fb62014-01-11 11:25:57 -050076class ReadOnlyTabularInline(PlStackTabularInline):
77 can_delete = False
78
79 def get_readonly_fields(self, request, obj=None):
80 return self.fields
81
82 def has_add_permission(self, request):
83 return False
84
85class ReservationROInline(ReadOnlyTabularInline):
86 model = Reservation
87 extra = 0
88 suit_classes = 'suit-tab suit-tab-reservations'
89 fields = ['startTime','slice','duration']
90
Siobhan Tullybfd11dc2013-09-03 12:59:24 -040091class ReservationInline(PlStackTabularInline):
92 model = Reservation
93 extra = 0
94 suit_classes = 'suit-tab suit-tab-reservations'
95
Siobhan Tullycf04fb62014-01-11 11:25:57 -050096class TagROInline(generic.GenericTabularInline):
97 model = Tag
Siobhan Tully4bc09f22013-04-10 21:15:21 -040098 extra = 0
Siobhan Tullycf04fb62014-01-11 11:25:57 -050099 suit_classes = 'suit-tab suit-tab-tags'
100 can_delete = False
101 fields = ['service', 'name', 'value']
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400102
103 def get_readonly_fields(self, request, obj=None):
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500104 return self.fields
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400105
106 def has_add_permission(self, request):
107 return False
108
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500109
Siobhan Tullyde5450d2013-06-21 11:35:33 -0400110class TagInline(generic.GenericTabularInline):
111 model = Tag
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400112 extra = 0
113 suit_classes = 'suit-tab suit-tab-tags'
Siobhan Tullyde5450d2013-06-21 11:35:33 -0400114
Scott Baker74d8e622013-07-29 16:04:22 -0700115class NetworkLookerUpper:
Siobhan Tully2c780ad2013-09-06 11:22:40 -0400116 """ This is a callable that looks up a network name in a sliver and returns
117 the ip address for that network.
118 """
119
120 def __init__(self, name):
121 self.short_description = name
122 self.__name__ = name
123 self.network_name = name
124
125 def __call__(self, obj):
126 if obj is not None:
127 for nbs in obj.networksliver_set.all():
128 if (nbs.network.name == self.network_name):
129 return nbs.ip
Scott Baker74d8e622013-07-29 16:04:22 -0700130 return ""
131
132 def __str__(self):
133 return self.network_name
134
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500135class SliverROInline(ReadOnlyTabularInline):
136 model = Sliver
137 fields = ['ip', 'instance_name', 'slice', 'numberCores', 'image', 'node', 'deploymentNetwork']
138 suit_classes = 'suit-tab suit-tab-slivers'
139
Siobhan Tullyd3515752013-06-21 16:34:53 -0400140class SliverInline(PlStackTabularInline):
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400141 model = Sliver
Tony Mackb0d97422013-06-10 09:57:45 -0400142 fields = ['ip', 'instance_name', 'slice', 'numberCores', 'image', 'node', 'deploymentNetwork']
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400143 extra = 0
Tony Mack3777b012013-05-07 21:38:06 -0400144 readonly_fields = ['ip', 'instance_name']
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400145 suit_classes = 'suit-tab suit-tab-slivers'
Scott Baker74d8e622013-07-29 16:04:22 -0700146
Siobhan Tully2d95e482013-09-06 10:56:06 -0400147# Note this is breaking in the admin.py when trying to use an inline to add a node/image
148# def _declared_fieldsets(self):
149# # Return None so django will call get_fieldsets and we can insert our
150# # dynamic fields
151# return None
152#
153# def get_readonly_fields(self, request, obj=None):
154# readonly_fields = super(SliverInline, self).get_readonly_fields(request, obj)
155#
156# # Lookup the networks that are bound to the slivers, and add those
157# # network names to the list of readonly fields.
158#
159# for sliver in obj.slivers.all():
160# for nbs in sliver.networksliver_set.all():
161# if nbs.ip:
162# network_name = nbs.network.name
163# if network_name not in [str(x) for x in readonly_fields]:
164# readonly_fields.append(NetworkLookerUpper(network_name))
165#
166# return readonly_fields
167#
168# def get_fieldsets(self, request, obj=None):
169# form = self.get_formset(request, obj).form
170# # fields = the read/write files + the read-only fields
171# fields = self.fields
172# for fieldName in self.get_readonly_fields(request,obj):
173# if not fieldName in fields:
174# fields.append(fieldName)
175#
176# return [(None, {'fields': fields})]
Scott Baker74d8e622013-07-29 16:04:22 -0700177
Tony Mackc2835a92013-05-28 09:18:49 -0400178
Siobhan Tully567e3e62013-06-21 18:03:16 -0400179
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500180class SiteROInline(ReadOnlyTabularInline):
181 model = Site
182 extra = 0
183 fields = ['name', 'login_base', 'site_url', 'enabled']
184 suit_classes = 'suit-tab suit-tab-sites'
185
Siobhan Tullyd3515752013-06-21 16:34:53 -0400186class SiteInline(PlStackTabularInline):
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400187 model = Site
188 extra = 0
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400189 suit_classes = 'suit-tab suit-tab-sites'
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400190
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500191class UserROInline(ReadOnlyTabularInline):
192 model = User
193 fields = ['email', 'firstname', 'lastname']
194 extra = 0
195 suit_classes = 'suit-tab suit-tab-users'
196
Siobhan Tullyd3515752013-06-21 16:34:53 -0400197class UserInline(PlStackTabularInline):
Siobhan Tully30fd4292013-05-10 08:59:56 -0400198 model = User
Siobhan Tully47ae1b52013-05-10 15:53:14 -0400199 fields = ['email', 'firstname', 'lastname']
Siobhan Tully30fd4292013-05-10 08:59:56 -0400200 extra = 0
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400201 suit_classes = 'suit-tab suit-tab-users'
Siobhan Tully30fd4292013-05-10 08:59:56 -0400202
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500203class SliceROInline(ReadOnlyTabularInline):
204 model = Slice
205 suit_classes = 'suit-tab suit-tab-slices'
206 fields = ['name','site', 'serviceClass', 'service']
207
Siobhan Tullyd3515752013-06-21 16:34:53 -0400208class SliceInline(PlStackTabularInline):
Tony Mack00d361f2013-04-28 10:28:42 -0400209 model = Slice
Siobhan Tullyce652d02013-10-08 21:52:35 -0400210 fields = ['name','site', 'serviceClass', 'service']
Tony Mack00d361f2013-04-28 10:28:42 -0400211 extra = 0
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400212 suit_classes = 'suit-tab suit-tab-slices'
213
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500214class NodeROInline(ReadOnlyTabularInline):
215 model = Node
216 extra = 0
217 suit_classes = 'suit-tab suit-tab-nodes'
218 fields = ['name','deployment']
Tony Mack00d361f2013-04-28 10:28:42 -0400219
Siobhan Tullyd3515752013-06-21 16:34:53 -0400220class NodeInline(PlStackTabularInline):
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400221 model = Node
222 extra = 0
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400223 suit_classes = 'suit-tab suit-tab-nodes'
224
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500225class DeploymentPrivilegeROInline(ReadOnlyTabularInline):
226 model = DeploymentPrivilege
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400227 extra = 0
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500228 suit_classes = 'suit-tab suit-tab-deploymentprivileges'
229 fields = ['user','role']
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400230
231class DeploymentPrivilegeInline(PlStackTabularInline):
232 model = DeploymentPrivilege
233 extra = 0
234 suit_classes = 'suit-tab suit-tab-deploymentprivileges'
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400235
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500236#CLEANUP DOUBLE SitePrivilegeInline
237class SitePrivilegeROInline(ReadOnlyTabularInline):
238 model = SitePrivilege
239 extra = 0
240 suit_classes = 'suit-tab suit-tab-siteprivileges'
241 fields = ['user','site', 'role']
242
Siobhan Tullyd3515752013-06-21 16:34:53 -0400243class SitePrivilegeInline(PlStackTabularInline):
Siobhan Tullyaa1bcd52013-05-10 12:43:09 -0400244 model = SitePrivilege
245 extra = 0
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400246 suit_classes = 'suit-tab suit-tab-siteprivileges'
Siobhan Tullyaa1bcd52013-05-10 12:43:09 -0400247
Tony Mackc2835a92013-05-28 09:18:49 -0400248 def formfield_for_foreignkey(self, db_field, request, **kwargs):
249 if db_field.name == 'site':
250 if not request.user.is_admin:
251 # only show sites where user is an admin or pi
252 roles = Role.objects.filter(role_type__in=['admin', 'pi'])
253 site_privileges = SitePrivilege.objects.filter(user=request.user).filter(role__in=roles)
254 login_bases = [site_privilege.site.login_base for site_privilege in site_privileges]
255 sites = Site.objects.filter(login_base__in=login_bases)
256 kwargs['queryset'] = sites
257
258 if db_field.name == 'user':
259 if not request.user.is_admin:
260 # only show users from sites where caller has admin or pi role
261 roles = Role.objects.filter(role_type__in=['admin', 'pi'])
262 site_privileges = SitePrivilege.objects.filter(user=request.user).filter(role__in=roles)
263 sites = [site_privilege.site for site_privilege in site_privileges]
264 site_privileges = SitePrivilege.objects.filter(site__in=sites)
265 emails = [site_privilege.user.email for site_privilege in site_privileges]
266 users = User.objects.filter(email__in=emails)
267 kwargs['queryset'] = users
268 return super(SitePrivilegeInline, self).formfield_for_foreignkey(db_field, request, **kwargs)
269
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400270class SitePrivilegeInline(PlStackTabularInline):
271 model = SitePrivilege
272 suit_classes = 'suit-tab suit-tab-siteprivileges'
Siobhan Tullyaa1bcd52013-05-10 12:43:09 -0400273 extra = 0
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400274 fields = ('user', 'site','role')
275
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500276class SlicePrivilegeROInline(ReadOnlyTabularInline):
277 model = SlicePrivilege
278 extra = 0
279 suit_classes = 'suit-tab suit-tab-sliceprivileges'
280 fields = ['user', 'slice', 'role']
281
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400282class SlicePrivilegeInline(PlStackTabularInline):
283 model = SlicePrivilege
284 suit_classes = 'suit-tab suit-tab-sliceprivileges'
285 extra = 0
286 fields = ('user', 'slice','role')
Siobhan Tullyaa1bcd52013-05-10 12:43:09 -0400287
Tony Mackc2835a92013-05-28 09:18:49 -0400288 def formfield_for_foreignkey(self, db_field, request, **kwargs):
289 if db_field.name == 'slice':
290 if not request.user.is_admin:
291 # only show slices at sites where caller has admin or pi role
292 roles = Role.objects.filter(role_type__in=['admin', 'pi'])
293 site_privileges = SitePrivilege.objects.filter(user=request.user).filter(role__in=roles)
294 sites = [site_privilege.site for site_privilege in site_privileges]
295 slices = Slice.objects.filter(site__in=sites)
296 kwargs['queryset'] = slices
297 if db_field.name == 'user':
298 if not request.user.is_admin:
299 # only show users from sites where caller has admin or pi role
300 roles = Role.objects.filter(role_type__in=['admin', 'pi'])
301 site_privileges = SitePrivilege.objects.filter(user=request.user).filter(role__in=roles)
302 sites = [site_privilege.site for site_privilege in site_privileges]
303 site_privileges = SitePrivilege.objects.filter(site__in=sites)
304 emails = [site_privilege.user.email for site_privilege in site_privileges]
305 users = User.objects.filter(email__in=emails)
306 kwargs['queryset'] = list(users)
307
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400308 return super(SlicePrivilegeInline, self).formfield_for_foreignkey(db_field, request, **kwargs)
Tony Mackc2835a92013-05-28 09:18:49 -0400309
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500310class SliceNetworkROInline(ReadOnlyTabularInline):
311 model = Network.slices.through
312 extra = 0
313 verbose_name = "Network Connection"
314 verbose_name_plural = "Network Connections"
315 suit_classes = 'suit-tab suit-tab-slicenetworks'
316 fields = ['network']
317
Scott Bakera0015eb2013-08-14 17:28:14 -0700318class SliceNetworkInline(PlStackTabularInline):
Scott Baker74d8e622013-07-29 16:04:22 -0700319 model = Network.slices.through
320 extra = 0
321 verbose_name = "Network Connection"
322 verbose_name_plural = "Network Connections"
Siobhan Tully2d95e482013-09-06 10:56:06 -0400323 suit_classes = 'suit-tab suit-tab-slicenetworks'
Scott Baker74d8e622013-07-29 16:04:22 -0700324
Tony Mack5e71a662013-05-03 23:30:41 -0400325class PlainTextWidget(forms.HiddenInput):
326 input_type = 'hidden'
327
328 def render(self, name, value, attrs=None):
329 if value is None:
330 value = ''
Tony Mack1d6b85f2013-05-07 18:49:14 -0400331 return mark_safe(str(value) + super(PlainTextWidget, self).render(name, value, attrs))
Tony Mack9bcbe4f2013-04-29 08:13:27 -0400332
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500333class PlanetStackBaseAdmin(ReadOnlyAwareAdmin):
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400334 save_on_top = False
335
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400336class SliceRoleAdmin(PlanetStackBaseAdmin):
337 model = SliceRole
338 pass
339
340class SiteRoleAdmin(PlanetStackBaseAdmin):
341 model = SiteRole
342 pass
343
Siobhan Tullybf1153a2013-05-27 20:53:48 -0400344class DeploymentAdminForm(forms.ModelForm):
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400345 sites = forms.ModelMultipleChoiceField(
346 queryset=Site.objects.all(),
347 required=False,
348 widget=FilteredSelectMultiple(
349 verbose_name=('Sites'), is_stacked=False
350 )
351 )
352 class Meta:
Siobhan Tullybf1153a2013-05-27 20:53:48 -0400353 model = Deployment
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400354
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500355class SiteAssocInline(PlStackTabularInline):
356 model = Site.deployments.through
357 extra = 0
358 suit_classes = 'suit-tab suit-tab-sites'
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400359
Siobhan Tullybf1153a2013-05-27 20:53:48 -0400360class DeploymentAdmin(PlanetStackBaseAdmin):
361 form = DeploymentAdminForm
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500362 model = Deployment
363 fieldList = ['name','sites']
364 fieldsets = [(None, {'fields': fieldList, 'classes':['suit-tab suit-tab-sites']})]
Siobhan Tully2d95e482013-09-06 10:56:06 -0400365 inlines = [DeploymentPrivilegeInline,NodeInline,TagInline]
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500366
367 user_readonly_inlines = [DeploymentPrivilegeROInline,NodeROInline,TagROInline]
368 user_readonly_fields = ['name']
369
370 suit_form_tabs =(('sites','Deployment Details'),('nodes','Nodes'),('deploymentprivileges','Privileges'),('tags','Tags'))
371
372class ServiceAttrAsTabROInline(ReadOnlyTabularInline):
373 model = ServiceAttribute
374 fields = ['name','value']
375 extra = 0
376 suit_classes = 'suit-tab suit-tab-serviceattrs'
Tony Mack5cd13202013-05-01 21:48:38 -0400377
Siobhan Tullyce652d02013-10-08 21:52:35 -0400378class ServiceAttrAsTabInline(PlStackTabularInline):
379 model = ServiceAttribute
380 fields = ['name','value']
381 extra = 0
382 suit_classes = 'suit-tab suit-tab-serviceattrs'
383
Siobhan Tullyce652d02013-10-08 21:52:35 -0400384class ServiceAdmin(PlanetStackBaseAdmin):
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500385 list_display = ("name","description","versionNumber","enabled","published")
386 fieldList = ["name","description","versionNumber","enabled","published"]
387 fieldsets = [(None, {'fields': fieldList, 'classes':['suit-tab suit-tab-general']})]
388 inlines = [ServiceAttrAsTabInline,SliceInline]
389
390 user_readonly_fields = fieldList
391 user_readonly_inlines = [ServiceAttrAsTabROInline,SliceROInline]
392
393 suit_form_tabs =(('general', 'Service Details'),
394 ('slices','Slices'),
395 ('serviceattrs','Additional Attributes'),
396 )
Siobhan Tullyce652d02013-10-08 21:52:35 -0400397
Tony Mack0553f282013-06-10 22:54:50 -0400398class SiteAdmin(PlanetStackBaseAdmin):
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500399 fieldList = ['name', 'site_url', 'enabled', 'is_public', 'login_base', 'accountLink','location']
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400400 fieldsets = [
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500401 (None, {'fields': fieldList, 'classes':['suit-tab suit-tab-general']}),
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400402 ('Deployment Networks', {'fields': ['deployments'], 'classes':['suit-tab suit-tab-deployments']}),
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400403 ]
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400404 suit_form_tabs =(('general', 'Site Details'),
405 ('users','Users'),
Siobhan Tully2d95e482013-09-06 10:56:06 -0400406 ('siteprivileges','Privileges'),
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400407 ('deployments','Deployments'),
408 ('slices','Slices'),
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500409 ('nodes','Nodes'),
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400410 ('tags','Tags'),
411 )
Scott Baker545db2a2013-12-09 18:44:43 -0800412 readonly_fields = ['accountLink']
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500413
414 user_readonly_fields = ['name', 'deployments','site_url', 'enabled', 'is_public', 'login_base', 'accountLink']
415 user_readonly_inlines = [SliceROInline,UserROInline,TagROInline, NodeROInline, SitePrivilegeROInline]
416
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400417 list_display = ('name', 'login_base','site_url', 'enabled')
418 filter_horizontal = ('deployments',)
Siobhan Tully2d95e482013-09-06 10:56:06 -0400419 inlines = [SliceInline,UserInline,TagInline, NodeInline, SitePrivilegeInline]
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400420 search_fields = ['name']
421
Tony Mack04062832013-05-10 08:22:44 -0400422 def queryset(self, request):
423 # admins can see all keys. Users can only see sites they belong to.
424 qs = super(SiteAdmin, self).queryset(request)
425 if not request.user.is_admin:
426 valid_sites = [request.user.site.login_base]
427 roles = request.user.get_roles()
428 for tenant_list in roles.values():
429 valid_sites.extend(tenant_list)
430 qs = qs.filter(login_base__in=valid_sites)
431 return qs
432
Tony Mack5cd13202013-05-01 21:48:38 -0400433 def get_formsets(self, request, obj=None):
434 for inline in self.get_inline_instances(request, obj):
435 # hide MyInline in the add view
436 if obj is None:
437 continue
Tony Mack2bd5b412013-06-11 21:05:06 -0400438 if isinstance(inline, SliceInline):
439 inline.model.caller = request.user
440 yield inline.get_formset(request, obj)
441
442 def get_formsets(self, request, obj=None):
443 for inline in self.get_inline_instances(request, obj):
444 # hide MyInline in the add view
445 if obj is None:
446 continue
447 if isinstance(inline, SliverInline):
448 inline.model.caller = request.user
Tony Mack5cd13202013-05-01 21:48:38 -0400449 yield inline.get_formset(request, obj)
450
Scott Baker545db2a2013-12-09 18:44:43 -0800451 def accountLink(self, obj):
452 link_obj = obj.accounts.all()
453 if link_obj:
454 reverse_path = "admin:core_account_change"
455 url = reverse(reverse_path, args =(link_obj[0].id,))
456 return "<a href='%s'>%s</a>" % (url, "view billing details")
457 else:
458 return "no billing data for this site"
459 accountLink.allow_tags = True
460 accountLink.short_description = "Billing"
461
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500462
Tony Mack9bcbe4f2013-04-29 08:13:27 -0400463class SitePrivilegeAdmin(PlanetStackBaseAdmin):
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500464 fieldList = ['user', 'site', 'role']
Tony Mack00d361f2013-04-28 10:28:42 -0400465 fieldsets = [
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500466 (None, {'fields': fieldList, 'classes':['collapse']})
Tony Mack00d361f2013-04-28 10:28:42 -0400467 ]
468 list_display = ('user', 'site', 'role')
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500469 user_readonly_fields = fieldList
470 user_readonly_inlines = []
Tony Mack00d361f2013-04-28 10:28:42 -0400471
Tony Mackc2835a92013-05-28 09:18:49 -0400472 def formfield_for_foreignkey(self, db_field, request, **kwargs):
473 if db_field.name == 'site':
474 if not request.user.is_admin:
475 # only show sites where user is an admin or pi
476 sites = set()
477 for site_privilege in SitePrivilege.objects.filer(user=request.user):
478 if site_privilege.role.role_type in ['admin', 'pi']:
479 sites.add(site_privilege.site)
480 kwargs['queryset'] = Site.objects.filter(site__in=list(sites))
481
482 if db_field.name == 'user':
483 if not request.user.is_admin:
484 # only show users from sites where caller has admin or pi role
485 roles = Role.objects.filter(role_type__in=['admin', 'pi'])
486 site_privileges = SitePrivilege.objects.filter(user=request.user).filter(role__in=roles)
487 sites = [site_privilege.site for site_privilege in site_privileges]
488 site_privileges = SitePrivilege.objects.filter(site__in=sites)
489 emails = [site_privilege.user.email for site_privilege in site_privileges]
490 users = User.objects.filter(email__in=emails)
491 kwargs['queryset'] = users
492
493 return super(SitePrivilegeAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)
494
Tony Mack04062832013-05-10 08:22:44 -0400495 def queryset(self, request):
496 # admins can see all privileges. Users can only see privileges at sites
Tony Mackc2835a92013-05-28 09:18:49 -0400497 # where they have the admin role or pi role.
Tony Mack04062832013-05-10 08:22:44 -0400498 qs = super(SitePrivilegeAdmin, self).queryset(request)
499 if not request.user.is_admin:
Tony Mackc2835a92013-05-28 09:18:49 -0400500 roles = Role.objects.filter(role_type__in=['admin', 'pi'])
501 site_privileges = SitePrivilege.objects.filter(user=request.user).filter(role__in=roles)
502 login_bases = [site_privilege.site.login_base for site_privilege in site_privileges]
503 sites = Site.objects.filter(login_base__in=login_bases)
504 qs = qs.filter(site__in=sites)
Tony Mack04062832013-05-10 08:22:44 -0400505 return qs
506
Siobhan Tullyce652d02013-10-08 21:52:35 -0400507class SliceForm(forms.ModelForm):
508 class Meta:
509 model = Slice
510 widgets = {
511 'service': LinkedSelect
512 }
513
Tony Mack2bd5b412013-06-11 21:05:06 -0400514class SliceAdmin(PlanetStackBaseAdmin):
Siobhan Tullyce652d02013-10-08 21:52:35 -0400515 form = SliceForm
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500516 fieldList = ['name', 'site', 'serviceClass', 'enabled','description', 'service', 'slice_url']
517 fieldsets = [('Slice Details', {'fields': fieldList, 'classes':['suit-tab suit-tab-general']}),]
Siobhan Tully30fd4292013-05-10 08:59:56 -0400518 list_display = ('name', 'site','serviceClass', 'slice_url')
Siobhan Tully2d95e482013-09-06 10:56:06 -0400519 inlines = [SlicePrivilegeInline,SliverInline, TagInline, ReservationInline,SliceNetworkInline]
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400520
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500521 user_readonly_fields = fieldList
522 user_readonly_inlines = [SlicePrivilegeROInline,SliverROInline,TagROInline, ReservationROInline, SliceNetworkROInline]
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400523
524 suit_form_tabs =(('general', 'Slice Details'),
Siobhan Tully2d95e482013-09-06 10:56:06 -0400525 ('slicenetworks','Networks'),
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400526 ('sliceprivileges','Privileges'),
527 ('slivers','Slivers'),
528 ('tags','Tags'),
529 ('reservations','Reservations'),
530 )
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400531
Tony Mackc2835a92013-05-28 09:18:49 -0400532 def formfield_for_foreignkey(self, db_field, request, **kwargs):
533 if db_field.name == 'site':
534 if not request.user.is_admin:
535 # only show sites where user is a pi or admin
536 roles = Role.objects.filter(role_type__in=['admin', 'pi'])
537 site_privileges = SitePrivilege.objects.filter(user=request.user).filter(role__in=roles)
538 login_bases = [site_privilege.site.login_base for site_privilege in site_privileges]
539 sites = Site.objects.filter(login_base__in=login_bases)
540 kwargs['queryset'] = sites
541
542 return super(SliceAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)
543
Tony Mack04062832013-05-10 08:22:44 -0400544 def queryset(self, request):
545 # admins can see all keys. Users can only see slices they belong to.
546 qs = super(SliceAdmin, self).queryset(request)
547 if not request.user.is_admin:
548 valid_slices = []
549 roles = request.user.get_roles()
550 for tenant_list in roles.values():
551 valid_slices.extend(tenant_list)
552 qs = qs.filter(name__in=valid_slices)
553 return qs
554
Tony Mack79748612013-05-01 14:52:03 -0400555 def get_formsets(self, request, obj=None):
556 for inline in self.get_inline_instances(request, obj):
557 # hide MyInline in the add view
558 if obj is None:
559 continue
Tony Mack2bd5b412013-06-11 21:05:06 -0400560 if isinstance(inline, SliverInline):
561 inline.model.caller = request.user
Tony Mack79748612013-05-01 14:52:03 -0400562 yield inline.get_formset(request, obj)
563
Tony Mackfdd4d802013-04-27 13:02:33 -0400564 def get_queryset(self, request):
565 qs = super(SliceAdmin, self).get_queryset(request)
566 if request.user.is_superuser:
567 return qs
568 # users can only see slices at their site
Tony Mack2bd5b412013-06-11 21:05:06 -0400569 return qs.filter(site=request.user.site)
570
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400571class SlicePrivilegeAdmin(PlanetStackBaseAdmin):
Tony Mack00d361f2013-04-28 10:28:42 -0400572 fieldsets = [
573 (None, {'fields': ['user', 'slice', 'role']})
574 ]
575 list_display = ('user', 'slice', 'role')
Tony Mack00d361f2013-04-28 10:28:42 -0400576
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500577 user_readonly_fields = ['user', 'slice', 'role']
578 user_readonly_inlines = []
579
Tony Mackc2835a92013-05-28 09:18:49 -0400580 def formfield_for_foreignkey(self, db_field, request, **kwargs):
581 if db_field.name == 'slice':
582 if not request.user.is_admin:
583 # only show slices at sites where caller has admin or pi role
584 roles = Role.objects.filter(role_type__in=['admin', 'pi'])
585 site_privileges = SitePrivilege.objects.filter(user=request.user).filter(role__in=roles)
586 sites = [site_privilege.site for site_privilege in site_privileges]
587 slices = Slice.objects.filter(site__in=sites)
588 kwargs['queryset'] = slices
589
590 if db_field.name == 'user':
591 if not request.user.is_admin:
592 # only show users from sites where caller has admin or pi role
593 roles = Role.objects.filter(role_type__in=['admin', 'pi'])
594 site_privileges = SitePrivilege.objects.filter(user=request.user).filter(role__in=roles)
595 sites = [site_privilege.site for site_privilege in site_privileges]
596 site_privileges = SitePrivilege.objects.filter(site__in=sites)
597 emails = [site_privilege.user.email for site_privilege in site_privileges]
598 users = User.objects.filter(email__in=emails)
599 kwargs['queryset'] = users
600
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400601 return super(SlicePrivilegeAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)
Tony Mackc2835a92013-05-28 09:18:49 -0400602
Tony Mack04062832013-05-10 08:22:44 -0400603 def queryset(self, request):
604 # admins can see all memberships. Users can only see memberships of
605 # slices where they have the admin role.
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400606 qs = super(SlicePrivilegeAdmin, self).queryset(request)
Tony Mack04062832013-05-10 08:22:44 -0400607 if not request.user.is_admin:
Tony Mackc2835a92013-05-28 09:18:49 -0400608 roles = Role.objects.filter(role_type__in=['admin', 'pi'])
609 site_privileges = SitePrivilege.objects.filter(user=request.user).filter(role__in=roles)
610 login_bases = [site_privilege.site.login_base for site_privilege in site_privileges]
611 sites = Site.objects.filter(login_base__in=login_bases)
612 slices = Slice.objects.filter(site__in=sites)
613 qs = qs.filter(slice__in=slices)
Tony Mack04062832013-05-10 08:22:44 -0400614 return qs
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400615
Tony Mack9bcbe4f2013-04-29 08:13:27 -0400616 def save_model(self, request, obj, form, change):
Tony Mack951dab42013-05-02 19:51:45 -0400617 # update openstack connection to use this site/tenant
618 auth = request.session.get('auth', {})
619 auth['tenant'] = obj.slice.name
620 obj.os_manager = OpenStackManager(auth=auth, caller=request.user)
Tony Mack9bcbe4f2013-04-29 08:13:27 -0400621 obj.save()
622
623 def delete_model(self, request, obj):
Tony Mack951dab42013-05-02 19:51:45 -0400624 # update openstack connection to use this site/tenant
625 auth = request.session.get('auth', {})
626 auth['tenant'] = obj.slice.name
627 obj.os_manager = OpenStackManager(auth=auth, caller=request.user)
Tony Mack9bcbe4f2013-04-29 08:13:27 -0400628 obj.delete()
629
Siobhan Tully567e3e62013-06-21 18:03:16 -0400630
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400631class ImageAdmin(PlanetStackBaseAdmin):
632
633 fieldsets = [('Image Details',
634 {'fields': ['image_id', 'name', 'disk_format', 'container_format'],
635 'classes': ['suit-tab suit-tab-general']})
636 ]
637
638 suit_form_tabs =(('general','Image Details'),('slivers','Slivers'))
639
640 inlines = [SliverInline]
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500641
642 user_readonly_fields = ['image_id', 'name', 'disk_format', 'container_format']
643 user_readonly_inlines = [SliverROInline]
644
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400645class NodeForm(forms.ModelForm):
646 class Meta:
647 widgets = {
648 'site': LinkedSelect,
649 'deployment': LinkedSelect
650 }
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400651
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500652class NodeAdmin(PlanetStackBaseAdmin):
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400653 form = NodeForm
Siobhan Tullybf1153a2013-05-27 20:53:48 -0400654 list_display = ('name', 'site', 'deployment')
655 list_filter = ('deployment',)
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500656
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400657 inlines = [TagInline,SliverInline]
658 fieldsets = [('Node Details', {'fields': ['name','site','deployment'], 'classes':['suit-tab suit-tab-details']})]
659
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500660 user_readonly_fields = ['name','site','deployment']
661 user_readonly_inlines = [TagInline,SliverInline]
662
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400663 suit_form_tabs =(('details','Node Details'),('slivers','Slivers'),('tags','Tags'))
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400664
Siobhan Tully567e3e62013-06-21 18:03:16 -0400665
Tony Mackd90cdbf2013-04-16 22:48:40 -0400666class SliverForm(forms.ModelForm):
667 class Meta:
Tony Mack1d6b85f2013-05-07 18:49:14 -0400668 model = Sliver
Tony Mackd90cdbf2013-04-16 22:48:40 -0400669 ip = forms.CharField(widget=PlainTextWidget)
Tony Mack18261812013-05-02 16:39:20 -0400670 instance_name = forms.CharField(widget=PlainTextWidget)
Tony Mackd90cdbf2013-04-16 22:48:40 -0400671 widgets = {
672 'ip': PlainTextWidget(),
Tony Mack18261812013-05-02 16:39:20 -0400673 'instance_name': PlainTextWidget(),
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400674 'slice': LinkedSelect,
675 'deploymentNetwork': LinkedSelect,
676 'node': LinkedSelect,
677 'image': LinkedSelect
Siobhan Tully53437282013-04-26 19:30:27 -0400678 }
Tony Mackd90cdbf2013-04-16 22:48:40 -0400679
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500680class TagAdmin(PlanetStackBaseAdmin):
Siobhan Tullyce652d02013-10-08 21:52:35 -0400681 list_display = ['service', 'name', 'value', 'content_type', 'content_object',]
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500682 user_readonly_fields = ['service', 'name', 'value', 'content_type', 'content_object',]
683 user_readonly_inlines = []
Siobhan Tullyd3515752013-06-21 16:34:53 -0400684
Tony Mack9bcbe4f2013-04-29 08:13:27 -0400685class SliverAdmin(PlanetStackBaseAdmin):
Tony Mackd90cdbf2013-04-16 22:48:40 -0400686 form = SliverForm
Tony Mackcdec0902013-04-15 00:38:49 -0400687 fieldsets = [
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400688 ('Sliver Details', {'fields': ['slice', 'deploymentNetwork', 'node', 'ip', 'instance_name', 'numberCores', 'image', ], 'classes': ['suit-tab suit-tab-general'], })
Tony Mackcdec0902013-04-15 00:38:49 -0400689 ]
Siobhan Tully5d7dc8d2013-07-02 13:17:33 -0400690 list_display = ['ip', 'instance_name', 'slice', 'numberCores', 'image', 'node', 'deploymentNetwork']
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400691
692 suit_form_tabs =(('general', 'Sliver Details'),
693 ('tags','Tags'),
694 )
695
Siobhan Tullyde5450d2013-06-21 11:35:33 -0400696 inlines = [TagInline]
Tony Mack53106f32013-04-27 16:43:01 -0400697
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500698 user_readonly_fields = ['slice', 'deploymentNetwork', 'node', 'ip', 'instance_name', 'numberCores', 'image']
699 user_readonly_inlines = [TagROInline]
700
Tony Mackc2835a92013-05-28 09:18:49 -0400701 def formfield_for_foreignkey(self, db_field, request, **kwargs):
702 if db_field.name == 'slice':
703 if not request.user.is_admin:
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400704 slices = set([sm.slice.name for sm in SlicePrivilege.objects.filter(user=request.user)])
Tony Mackc2835a92013-05-28 09:18:49 -0400705 kwargs['queryset'] = Slice.objects.filter(name__in=list(slices))
706
707 return super(SliverAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)
708
Tony Mack04062832013-05-10 08:22:44 -0400709 def queryset(self, request):
710 # admins can see all slivers. Users can only see slivers of
711 # the slices they belong to.
712 qs = super(SliverAdmin, self).queryset(request)
713 if not request.user.is_admin:
714 tenants = []
715 roles = request.user.get_roles()
716 for tenant_list in roles.values():
717 tenants.extend(tenant_list)
718 valid_slices = Slice.objects.filter(name__in=tenants)
719 qs = qs.filter(slice__in=valid_slices)
720 return qs
721
Tony Mack1d6b85f2013-05-07 18:49:14 -0400722 def get_formsets(self, request, obj=None):
723 # make some fields read only if we are updating an existing record
724 if obj == None:
725 #self.readonly_fields = ('ip', 'instance_name')
726 self.readonly_fields = ()
727 else:
Tony Mack1e889462013-05-10 21:34:54 -0400728 self.readonly_fields = ()
729 #self.readonly_fields = ('ip', 'instance_name', 'slice', 'image', 'key')
Tony Mack1d6b85f2013-05-07 18:49:14 -0400730
731 for inline in self.get_inline_instances(request, obj):
732 # hide MyInline in the add view
733 if obj is None:
734 continue
735 # give inline object access to driver and caller
736 auth = request.session.get('auth', {})
737 auth['tenant'] = obj.name # meed to connect using slice's tenant
738 inline.model.os_manager = OpenStackManager(auth=auth, caller=request.user)
739 yield inline.get_formset(request, obj)
Tony Mack53106f32013-04-27 16:43:01 -0400740
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500741 #def save_model(self, request, obj, form, change):
742 # # update openstack connection to use this site/tenant
743 # auth = request.session.get('auth', {})
744 # auth['tenant'] = obj.slice.name
745 # obj.os_manager = OpenStackManager(auth=auth, caller=request.user)
746 # obj.creator = request.user
747 # obj.save()
Tony Mack53106f32013-04-27 16:43:01 -0400748
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500749 #def delete_model(self, request, obj):
750 # # update openstack connection to use this site/tenant
751 # auth = request.session.get('auth', {})
752 # auth['tenant'] = obj.slice.name
753 # obj.os_manager = OpenStackManager(auth=auth, caller=request.user)
754 # obj.delete()
Tony Mackcdec0902013-04-15 00:38:49 -0400755
Siobhan Tully53437282013-04-26 19:30:27 -0400756class UserCreationForm(forms.ModelForm):
757 """A form for creating new users. Includes all the required
758 fields, plus a repeated password."""
759 password1 = forms.CharField(label='Password', widget=forms.PasswordInput)
760 password2 = forms.CharField(label='Password confirmation', widget=forms.PasswordInput)
761
762 class Meta:
Siobhan Tully30fd4292013-05-10 08:59:56 -0400763 model = User
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400764 fields = ('email', 'firstname', 'lastname', 'phone', 'public_key')
Siobhan Tully53437282013-04-26 19:30:27 -0400765
766 def clean_password2(self):
767 # Check that the two password entries match
768 password1 = self.cleaned_data.get("password1")
769 password2 = self.cleaned_data.get("password2")
770 if password1 and password2 and password1 != password2:
771 raise forms.ValidationError("Passwords don't match")
772 return password2
773
774 def save(self, commit=True):
775 # Save the provided password in hashed format
776 user = super(UserCreationForm, self).save(commit=False)
Tony Mackf9f4afb2013-05-01 21:02:12 -0400777 user.password = self.cleaned_data["password1"]
778 #user.set_password(self.cleaned_data["password1"])
Siobhan Tully53437282013-04-26 19:30:27 -0400779 if commit:
780 user.save()
781 return user
782
Siobhan Tully567e3e62013-06-21 18:03:16 -0400783
Siobhan Tully53437282013-04-26 19:30:27 -0400784class UserChangeForm(forms.ModelForm):
785 """A form for updating users. Includes all the fields on
786 the user, but replaces the password field with admin's
787 password hash display field.
788 """
789 password = ReadOnlyPasswordHashField()
790
791 class Meta:
Siobhan Tully30fd4292013-05-10 08:59:56 -0400792 model = User
Siobhan Tully53437282013-04-26 19:30:27 -0400793
794 def clean_password(self):
795 # Regardless of what the user provides, return the initial value.
796 # This is done here, rather than on the field, because the
797 # field does not have access to the initial value
798 return self.initial["password"]
799
Siobhan Tully567e3e62013-06-21 18:03:16 -0400800
Tony Mack2bd5b412013-06-11 21:05:06 -0400801class UserAdmin(UserAdmin):
Siobhan Tully53437282013-04-26 19:30:27 -0400802 class Meta:
803 app_label = "core"
804
805 # The forms to add and change user instances
806 form = UserChangeForm
807 add_form = UserCreationForm
808
809 # The fields to be used in displaying the User model.
810 # These override the definitions on the base UserAdmin
811 # that reference specific fields on auth.User.
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500812 list_display = ('email', 'firstname', 'lastname', 'site', 'last_login')
Siobhan Tullyce652d02013-10-08 21:52:35 -0400813 #list_display = ('email', 'username','firstname', 'lastname', 'is_admin', 'last_login')
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500814 list_filter = ('site',)
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400815 inlines = [SlicePrivilegeInline,SitePrivilegeInline,DeploymentPrivilegeInline]
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500816
817 fieldListLoginDetails = ['email','site','password','is_readonly','is_amin','public_key']
818 fieldListContactInfo = ['firstname','lastname','phone','timezone']
819
Siobhan Tully53437282013-04-26 19:30:27 -0400820 fieldsets = (
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500821 ('Login Details', {'fields': ['email', 'site','password', 'is_readonly', 'is_admin', 'public_key'], 'classes':['suit-tab suit-tab-general']}),
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400822 ('Contact Information', {'fields': ('firstname','lastname','phone', 'timezone'), 'classes':['suit-tab suit-tab-contact']}),
Siobhan Tully53437282013-04-26 19:30:27 -0400823 #('Important dates', {'fields': ('last_login',)}),
824 )
825 add_fieldsets = (
826 (None, {
827 'classes': ('wide',),
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500828 'fields': ('email', 'firstname', 'lastname', 'is_readonly', 'phone', 'public_key','password1', 'password2')}
Siobhan Tully53437282013-04-26 19:30:27 -0400829 ),
830 )
831 search_fields = ('email',)
832 ordering = ('email',)
833 filter_horizontal = ()
834
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500835 user_readonly_fields = fieldListLoginDetails
836 user_readonly_inlines = [SlicePrivilegeROInline,SitePrivilegeROInline,DeploymentPrivilegeROInline]
837
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400838 suit_form_tabs =(('general','Login Details'),('contact','Contact Information'),('sliceprivileges','Slice Privileges'),('siteprivileges','Site Privileges'),('deploymentprivileges','Deployment Privileges'))
839
Tony Mackc2835a92013-05-28 09:18:49 -0400840 def formfield_for_foreignkey(self, db_field, request, **kwargs):
841 if db_field.name == 'site':
842 if not request.user.is_admin:
843 # show sites where caller is an admin or pi
844 sites = []
845 for site_privilege in SitePrivilege.objects.filer(user=request.user):
846 if site_privilege.role.role_type in ['admin', 'pi']:
847 sites.append(site_privilege.site.login_base)
848 kwargs['queryset'] = Site.objects.filter(login_base__in(list(sites)))
849
850 return super(UserAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)
851
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500852 def has_add_permission(self, request, obj=None):
853 return (not self.__user_is_readonly(request))
854
855 def has_delete_permission(self, request, obj=None):
856 return (not self.__user_is_readonly(request))
857
858 def get_actions(self,request):
859 actions = super(UserAdmin,self).get_actions(request)
860
861 if self.__user_is_readonly(request):
862 if 'delete_selected' in actions:
863 del actions['delete_selected']
864
865 return actions
866
867 def change_view(self,request,object_id, extra_context=None):
868
869 if self.__user_is_readonly(request):
870 self.readonly_fields=self.user_readonly_fields
871 self.inlines = self.user_readonly_inlines
872 try:
873 return super(UserAdmin, self).change_view(request, object_id, extra_context=extra_context)
874 except PermissionDenied:
875 pass
876 if request.method == 'POST':
877 raise PermissionDenied
878 request.readonly = True
879 return super(UserAdmin, self).change_view(request, object_id, extra_context=extra_context)
880
881 def __user_is_readonly(self, request):
882 #groups = [x.name for x in request.user.groups.all() ]
883 #return "readonly" in groups
884 return request.user.isReadOnlyUser()
885
886
887
888class ServiceResourceROInline(ReadOnlyTabularInline):
889 model = ServiceResource
890 extra = 0
891 fields = ['serviceClass', 'name', 'maxUnitsDeployment', 'maxUnitsNode', 'maxDuration', 'bucketInRate', 'bucketMaxSize', 'cost', 'calendarReservable']
892
Scott Baker3de3e372013-05-10 16:50:44 -0700893class ServiceResourceInline(admin.TabularInline):
894 model = ServiceResource
895 extra = 0
896
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500897class ServiceClassAdmin(PlanetStackBaseAdmin):
Scott Baker3de3e372013-05-10 16:50:44 -0700898 list_display = ('name', 'commitment', 'membershipFee')
899 inlines = [ServiceResourceInline]
900
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500901 user_readonly_fields = ['name', 'commitment', 'membershipFee']
902 user_readonly_inlines = []
903
904class ReservedResourceROInline(ReadOnlyTabularInline):
905 model = ReservedResource
906 extra = 0
907 fields = ['sliver', 'resource','quantity','reservationSet']
908 suit_classes = 'suit-tab suit-tab-reservedresources'
909
Scott Baker133c9212013-05-17 09:09:11 -0700910class ReservedResourceInline(admin.TabularInline):
911 model = ReservedResource
912 extra = 0
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400913 suit_classes = 'suit-tab suit-tab-reservedresources'
Scott Baker133c9212013-05-17 09:09:11 -0700914
915 def formfield_for_foreignkey(self, db_field, request=None, **kwargs):
916 field = super(ReservedResourceInline, self).formfield_for_foreignkey(db_field, request, **kwargs)
917
918 if db_field.name == 'resource':
919 # restrict resources to those that the slice's service class allows
920 if request._slice is not None:
921 field.queryset = field.queryset.filter(serviceClass = request._slice.serviceClass, calendarReservable=True)
922 if len(field.queryset) > 0:
923 field.initial = field.queryset.all()[0]
924 else:
925 field.queryset = field.queryset.none()
926 elif db_field.name == 'sliver':
927 # restrict slivers to those that belong to the slice
928 if request._slice is not None:
929 field.queryset = field.queryset.filter(slice = request._slice)
930 else:
931 field.queryset = field.queryset.none()
932
933 return field
934
935class ReservationChangeForm(forms.ModelForm):
936 class Meta:
937 model = Reservation
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400938 widgets = {
939 'slice' : LinkedSelect
940 }
Scott Baker133c9212013-05-17 09:09:11 -0700941
942class ReservationAddForm(forms.ModelForm):
943 slice = forms.ModelChoiceField(queryset=Slice.objects.all(), widget=forms.Select(attrs={"onChange":"document.getElementById('id_refresh').value=1; submit()"}))
944 refresh = forms.CharField(widget=forms.HiddenInput())
945
946 class Media:
947 css = {'all': ('planetstack.css',)} # .field-refresh { display: none; }
948
949 def clean_slice(self):
950 slice = self.cleaned_data.get("slice")
951 x = ServiceResource.objects.filter(serviceClass = slice.serviceClass, calendarReservable=True)
952 if len(x) == 0:
953 raise forms.ValidationError("The slice you selected does not have a service class that allows reservations")
954 return slice
955
956 class Meta:
957 model = Reservation
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400958 widgets = {
959 'slice' : LinkedSelect
960 }
961
Scott Baker133c9212013-05-17 09:09:11 -0700962
963class ReservationAddRefreshForm(ReservationAddForm):
964 """ This form is displayed when the Reservation Form receives an update
965 from the Slice dropdown onChange handler. It doesn't validate the
966 data and doesn't save the data. This will cause the form to be
967 redrawn.
968 """
969
Scott Baker8737e5f2013-05-17 09:35:32 -0700970 """ don't validate anything other than slice """
971 dont_validate_fields = ("startTime", "duration")
972
Scott Baker133c9212013-05-17 09:09:11 -0700973 def full_clean(self):
974 result = super(ReservationAddForm, self).full_clean()
Scott Baker8737e5f2013-05-17 09:35:32 -0700975
976 for fieldname in self.dont_validate_fields:
977 if fieldname in self._errors:
978 del self._errors[fieldname]
979
Scott Baker133c9212013-05-17 09:09:11 -0700980 return result
981
982 """ don't save anything """
983 def is_valid(self):
984 return False
985
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500986class ReservationAdmin(PlanetStackBaseAdmin):
987 fieldList = ['slice', 'startTime', 'duration']
988 fieldsets = [('Reservation Details', {'fields': fieldList, 'classes': ['suit-tab suit-tab-general']})]
Scott Baker133c9212013-05-17 09:09:11 -0700989 list_display = ('startTime', 'duration')
Scott Baker133c9212013-05-17 09:09:11 -0700990 form = ReservationAddForm
991
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400992 suit_form_tabs = (('general','Reservation Details'), ('reservedresources','Reserved Resources'))
993
994 inlines = [ReservedResourceInline]
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500995 user_readonly_inlines = [ReservedResourceROInline]
996 user_readonly_fields = fieldList
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400997
Scott Baker133c9212013-05-17 09:09:11 -0700998 def add_view(self, request, form_url='', extra_context=None):
Scott Bakeracd45142013-05-19 16:19:16 -0700999 timezone.activate(request.user.timezone)
Scott Baker133c9212013-05-17 09:09:11 -07001000 request._refresh = False
1001 request._slice = None
1002 if request.method == 'POST':
Scott Baker8737e5f2013-05-17 09:35:32 -07001003 # "refresh" will be set to "1" if the form was submitted due to
1004 # a change in the Slice dropdown.
Scott Baker133c9212013-05-17 09:09:11 -07001005 if request.POST.get("refresh","1") == "1":
1006 request._refresh = True
1007 request.POST["refresh"] = "0"
Scott Baker8737e5f2013-05-17 09:35:32 -07001008
1009 # Keep track of the slice that was selected, so the
1010 # reservedResource inline can filter items for the slice.
Scott Baker133c9212013-05-17 09:09:11 -07001011 request._slice = request.POST.get("slice",None)
1012 if (request._slice is not None):
1013 request._slice = Slice.objects.get(id=request._slice)
1014
1015 result = super(ReservationAdmin, self).add_view(request, form_url, extra_context)
1016 return result
1017
Scott Bakeracd45142013-05-19 16:19:16 -07001018 def changelist_view(self, request, extra_context = None):
1019 timezone.activate(request.user.timezone)
1020 return super(ReservationAdmin, self).changelist_view(request, extra_context)
1021
Scott Baker133c9212013-05-17 09:09:11 -07001022 def get_form(self, request, obj=None, **kwargs):
Siobhan Tullyd3515752013-06-21 16:34:53 -04001023 request._obj_ = obj
1024 if obj is not None:
1025 # For changes, set request._slice to the slice already set in the
1026 # object.
1027 request._slice = obj.slice
1028 self.form = ReservationChangeForm
1029 else:
1030 if getattr(request, "_refresh", False):
1031 self.form = ReservationAddRefreshForm
1032 else:
1033 self.form = ReservationAddForm
1034 return super(ReservationAdmin, self).get_form(request, obj, **kwargs)
1035
Scott Baker133c9212013-05-17 09:09:11 -07001036 def get_readonly_fields(self, request, obj=None):
Siobhan Tullyd3515752013-06-21 16:34:53 -04001037 if (obj is not None):
1038 # Prevent slice from being changed after the reservation has been
1039 # created.
1040 return ['slice']
1041 else:
Scott Baker133c9212013-05-17 09:09:11 -07001042 return []
Scott Baker3de3e372013-05-10 16:50:44 -07001043
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001044class NetworkParameterTypeAdmin(PlanetStackBaseAdmin):
Scott Baker74d8e622013-07-29 16:04:22 -07001045 list_display = ("name", )
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001046 user_readonly_fields = ['name']
1047 user_readonly_inlines = []
Scott Baker74d8e622013-07-29 16:04:22 -07001048
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001049class RouterAdmin(PlanetStackBaseAdmin):
Scott Baker74d8e622013-07-29 16:04:22 -07001050 list_display = ("name", )
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001051 user_readonly_fields = ['name']
1052 user_readonly_inlines = []
1053
1054class RouterROInline(ReadOnlyTabularInline):
1055 model = Router.networks.through
1056 extra = 0
1057 verbose_name_plural = "Routers"
1058 verbose_name = "Router"
1059 suit_classes = 'suit-tab suit-tab-routers'
1060
1061 fields = ['name', 'owner', 'permittedNetworks', 'networks']
Scott Baker74d8e622013-07-29 16:04:22 -07001062
1063class RouterInline(admin.TabularInline):
Scott Baker74d8e622013-07-29 16:04:22 -07001064 model = Router.networks.through
1065 extra = 0
1066 verbose_name_plural = "Routers"
1067 verbose_name = "Router"
Siobhan Tully2d95e482013-09-06 10:56:06 -04001068 suit_classes = 'suit-tab suit-tab-routers'
Scott Baker74d8e622013-07-29 16:04:22 -07001069
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001070class NetworkParameterROInline(ReadOnlyTabularInline):
1071 model = NetworkParameter
1072 extra = 1
1073 verbose_name_plural = "Parameters"
1074 verbose_name = "Parameter"
1075 suit_classes = 'suit-tab suit-tab-netparams'
1076 fields = ['parameter', 'value', 'content_type', 'object_id', 'content_object']
1077
Scott Baker74d8e622013-07-29 16:04:22 -07001078class NetworkParameterInline(generic.GenericTabularInline):
Scott Baker74d8e622013-07-29 16:04:22 -07001079 model = NetworkParameter
1080 extra = 1
1081 verbose_name_plural = "Parameters"
1082 verbose_name = "Parameter"
Siobhan Tully2d95e482013-09-06 10:56:06 -04001083 suit_classes = 'suit-tab suit-tab-netparams'
Scott Baker74d8e622013-07-29 16:04:22 -07001084
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001085class NetworkSliversROInline(ReadOnlyTabularInline):
1086 fields = ['network', 'sliver', 'ip', 'port_id']
1087 model = NetworkSliver
1088 extra = 0
1089 verbose_name_plural = "Slivers"
1090 verbose_name = "Sliver"
1091 suit_classes = 'suit-tab suit-tab-networkslivers'
1092
Scott Baker74d8e622013-07-29 16:04:22 -07001093class NetworkSliversInline(admin.TabularInline):
Scott Baker74d8e622013-07-29 16:04:22 -07001094 readonly_fields = ("ip", )
1095 model = NetworkSliver
1096 extra = 0
1097 verbose_name_plural = "Slivers"
1098 verbose_name = "Sliver"
Siobhan Tully2d95e482013-09-06 10:56:06 -04001099 suit_classes = 'suit-tab suit-tab-networkslivers'
Scott Baker74d8e622013-07-29 16:04:22 -07001100
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001101class NetworkSlicesROInline(ReadOnlyTabularInline):
1102 model = NetworkSlice
1103 extra = 0
1104 verbose_name_plural = "Slices"
1105 verbose_name = "Slice"
1106 suit_classes = 'suit-tab suit-tab-networkslices'
1107 fields = ['network','slice']
1108
Scott Bakerd7d2a392013-08-06 08:57:30 -07001109class NetworkSlicesInline(admin.TabularInline):
Scott Bakerd7d2a392013-08-06 08:57:30 -07001110 model = NetworkSlice
1111 extra = 0
1112 verbose_name_plural = "Slices"
1113 verbose_name = "Slice"
Siobhan Tully2d95e482013-09-06 10:56:06 -04001114 suit_classes = 'suit-tab suit-tab-networkslices'
Scott Bakerd7d2a392013-08-06 08:57:30 -07001115
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001116class NetworkAdmin(PlanetStackBaseAdmin):
Scott Baker74d8e622013-07-29 16:04:22 -07001117 list_display = ("name", "subnet", "ports", "labels")
1118 readonly_fields = ("subnet", )
Siobhan Tully2d95e482013-09-06 10:56:06 -04001119
Scott Bakerd7d2a392013-08-06 08:57:30 -07001120 inlines = [NetworkParameterInline, NetworkSliversInline, NetworkSlicesInline, RouterInline]
Scott Baker74d8e622013-07-29 16:04:22 -07001121
Siobhan Tully2d95e482013-09-06 10:56:06 -04001122 fieldsets = [
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001123 (None, {'fields': ['name','template','ports','labels','owner','guaranteedBandwidth', 'permitAllSlices','permittedSlices','network_id','router_id','subnet_id','subnet'], 'classes':['suit-tab suit-tab-general']}),]
1124
1125 user_readonly_fields = ['name','template','ports','labels','owner','guaranteedBandwidth', 'permitAllSlices','permittedSlices','network_id','router_id','subnet_id','subnet']
1126 user_readonly_inlines = [NetworkParameterROInline, NetworkSliversROInline, NetworkSlicesROInline, RouterROInline]
Siobhan Tully2d95e482013-09-06 10:56:06 -04001127
1128 suit_form_tabs =(
1129 ('general','Network Details'),
1130 ('netparams', 'Parameters'),
1131 ('networkslivers','Slivers'),
1132 ('networkslices','Slices'),
1133 ('routers','Routers'),
1134 )
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001135class NetworkTemplateAdmin(PlanetStackBaseAdmin):
Scott Baker74d8e622013-07-29 16:04:22 -07001136 list_display = ("name", "guaranteedBandwidth", "visibility")
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001137 user_readonly_fields = ["name", "guaranteedBandwidth", "visibility"]
1138 user_readonly_inlines = []
Scott Baker74d8e622013-07-29 16:04:22 -07001139
Tony Mack31c2b8f2013-04-26 20:01:42 -04001140# register a signal that caches the user's credentials when they log in
1141def cache_credentials(sender, user, request, **kwds):
1142 auth = {'username': request.POST['username'],
1143 'password': request.POST['password']}
1144 request.session['auth'] = auth
1145user_logged_in.connect(cache_credentials)
1146
Scott Baker15cddfa2013-12-09 13:45:19 -08001147def dollar_field(fieldName, short_description):
1148 def newFunc(self, obj):
1149 try:
1150 x= "$ %0.2f" % float(getattr(obj, fieldName, 0.0))
1151 except:
1152 x=getattr(obj, fieldName, 0.0)
1153 return x
1154 newFunc.short_description = short_description
1155 return newFunc
1156
1157def right_dollar_field(fieldName, short_description):
1158 def newFunc(self, obj):
1159 try:
1160 #x= '<div align=right style="width:6em">$ %0.2f</div>' % float(getattr(obj, fieldName, 0.0))
1161 x= '<div align=right>$ %0.2f</div>' % float(getattr(obj, fieldName, 0.0))
1162 except:
1163 x=getattr(obj, fieldName, 0.0)
1164 return x
1165 newFunc.short_description = short_description
1166 newFunc.allow_tags = True
1167 return newFunc
Scott Baker43105042013-12-06 23:23:36 -08001168
1169class InvoiceChargeInline(admin.TabularInline):
1170 model = Charge
Scott Baker15cddfa2013-12-09 13:45:19 -08001171 extra = 0
Scott Baker43105042013-12-06 23:23:36 -08001172 verbose_name_plural = "Charges"
1173 verbose_name = "Charge"
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001174 exclude = ['account']
Scott Baker9cb88a22013-12-09 18:56:00 -08001175 fields = ["date", "kind", "state", "object", "coreHours", "dollar_amount", "slice"]
1176 readonly_fields = ["date", "kind", "state", "object", "coreHours", "dollar_amount", "slice"]
1177 can_delete = False
1178 max_num = 0
1179
1180 dollar_amount = right_dollar_field("amount", "Amount")
Scott Baker43105042013-12-06 23:23:36 -08001181
1182class InvoiceAdmin(admin.ModelAdmin):
1183 list_display = ("date", "account")
1184
1185 inlines = [InvoiceChargeInline]
1186
Scott Baker9cb88a22013-12-09 18:56:00 -08001187 fields = ["date", "account", "dollar_amount"]
1188 readonly_fields = ["date", "account", "dollar_amount"]
1189
1190 dollar_amount = dollar_field("amount", "Amount")
Scott Baker43105042013-12-06 23:23:36 -08001191
Scott Baker15cddfa2013-12-09 13:45:19 -08001192class InvoiceInline(admin.TabularInline):
1193 model = Invoice
1194 extra = 0
1195 verbose_name_plural = "Invoices"
1196 verbose_name = "Invoice"
Scott Baker9cb88a22013-12-09 18:56:00 -08001197 fields = ["date", "dollar_amount", "invoiceLink"]
1198 readonly_fields = ["date", "dollar_amount", "invoiceLink"]
Scott Baker15cddfa2013-12-09 13:45:19 -08001199 suit_classes = 'suit-tab suit-tab-accountinvoice'
1200 can_delete=False
1201 max_num=0
1202
1203 dollar_amount = right_dollar_field("amount", "Amount")
1204
Scott Baker9cb88a22013-12-09 18:56:00 -08001205 def invoiceLink(self, obj):
1206 reverse_path = "admin:core_invoice_change"
1207 url = reverse(reverse_path, args =(obj.id,))
1208 return "<a href='%s'>%s</a>" % (url, "details")
1209 invoiceLink.allow_tags = True
1210 invoiceLink.short_description = "Details"
1211
Scott Baker43105042013-12-06 23:23:36 -08001212class PendingChargeInline(admin.TabularInline):
1213 model = Charge
Scott Baker15cddfa2013-12-09 13:45:19 -08001214 extra = 0
Scott Baker43105042013-12-06 23:23:36 -08001215 verbose_name_plural = "Charges"
1216 verbose_name = "Charge"
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001217 exclude = ["invoice"]
Scott Baker15cddfa2013-12-09 13:45:19 -08001218 fields = ["date", "kind", "state", "object", "coreHours", "dollar_amount", "slice"]
1219 readonly_fields = ["date", "kind", "state", "object", "coreHours", "dollar_amount", "slice"]
Scott Baker43105042013-12-06 23:23:36 -08001220 suit_classes = 'suit-tab suit-tab-accountpendingcharges'
Scott Baker15cddfa2013-12-09 13:45:19 -08001221 can_delete=False
1222 max_num=0
Scott Baker43105042013-12-06 23:23:36 -08001223
1224 def queryset(self, request):
1225 qs = super(PendingChargeInline, self).queryset(request)
1226 qs = qs.filter(state="pending")
1227 return qs
1228
Scott Baker15cddfa2013-12-09 13:45:19 -08001229 dollar_amount = right_dollar_field("amount", "Amount")
1230
Scott Baker43105042013-12-06 23:23:36 -08001231class PaymentInline(admin.TabularInline):
1232 model=Payment
1233 extra = 1
1234 verbose_name_plural = "Payments"
1235 verbose_name = "Payment"
Scott Baker15cddfa2013-12-09 13:45:19 -08001236 fields = ["date", "dollar_amount"]
1237 readonly_fields = ["date", "dollar_amount"]
Scott Baker43105042013-12-06 23:23:36 -08001238 suit_classes = 'suit-tab suit-tab-accountpayments'
Scott Baker15cddfa2013-12-09 13:45:19 -08001239 can_delete=False
1240 max_num=0
1241
1242 dollar_amount = right_dollar_field("amount", "Amount")
1243
Scott Baker43105042013-12-06 23:23:36 -08001244class AccountAdmin(admin.ModelAdmin):
1245 list_display = ("site", "balance_due")
1246
1247 inlines = [InvoiceInline, PaymentInline, PendingChargeInline]
1248
1249 fieldsets = [
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001250 (None, {'fields': ['site', 'dollar_balance_due', 'dollar_total_invoices', 'dollar_total_payments'],'classes':['suit-tab suit-tab-general']}),]
Scott Baker43105042013-12-06 23:23:36 -08001251
Scott Baker15cddfa2013-12-09 13:45:19 -08001252 readonly_fields = ['site', 'dollar_balance_due', 'dollar_total_invoices', 'dollar_total_payments']
Scott Baker43105042013-12-06 23:23:36 -08001253
1254 suit_form_tabs =(
1255 ('general','Account Details'),
1256 ('accountinvoice', 'Invoices'),
1257 ('accountpayments', 'Payments'),
1258 ('accountpendingcharges','Pending Charges'),
1259 )
1260
Scott Baker15cddfa2013-12-09 13:45:19 -08001261 dollar_balance_due = dollar_field("balance_due", "Balance Due")
1262 dollar_total_invoices = dollar_field("total_invoices", "Total Invoices")
1263 dollar_total_payments = dollar_field("total_payments", "Total Payments")
1264
Siobhan Tullyce652d02013-10-08 21:52:35 -04001265
Siobhan Tully53437282013-04-26 19:30:27 -04001266# Now register the new UserAdmin...
Siobhan Tully30fd4292013-05-10 08:59:56 -04001267admin.site.register(User, UserAdmin)
Siobhan Tully53437282013-04-26 19:30:27 -04001268# ... and, since we're not using Django's builtin permissions,
1269# unregister the Group model from admin.
Siobhan Tullyce652d02013-10-08 21:52:35 -04001270#admin.site.unregister(Group)
Siobhan Tully53437282013-04-26 19:30:27 -04001271
Siobhan Tullybf1153a2013-05-27 20:53:48 -04001272#Do not show django evolution in the admin interface
1273from django_evolution.models import Version, Evolution
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001274#admin.site.unregister(Version)
1275#admin.site.unregister(Evolution)
Siobhan Tullybf1153a2013-05-27 20:53:48 -04001276
1277
1278# When debugging it is often easier to see all the classes, but for regular use
1279# only the top-levels should be displayed
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001280showAll = False
Scott Baker43105042013-12-06 23:23:36 -08001281
Siobhan Tullybf1153a2013-05-27 20:53:48 -04001282admin.site.register(Deployment, DeploymentAdmin)
Siobhan Tully4bc09f22013-04-10 21:15:21 -04001283admin.site.register(Site, SiteAdmin)
Siobhan Tully4bc09f22013-04-10 21:15:21 -04001284admin.site.register(Slice, SliceAdmin)
Siobhan Tullyce652d02013-10-08 21:52:35 -04001285admin.site.register(Service, ServiceAdmin)
smbakera3cf70c2013-06-27 02:01:41 -07001286admin.site.register(Reservation, ReservationAdmin)
Scott Baker74d8e622013-07-29 16:04:22 -07001287admin.site.register(Network, NetworkAdmin)
1288admin.site.register(Router, RouterAdmin)
Scott Baker74d8e622013-07-29 16:04:22 -07001289admin.site.register(NetworkTemplate, NetworkTemplateAdmin)
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001290admin.site.register(Account, AccountAdmin)
1291admin.site.register(Invoice, InvoiceAdmin)
Siobhan Tullybf1153a2013-05-27 20:53:48 -04001292
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001293if True:
1294 admin.site.register(NetworkParameterType, NetworkParameterTypeAdmin)
1295 admin.site.register(ServiceClass, ServiceClassAdmin)
Siobhan Tullybfd11dc2013-09-03 12:59:24 -04001296 #admin.site.register(PlanetStack)
Siobhan Tullyd3515752013-06-21 16:34:53 -04001297 admin.site.register(Tag, TagAdmin)
Siobhan Tullyce652d02013-10-08 21:52:35 -04001298 admin.site.register(DeploymentRole)
1299 admin.site.register(SiteRole)
1300 admin.site.register(SliceRole)
1301 admin.site.register(PlanetStackRole)
Siobhan Tullybf1153a2013-05-27 20:53:48 -04001302 admin.site.register(Node, NodeAdmin)
Siobhan Tullybfd11dc2013-09-03 12:59:24 -04001303 #admin.site.register(SlicePrivilege, SlicePrivilegeAdmin)
1304 #admin.site.register(SitePrivilege, SitePrivilegeAdmin)
Siobhan Tullybf1153a2013-05-27 20:53:48 -04001305 admin.site.register(Sliver, SliverAdmin)
Siobhan Tullybf1153a2013-05-27 20:53:48 -04001306 admin.site.register(Image, ImageAdmin)
Tony Mack7130ac32013-03-22 21:58:00 -04001307