blob: 44307c392f4f9a76c82799dbd62bc392f48e1de1 [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):
Scott Baker86568322014-01-12 16:53:31 -080074 def __init__(self, *args, **kwargs):
75 super(PlStackTabularInline, self).__init__(*args, **kwargs)
76
77 # InlineModelAdmin as no get_fields() method, so in order to add
78 # the selflink field, we override __init__ to modify self.fields and
79 # self.readonly_fields.
80
81 #if (self.fields is None):
82 # self.fields = self.model._meta.get_all_field_names()
83
84 if (self.fields is not None):
85 self.fields = tuple(self.fields) + ("selflink", )
86
87 if self.readonly_fields is None:
88 self.readonly_fields = ()
89
90 self.readonly_fields = tuple(self.readonly_fields) + ("selflink", )
91
92 def selflink(self, obj):
93 if obj.id:
94 reverse_path = "admin:%s_change" % (self.model._meta.db_table)
95 url = reverse(reverse_path, args =(obj.id,))
96 return "<a href='%s'>Details</a>" % str(url)
97 else:
98 return "Not present"
99
100 selflink.allow_tags = True
101 selflink.short_description = "Details"
Siobhan Tullyd3515752013-06-21 16:34:53 -0400102
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500103class ReadOnlyTabularInline(PlStackTabularInline):
104 can_delete = False
105
106 def get_readonly_fields(self, request, obj=None):
107 return self.fields
108
109 def has_add_permission(self, request):
110 return False
111
112class ReservationROInline(ReadOnlyTabularInline):
113 model = Reservation
114 extra = 0
115 suit_classes = 'suit-tab suit-tab-reservations'
116 fields = ['startTime','slice','duration']
117
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400118class ReservationInline(PlStackTabularInline):
119 model = Reservation
120 extra = 0
121 suit_classes = 'suit-tab suit-tab-reservations'
122
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500123class TagROInline(generic.GenericTabularInline):
124 model = Tag
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400125 extra = 0
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500126 suit_classes = 'suit-tab suit-tab-tags'
127 can_delete = False
128 fields = ['service', 'name', 'value']
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400129
130 def get_readonly_fields(self, request, obj=None):
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500131 return self.fields
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400132
133 def has_add_permission(self, request):
134 return False
135
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500136
Siobhan Tullyde5450d2013-06-21 11:35:33 -0400137class TagInline(generic.GenericTabularInline):
138 model = Tag
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400139 extra = 0
140 suit_classes = 'suit-tab suit-tab-tags'
Siobhan Tullyde5450d2013-06-21 11:35:33 -0400141
Scott Baker74d8e622013-07-29 16:04:22 -0700142class NetworkLookerUpper:
Siobhan Tully2c780ad2013-09-06 11:22:40 -0400143 """ This is a callable that looks up a network name in a sliver and returns
144 the ip address for that network.
145 """
146
147 def __init__(self, name):
148 self.short_description = name
149 self.__name__ = name
150 self.network_name = name
151
152 def __call__(self, obj):
153 if obj is not None:
154 for nbs in obj.networksliver_set.all():
155 if (nbs.network.name == self.network_name):
156 return nbs.ip
Scott Baker74d8e622013-07-29 16:04:22 -0700157 return ""
158
159 def __str__(self):
160 return self.network_name
161
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500162class SliverROInline(ReadOnlyTabularInline):
163 model = Sliver
164 fields = ['ip', 'instance_name', 'slice', 'numberCores', 'image', 'node', 'deploymentNetwork']
165 suit_classes = 'suit-tab suit-tab-slivers'
166
Siobhan Tullyd3515752013-06-21 16:34:53 -0400167class SliverInline(PlStackTabularInline):
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400168 model = Sliver
Tony Mackb0d97422013-06-10 09:57:45 -0400169 fields = ['ip', 'instance_name', 'slice', 'numberCores', 'image', 'node', 'deploymentNetwork']
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400170 extra = 0
Tony Mack3777b012013-05-07 21:38:06 -0400171 readonly_fields = ['ip', 'instance_name']
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400172 suit_classes = 'suit-tab suit-tab-slivers'
Scott Baker74d8e622013-07-29 16:04:22 -0700173
Siobhan Tully2d95e482013-09-06 10:56:06 -0400174# Note this is breaking in the admin.py when trying to use an inline to add a node/image
175# def _declared_fieldsets(self):
176# # Return None so django will call get_fieldsets and we can insert our
177# # dynamic fields
178# return None
179#
180# def get_readonly_fields(self, request, obj=None):
181# readonly_fields = super(SliverInline, self).get_readonly_fields(request, obj)
182#
183# # Lookup the networks that are bound to the slivers, and add those
184# # network names to the list of readonly fields.
185#
186# for sliver in obj.slivers.all():
187# for nbs in sliver.networksliver_set.all():
188# if nbs.ip:
189# network_name = nbs.network.name
190# if network_name not in [str(x) for x in readonly_fields]:
191# readonly_fields.append(NetworkLookerUpper(network_name))
192#
193# return readonly_fields
194#
195# def get_fieldsets(self, request, obj=None):
196# form = self.get_formset(request, obj).form
197# # fields = the read/write files + the read-only fields
198# fields = self.fields
199# for fieldName in self.get_readonly_fields(request,obj):
200# if not fieldName in fields:
201# fields.append(fieldName)
202#
203# return [(None, {'fields': fields})]
Scott Baker74d8e622013-07-29 16:04:22 -0700204
Tony Mackc2835a92013-05-28 09:18:49 -0400205
Siobhan Tully567e3e62013-06-21 18:03:16 -0400206
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500207class SiteROInline(ReadOnlyTabularInline):
208 model = Site
209 extra = 0
210 fields = ['name', 'login_base', 'site_url', 'enabled']
211 suit_classes = 'suit-tab suit-tab-sites'
212
Siobhan Tullyd3515752013-06-21 16:34:53 -0400213class SiteInline(PlStackTabularInline):
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400214 model = Site
215 extra = 0
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400216 suit_classes = 'suit-tab suit-tab-sites'
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400217
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500218class UserROInline(ReadOnlyTabularInline):
219 model = User
220 fields = ['email', 'firstname', 'lastname']
221 extra = 0
222 suit_classes = 'suit-tab suit-tab-users'
223
Siobhan Tullyd3515752013-06-21 16:34:53 -0400224class UserInline(PlStackTabularInline):
Siobhan Tully30fd4292013-05-10 08:59:56 -0400225 model = User
Siobhan Tully47ae1b52013-05-10 15:53:14 -0400226 fields = ['email', 'firstname', 'lastname']
Siobhan Tully30fd4292013-05-10 08:59:56 -0400227 extra = 0
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400228 suit_classes = 'suit-tab suit-tab-users'
Siobhan Tully30fd4292013-05-10 08:59:56 -0400229
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500230class SliceROInline(ReadOnlyTabularInline):
231 model = Slice
232 suit_classes = 'suit-tab suit-tab-slices'
233 fields = ['name','site', 'serviceClass', 'service']
234
Siobhan Tullyd3515752013-06-21 16:34:53 -0400235class SliceInline(PlStackTabularInline):
Tony Mack00d361f2013-04-28 10:28:42 -0400236 model = Slice
Siobhan Tullyce652d02013-10-08 21:52:35 -0400237 fields = ['name','site', 'serviceClass', 'service']
Tony Mack00d361f2013-04-28 10:28:42 -0400238 extra = 0
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400239 suit_classes = 'suit-tab suit-tab-slices'
240
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500241class NodeROInline(ReadOnlyTabularInline):
242 model = Node
243 extra = 0
244 suit_classes = 'suit-tab suit-tab-nodes'
245 fields = ['name','deployment']
Tony Mack00d361f2013-04-28 10:28:42 -0400246
Siobhan Tullyd3515752013-06-21 16:34:53 -0400247class NodeInline(PlStackTabularInline):
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400248 model = Node
249 extra = 0
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400250 suit_classes = 'suit-tab suit-tab-nodes'
251
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500252class DeploymentPrivilegeROInline(ReadOnlyTabularInline):
253 model = DeploymentPrivilege
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400254 extra = 0
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500255 suit_classes = 'suit-tab suit-tab-deploymentprivileges'
256 fields = ['user','role']
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400257
258class DeploymentPrivilegeInline(PlStackTabularInline):
259 model = DeploymentPrivilege
260 extra = 0
261 suit_classes = 'suit-tab suit-tab-deploymentprivileges'
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400262
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500263#CLEANUP DOUBLE SitePrivilegeInline
264class SitePrivilegeROInline(ReadOnlyTabularInline):
265 model = SitePrivilege
266 extra = 0
267 suit_classes = 'suit-tab suit-tab-siteprivileges'
268 fields = ['user','site', 'role']
269
Siobhan Tullyd3515752013-06-21 16:34:53 -0400270class SitePrivilegeInline(PlStackTabularInline):
Siobhan Tullyaa1bcd52013-05-10 12:43:09 -0400271 model = SitePrivilege
272 extra = 0
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400273 suit_classes = 'suit-tab suit-tab-siteprivileges'
Siobhan Tullyaa1bcd52013-05-10 12:43:09 -0400274
Tony Mackc2835a92013-05-28 09:18:49 -0400275 def formfield_for_foreignkey(self, db_field, request, **kwargs):
276 if db_field.name == 'site':
277 if not request.user.is_admin:
278 # only show sites where user is an admin or pi
279 roles = Role.objects.filter(role_type__in=['admin', 'pi'])
280 site_privileges = SitePrivilege.objects.filter(user=request.user).filter(role__in=roles)
281 login_bases = [site_privilege.site.login_base for site_privilege in site_privileges]
282 sites = Site.objects.filter(login_base__in=login_bases)
283 kwargs['queryset'] = sites
284
285 if db_field.name == 'user':
286 if not request.user.is_admin:
287 # only show users from sites where caller has admin or pi role
288 roles = Role.objects.filter(role_type__in=['admin', 'pi'])
289 site_privileges = SitePrivilege.objects.filter(user=request.user).filter(role__in=roles)
290 sites = [site_privilege.site for site_privilege in site_privileges]
291 site_privileges = SitePrivilege.objects.filter(site__in=sites)
292 emails = [site_privilege.user.email for site_privilege in site_privileges]
293 users = User.objects.filter(email__in=emails)
294 kwargs['queryset'] = users
295 return super(SitePrivilegeInline, self).formfield_for_foreignkey(db_field, request, **kwargs)
296
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400297class SitePrivilegeInline(PlStackTabularInline):
298 model = SitePrivilege
299 suit_classes = 'suit-tab suit-tab-siteprivileges'
Siobhan Tullyaa1bcd52013-05-10 12:43:09 -0400300 extra = 0
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400301 fields = ('user', 'site','role')
302
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500303class SlicePrivilegeROInline(ReadOnlyTabularInline):
304 model = SlicePrivilege
305 extra = 0
306 suit_classes = 'suit-tab suit-tab-sliceprivileges'
307 fields = ['user', 'slice', 'role']
308
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400309class SlicePrivilegeInline(PlStackTabularInline):
310 model = SlicePrivilege
311 suit_classes = 'suit-tab suit-tab-sliceprivileges'
312 extra = 0
313 fields = ('user', 'slice','role')
Siobhan Tullyaa1bcd52013-05-10 12:43:09 -0400314
Tony Mackc2835a92013-05-28 09:18:49 -0400315 def formfield_for_foreignkey(self, db_field, request, **kwargs):
316 if db_field.name == 'slice':
317 if not request.user.is_admin:
318 # only show slices at sites where caller has admin or pi role
319 roles = Role.objects.filter(role_type__in=['admin', 'pi'])
320 site_privileges = SitePrivilege.objects.filter(user=request.user).filter(role__in=roles)
321 sites = [site_privilege.site for site_privilege in site_privileges]
322 slices = Slice.objects.filter(site__in=sites)
323 kwargs['queryset'] = slices
324 if db_field.name == 'user':
325 if not request.user.is_admin:
326 # only show users from sites where caller has admin or pi role
327 roles = Role.objects.filter(role_type__in=['admin', 'pi'])
328 site_privileges = SitePrivilege.objects.filter(user=request.user).filter(role__in=roles)
329 sites = [site_privilege.site for site_privilege in site_privileges]
330 site_privileges = SitePrivilege.objects.filter(site__in=sites)
331 emails = [site_privilege.user.email for site_privilege in site_privileges]
332 users = User.objects.filter(email__in=emails)
333 kwargs['queryset'] = list(users)
334
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400335 return super(SlicePrivilegeInline, self).formfield_for_foreignkey(db_field, request, **kwargs)
Tony Mackc2835a92013-05-28 09:18:49 -0400336
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500337class SliceNetworkROInline(ReadOnlyTabularInline):
338 model = Network.slices.through
339 extra = 0
340 verbose_name = "Network Connection"
341 verbose_name_plural = "Network Connections"
342 suit_classes = 'suit-tab suit-tab-slicenetworks'
343 fields = ['network']
344
Scott Bakera0015eb2013-08-14 17:28:14 -0700345class SliceNetworkInline(PlStackTabularInline):
Scott Baker74d8e622013-07-29 16:04:22 -0700346 model = Network.slices.through
347 extra = 0
348 verbose_name = "Network Connection"
349 verbose_name_plural = "Network Connections"
Siobhan Tully2d95e482013-09-06 10:56:06 -0400350 suit_classes = 'suit-tab suit-tab-slicenetworks'
Scott Baker74d8e622013-07-29 16:04:22 -0700351
Tony Mack5e71a662013-05-03 23:30:41 -0400352class PlainTextWidget(forms.HiddenInput):
353 input_type = 'hidden'
354
355 def render(self, name, value, attrs=None):
356 if value is None:
357 value = ''
Tony Mack1d6b85f2013-05-07 18:49:14 -0400358 return mark_safe(str(value) + super(PlainTextWidget, self).render(name, value, attrs))
Tony Mack9bcbe4f2013-04-29 08:13:27 -0400359
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500360class PlanetStackBaseAdmin(ReadOnlyAwareAdmin):
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400361 save_on_top = False
362
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400363class SliceRoleAdmin(PlanetStackBaseAdmin):
364 model = SliceRole
365 pass
366
367class SiteRoleAdmin(PlanetStackBaseAdmin):
368 model = SiteRole
369 pass
370
Siobhan Tullybf1153a2013-05-27 20:53:48 -0400371class DeploymentAdminForm(forms.ModelForm):
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400372 sites = forms.ModelMultipleChoiceField(
373 queryset=Site.objects.all(),
374 required=False,
375 widget=FilteredSelectMultiple(
376 verbose_name=('Sites'), is_stacked=False
377 )
378 )
379 class Meta:
Siobhan Tullybf1153a2013-05-27 20:53:48 -0400380 model = Deployment
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400381
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500382class SiteAssocInline(PlStackTabularInline):
383 model = Site.deployments.through
384 extra = 0
385 suit_classes = 'suit-tab suit-tab-sites'
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400386
Siobhan Tullybf1153a2013-05-27 20:53:48 -0400387class DeploymentAdmin(PlanetStackBaseAdmin):
388 form = DeploymentAdminForm
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500389 model = Deployment
390 fieldList = ['name','sites']
391 fieldsets = [(None, {'fields': fieldList, 'classes':['suit-tab suit-tab-sites']})]
Siobhan Tully2d95e482013-09-06 10:56:06 -0400392 inlines = [DeploymentPrivilegeInline,NodeInline,TagInline]
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500393
394 user_readonly_inlines = [DeploymentPrivilegeROInline,NodeROInline,TagROInline]
395 user_readonly_fields = ['name']
396
397 suit_form_tabs =(('sites','Deployment Details'),('nodes','Nodes'),('deploymentprivileges','Privileges'),('tags','Tags'))
398
399class ServiceAttrAsTabROInline(ReadOnlyTabularInline):
400 model = ServiceAttribute
401 fields = ['name','value']
402 extra = 0
403 suit_classes = 'suit-tab suit-tab-serviceattrs'
Tony Mack5cd13202013-05-01 21:48:38 -0400404
Siobhan Tullyce652d02013-10-08 21:52:35 -0400405class ServiceAttrAsTabInline(PlStackTabularInline):
406 model = ServiceAttribute
407 fields = ['name','value']
408 extra = 0
409 suit_classes = 'suit-tab suit-tab-serviceattrs'
410
Siobhan Tullyce652d02013-10-08 21:52:35 -0400411class ServiceAdmin(PlanetStackBaseAdmin):
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500412 list_display = ("name","description","versionNumber","enabled","published")
413 fieldList = ["name","description","versionNumber","enabled","published"]
414 fieldsets = [(None, {'fields': fieldList, 'classes':['suit-tab suit-tab-general']})]
415 inlines = [ServiceAttrAsTabInline,SliceInline]
416
417 user_readonly_fields = fieldList
418 user_readonly_inlines = [ServiceAttrAsTabROInline,SliceROInline]
419
420 suit_form_tabs =(('general', 'Service Details'),
421 ('slices','Slices'),
422 ('serviceattrs','Additional Attributes'),
423 )
Siobhan Tullyce652d02013-10-08 21:52:35 -0400424
Tony Mack0553f282013-06-10 22:54:50 -0400425class SiteAdmin(PlanetStackBaseAdmin):
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500426 fieldList = ['name', 'site_url', 'enabled', 'is_public', 'login_base', 'accountLink','location']
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400427 fieldsets = [
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500428 (None, {'fields': fieldList, 'classes':['suit-tab suit-tab-general']}),
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400429 ('Deployment Networks', {'fields': ['deployments'], 'classes':['suit-tab suit-tab-deployments']}),
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400430 ]
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400431 suit_form_tabs =(('general', 'Site Details'),
432 ('users','Users'),
Siobhan Tully2d95e482013-09-06 10:56:06 -0400433 ('siteprivileges','Privileges'),
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400434 ('deployments','Deployments'),
435 ('slices','Slices'),
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500436 ('nodes','Nodes'),
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400437 ('tags','Tags'),
438 )
Scott Baker545db2a2013-12-09 18:44:43 -0800439 readonly_fields = ['accountLink']
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500440
441 user_readonly_fields = ['name', 'deployments','site_url', 'enabled', 'is_public', 'login_base', 'accountLink']
442 user_readonly_inlines = [SliceROInline,UserROInline,TagROInline, NodeROInline, SitePrivilegeROInline]
443
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400444 list_display = ('name', 'login_base','site_url', 'enabled')
445 filter_horizontal = ('deployments',)
Siobhan Tully2d95e482013-09-06 10:56:06 -0400446 inlines = [SliceInline,UserInline,TagInline, NodeInline, SitePrivilegeInline]
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400447 search_fields = ['name']
448
Tony Mack04062832013-05-10 08:22:44 -0400449 def queryset(self, request):
450 # admins can see all keys. Users can only see sites they belong to.
451 qs = super(SiteAdmin, self).queryset(request)
452 if not request.user.is_admin:
453 valid_sites = [request.user.site.login_base]
454 roles = request.user.get_roles()
455 for tenant_list in roles.values():
456 valid_sites.extend(tenant_list)
457 qs = qs.filter(login_base__in=valid_sites)
458 return qs
459
Tony Mack5cd13202013-05-01 21:48:38 -0400460 def get_formsets(self, request, obj=None):
461 for inline in self.get_inline_instances(request, obj):
462 # hide MyInline in the add view
463 if obj is None:
464 continue
Tony Mack2bd5b412013-06-11 21:05:06 -0400465 if isinstance(inline, SliceInline):
466 inline.model.caller = request.user
467 yield inline.get_formset(request, obj)
468
469 def get_formsets(self, request, obj=None):
470 for inline in self.get_inline_instances(request, obj):
471 # hide MyInline in the add view
472 if obj is None:
473 continue
474 if isinstance(inline, SliverInline):
475 inline.model.caller = request.user
Tony Mack5cd13202013-05-01 21:48:38 -0400476 yield inline.get_formset(request, obj)
477
Scott Baker545db2a2013-12-09 18:44:43 -0800478 def accountLink(self, obj):
479 link_obj = obj.accounts.all()
480 if link_obj:
481 reverse_path = "admin:core_account_change"
482 url = reverse(reverse_path, args =(link_obj[0].id,))
483 return "<a href='%s'>%s</a>" % (url, "view billing details")
484 else:
485 return "no billing data for this site"
486 accountLink.allow_tags = True
487 accountLink.short_description = "Billing"
488
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500489
Tony Mack9bcbe4f2013-04-29 08:13:27 -0400490class SitePrivilegeAdmin(PlanetStackBaseAdmin):
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500491 fieldList = ['user', 'site', 'role']
Tony Mack00d361f2013-04-28 10:28:42 -0400492 fieldsets = [
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500493 (None, {'fields': fieldList, 'classes':['collapse']})
Tony Mack00d361f2013-04-28 10:28:42 -0400494 ]
495 list_display = ('user', 'site', 'role')
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500496 user_readonly_fields = fieldList
497 user_readonly_inlines = []
Tony Mack00d361f2013-04-28 10:28:42 -0400498
Tony Mackc2835a92013-05-28 09:18:49 -0400499 def formfield_for_foreignkey(self, db_field, request, **kwargs):
500 if db_field.name == 'site':
501 if not request.user.is_admin:
502 # only show sites where user is an admin or pi
503 sites = set()
504 for site_privilege in SitePrivilege.objects.filer(user=request.user):
505 if site_privilege.role.role_type in ['admin', 'pi']:
506 sites.add(site_privilege.site)
507 kwargs['queryset'] = Site.objects.filter(site__in=list(sites))
508
509 if db_field.name == 'user':
510 if not request.user.is_admin:
511 # only show users from sites where caller has admin or pi role
512 roles = Role.objects.filter(role_type__in=['admin', 'pi'])
513 site_privileges = SitePrivilege.objects.filter(user=request.user).filter(role__in=roles)
514 sites = [site_privilege.site for site_privilege in site_privileges]
515 site_privileges = SitePrivilege.objects.filter(site__in=sites)
516 emails = [site_privilege.user.email for site_privilege in site_privileges]
517 users = User.objects.filter(email__in=emails)
518 kwargs['queryset'] = users
519
520 return super(SitePrivilegeAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)
521
Tony Mack04062832013-05-10 08:22:44 -0400522 def queryset(self, request):
523 # admins can see all privileges. Users can only see privileges at sites
Tony Mackc2835a92013-05-28 09:18:49 -0400524 # where they have the admin role or pi role.
Tony Mack04062832013-05-10 08:22:44 -0400525 qs = super(SitePrivilegeAdmin, self).queryset(request)
526 if not request.user.is_admin:
Tony Mackc2835a92013-05-28 09:18:49 -0400527 roles = Role.objects.filter(role_type__in=['admin', 'pi'])
528 site_privileges = SitePrivilege.objects.filter(user=request.user).filter(role__in=roles)
529 login_bases = [site_privilege.site.login_base for site_privilege in site_privileges]
530 sites = Site.objects.filter(login_base__in=login_bases)
531 qs = qs.filter(site__in=sites)
Tony Mack04062832013-05-10 08:22:44 -0400532 return qs
533
Siobhan Tullyce652d02013-10-08 21:52:35 -0400534class SliceForm(forms.ModelForm):
535 class Meta:
536 model = Slice
537 widgets = {
538 'service': LinkedSelect
539 }
540
Tony Mack2bd5b412013-06-11 21:05:06 -0400541class SliceAdmin(PlanetStackBaseAdmin):
Siobhan Tullyce652d02013-10-08 21:52:35 -0400542 form = SliceForm
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500543 fieldList = ['name', 'site', 'serviceClass', 'enabled','description', 'service', 'slice_url']
544 fieldsets = [('Slice Details', {'fields': fieldList, 'classes':['suit-tab suit-tab-general']}),]
Siobhan Tully30fd4292013-05-10 08:59:56 -0400545 list_display = ('name', 'site','serviceClass', 'slice_url')
Siobhan Tully2d95e482013-09-06 10:56:06 -0400546 inlines = [SlicePrivilegeInline,SliverInline, TagInline, ReservationInline,SliceNetworkInline]
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400547
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500548 user_readonly_fields = fieldList
549 user_readonly_inlines = [SlicePrivilegeROInline,SliverROInline,TagROInline, ReservationROInline, SliceNetworkROInline]
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400550
551 suit_form_tabs =(('general', 'Slice Details'),
Siobhan Tully2d95e482013-09-06 10:56:06 -0400552 ('slicenetworks','Networks'),
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400553 ('sliceprivileges','Privileges'),
554 ('slivers','Slivers'),
555 ('tags','Tags'),
556 ('reservations','Reservations'),
557 )
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400558
Tony Mackc2835a92013-05-28 09:18:49 -0400559 def formfield_for_foreignkey(self, db_field, request, **kwargs):
560 if db_field.name == 'site':
561 if not request.user.is_admin:
562 # only show sites where user is a pi or admin
563 roles = Role.objects.filter(role_type__in=['admin', 'pi'])
564 site_privileges = SitePrivilege.objects.filter(user=request.user).filter(role__in=roles)
565 login_bases = [site_privilege.site.login_base for site_privilege in site_privileges]
566 sites = Site.objects.filter(login_base__in=login_bases)
567 kwargs['queryset'] = sites
568
569 return super(SliceAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)
570
Tony Mack04062832013-05-10 08:22:44 -0400571 def queryset(self, request):
572 # admins can see all keys. Users can only see slices they belong to.
573 qs = super(SliceAdmin, self).queryset(request)
574 if not request.user.is_admin:
575 valid_slices = []
576 roles = request.user.get_roles()
577 for tenant_list in roles.values():
578 valid_slices.extend(tenant_list)
579 qs = qs.filter(name__in=valid_slices)
580 return qs
581
Tony Mack79748612013-05-01 14:52:03 -0400582 def get_formsets(self, request, obj=None):
583 for inline in self.get_inline_instances(request, obj):
584 # hide MyInline in the add view
585 if obj is None:
586 continue
Tony Mack2bd5b412013-06-11 21:05:06 -0400587 if isinstance(inline, SliverInline):
588 inline.model.caller = request.user
Tony Mack79748612013-05-01 14:52:03 -0400589 yield inline.get_formset(request, obj)
590
Tony Mackfdd4d802013-04-27 13:02:33 -0400591 def get_queryset(self, request):
592 qs = super(SliceAdmin, self).get_queryset(request)
593 if request.user.is_superuser:
594 return qs
595 # users can only see slices at their site
Tony Mack2bd5b412013-06-11 21:05:06 -0400596 return qs.filter(site=request.user.site)
597
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400598class SlicePrivilegeAdmin(PlanetStackBaseAdmin):
Tony Mack00d361f2013-04-28 10:28:42 -0400599 fieldsets = [
600 (None, {'fields': ['user', 'slice', 'role']})
601 ]
602 list_display = ('user', 'slice', 'role')
Tony Mack00d361f2013-04-28 10:28:42 -0400603
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500604 user_readonly_fields = ['user', 'slice', 'role']
605 user_readonly_inlines = []
606
Tony Mackc2835a92013-05-28 09:18:49 -0400607 def formfield_for_foreignkey(self, db_field, request, **kwargs):
608 if db_field.name == 'slice':
609 if not request.user.is_admin:
610 # only show slices at sites where caller has admin or pi role
611 roles = Role.objects.filter(role_type__in=['admin', 'pi'])
612 site_privileges = SitePrivilege.objects.filter(user=request.user).filter(role__in=roles)
613 sites = [site_privilege.site for site_privilege in site_privileges]
614 slices = Slice.objects.filter(site__in=sites)
615 kwargs['queryset'] = slices
616
617 if db_field.name == 'user':
618 if not request.user.is_admin:
619 # only show users from sites where caller has admin or pi role
620 roles = Role.objects.filter(role_type__in=['admin', 'pi'])
621 site_privileges = SitePrivilege.objects.filter(user=request.user).filter(role__in=roles)
622 sites = [site_privilege.site for site_privilege in site_privileges]
623 site_privileges = SitePrivilege.objects.filter(site__in=sites)
624 emails = [site_privilege.user.email for site_privilege in site_privileges]
625 users = User.objects.filter(email__in=emails)
626 kwargs['queryset'] = users
627
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400628 return super(SlicePrivilegeAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)
Tony Mackc2835a92013-05-28 09:18:49 -0400629
Tony Mack04062832013-05-10 08:22:44 -0400630 def queryset(self, request):
631 # admins can see all memberships. Users can only see memberships of
632 # slices where they have the admin role.
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400633 qs = super(SlicePrivilegeAdmin, self).queryset(request)
Tony Mack04062832013-05-10 08:22:44 -0400634 if not request.user.is_admin:
Tony Mackc2835a92013-05-28 09:18:49 -0400635 roles = Role.objects.filter(role_type__in=['admin', 'pi'])
636 site_privileges = SitePrivilege.objects.filter(user=request.user).filter(role__in=roles)
637 login_bases = [site_privilege.site.login_base for site_privilege in site_privileges]
638 sites = Site.objects.filter(login_base__in=login_bases)
639 slices = Slice.objects.filter(site__in=sites)
640 qs = qs.filter(slice__in=slices)
Tony Mack04062832013-05-10 08:22:44 -0400641 return qs
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400642
Tony Mack9bcbe4f2013-04-29 08:13:27 -0400643 def save_model(self, request, obj, form, change):
Tony Mack951dab42013-05-02 19:51:45 -0400644 # update openstack connection to use this site/tenant
645 auth = request.session.get('auth', {})
646 auth['tenant'] = obj.slice.name
647 obj.os_manager = OpenStackManager(auth=auth, caller=request.user)
Tony Mack9bcbe4f2013-04-29 08:13:27 -0400648 obj.save()
649
650 def delete_model(self, request, obj):
Tony Mack951dab42013-05-02 19:51:45 -0400651 # update openstack connection to use this site/tenant
652 auth = request.session.get('auth', {})
653 auth['tenant'] = obj.slice.name
654 obj.os_manager = OpenStackManager(auth=auth, caller=request.user)
Tony Mack9bcbe4f2013-04-29 08:13:27 -0400655 obj.delete()
656
Siobhan Tully567e3e62013-06-21 18:03:16 -0400657
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400658class ImageAdmin(PlanetStackBaseAdmin):
659
660 fieldsets = [('Image Details',
661 {'fields': ['image_id', 'name', 'disk_format', 'container_format'],
662 'classes': ['suit-tab suit-tab-general']})
663 ]
664
665 suit_form_tabs =(('general','Image Details'),('slivers','Slivers'))
666
667 inlines = [SliverInline]
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500668
669 user_readonly_fields = ['image_id', 'name', 'disk_format', 'container_format']
670 user_readonly_inlines = [SliverROInline]
671
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400672class NodeForm(forms.ModelForm):
673 class Meta:
674 widgets = {
675 'site': LinkedSelect,
676 'deployment': LinkedSelect
677 }
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400678
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500679class NodeAdmin(PlanetStackBaseAdmin):
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400680 form = NodeForm
Siobhan Tullybf1153a2013-05-27 20:53:48 -0400681 list_display = ('name', 'site', 'deployment')
682 list_filter = ('deployment',)
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500683
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400684 inlines = [TagInline,SliverInline]
685 fieldsets = [('Node Details', {'fields': ['name','site','deployment'], 'classes':['suit-tab suit-tab-details']})]
686
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500687 user_readonly_fields = ['name','site','deployment']
688 user_readonly_inlines = [TagInline,SliverInline]
689
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400690 suit_form_tabs =(('details','Node Details'),('slivers','Slivers'),('tags','Tags'))
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400691
Siobhan Tully567e3e62013-06-21 18:03:16 -0400692
Tony Mackd90cdbf2013-04-16 22:48:40 -0400693class SliverForm(forms.ModelForm):
694 class Meta:
Tony Mack1d6b85f2013-05-07 18:49:14 -0400695 model = Sliver
Tony Mackd90cdbf2013-04-16 22:48:40 -0400696 ip = forms.CharField(widget=PlainTextWidget)
Tony Mack18261812013-05-02 16:39:20 -0400697 instance_name = forms.CharField(widget=PlainTextWidget)
Tony Mackd90cdbf2013-04-16 22:48:40 -0400698 widgets = {
699 'ip': PlainTextWidget(),
Tony Mack18261812013-05-02 16:39:20 -0400700 'instance_name': PlainTextWidget(),
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400701 'slice': LinkedSelect,
702 'deploymentNetwork': LinkedSelect,
703 'node': LinkedSelect,
704 'image': LinkedSelect
Siobhan Tully53437282013-04-26 19:30:27 -0400705 }
Tony Mackd90cdbf2013-04-16 22:48:40 -0400706
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500707class TagAdmin(PlanetStackBaseAdmin):
Siobhan Tullyce652d02013-10-08 21:52:35 -0400708 list_display = ['service', 'name', 'value', 'content_type', 'content_object',]
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500709 user_readonly_fields = ['service', 'name', 'value', 'content_type', 'content_object',]
710 user_readonly_inlines = []
Siobhan Tullyd3515752013-06-21 16:34:53 -0400711
Tony Mack9bcbe4f2013-04-29 08:13:27 -0400712class SliverAdmin(PlanetStackBaseAdmin):
Tony Mackd90cdbf2013-04-16 22:48:40 -0400713 form = SliverForm
Tony Mackcdec0902013-04-15 00:38:49 -0400714 fieldsets = [
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400715 ('Sliver Details', {'fields': ['slice', 'deploymentNetwork', 'node', 'ip', 'instance_name', 'numberCores', 'image', ], 'classes': ['suit-tab suit-tab-general'], })
Tony Mackcdec0902013-04-15 00:38:49 -0400716 ]
Siobhan Tully5d7dc8d2013-07-02 13:17:33 -0400717 list_display = ['ip', 'instance_name', 'slice', 'numberCores', 'image', 'node', 'deploymentNetwork']
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400718
719 suit_form_tabs =(('general', 'Sliver Details'),
720 ('tags','Tags'),
721 )
722
Siobhan Tullyde5450d2013-06-21 11:35:33 -0400723 inlines = [TagInline]
Tony Mack53106f32013-04-27 16:43:01 -0400724
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500725 user_readonly_fields = ['slice', 'deploymentNetwork', 'node', 'ip', 'instance_name', 'numberCores', 'image']
726 user_readonly_inlines = [TagROInline]
727
Tony Mackc2835a92013-05-28 09:18:49 -0400728 def formfield_for_foreignkey(self, db_field, request, **kwargs):
729 if db_field.name == 'slice':
730 if not request.user.is_admin:
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400731 slices = set([sm.slice.name for sm in SlicePrivilege.objects.filter(user=request.user)])
Tony Mackc2835a92013-05-28 09:18:49 -0400732 kwargs['queryset'] = Slice.objects.filter(name__in=list(slices))
733
734 return super(SliverAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)
735
Tony Mack04062832013-05-10 08:22:44 -0400736 def queryset(self, request):
737 # admins can see all slivers. Users can only see slivers of
738 # the slices they belong to.
739 qs = super(SliverAdmin, self).queryset(request)
740 if not request.user.is_admin:
741 tenants = []
742 roles = request.user.get_roles()
743 for tenant_list in roles.values():
744 tenants.extend(tenant_list)
745 valid_slices = Slice.objects.filter(name__in=tenants)
746 qs = qs.filter(slice__in=valid_slices)
747 return qs
748
Tony Mack1d6b85f2013-05-07 18:49:14 -0400749 def get_formsets(self, request, obj=None):
750 # make some fields read only if we are updating an existing record
751 if obj == None:
752 #self.readonly_fields = ('ip', 'instance_name')
753 self.readonly_fields = ()
754 else:
Tony Mack1e889462013-05-10 21:34:54 -0400755 self.readonly_fields = ()
756 #self.readonly_fields = ('ip', 'instance_name', 'slice', 'image', 'key')
Tony Mack1d6b85f2013-05-07 18:49:14 -0400757
758 for inline in self.get_inline_instances(request, obj):
759 # hide MyInline in the add view
760 if obj is None:
761 continue
762 # give inline object access to driver and caller
763 auth = request.session.get('auth', {})
764 auth['tenant'] = obj.name # meed to connect using slice's tenant
765 inline.model.os_manager = OpenStackManager(auth=auth, caller=request.user)
766 yield inline.get_formset(request, obj)
Tony Mack53106f32013-04-27 16:43:01 -0400767
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500768 #def save_model(self, request, obj, form, change):
769 # # update openstack connection to use this site/tenant
770 # auth = request.session.get('auth', {})
771 # auth['tenant'] = obj.slice.name
772 # obj.os_manager = OpenStackManager(auth=auth, caller=request.user)
773 # obj.creator = request.user
774 # obj.save()
Tony Mack53106f32013-04-27 16:43:01 -0400775
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500776 #def delete_model(self, request, obj):
777 # # update openstack connection to use this site/tenant
778 # auth = request.session.get('auth', {})
779 # auth['tenant'] = obj.slice.name
780 # obj.os_manager = OpenStackManager(auth=auth, caller=request.user)
781 # obj.delete()
Tony Mackcdec0902013-04-15 00:38:49 -0400782
Siobhan Tully53437282013-04-26 19:30:27 -0400783class UserCreationForm(forms.ModelForm):
784 """A form for creating new users. Includes all the required
785 fields, plus a repeated password."""
786 password1 = forms.CharField(label='Password', widget=forms.PasswordInput)
787 password2 = forms.CharField(label='Password confirmation', widget=forms.PasswordInput)
788
789 class Meta:
Siobhan Tully30fd4292013-05-10 08:59:56 -0400790 model = User
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400791 fields = ('email', 'firstname', 'lastname', 'phone', 'public_key')
Siobhan Tully53437282013-04-26 19:30:27 -0400792
793 def clean_password2(self):
794 # Check that the two password entries match
795 password1 = self.cleaned_data.get("password1")
796 password2 = self.cleaned_data.get("password2")
797 if password1 and password2 and password1 != password2:
798 raise forms.ValidationError("Passwords don't match")
799 return password2
800
801 def save(self, commit=True):
802 # Save the provided password in hashed format
803 user = super(UserCreationForm, self).save(commit=False)
Tony Mackf9f4afb2013-05-01 21:02:12 -0400804 user.password = self.cleaned_data["password1"]
805 #user.set_password(self.cleaned_data["password1"])
Siobhan Tully53437282013-04-26 19:30:27 -0400806 if commit:
807 user.save()
808 return user
809
Siobhan Tully567e3e62013-06-21 18:03:16 -0400810
Siobhan Tully53437282013-04-26 19:30:27 -0400811class UserChangeForm(forms.ModelForm):
812 """A form for updating users. Includes all the fields on
813 the user, but replaces the password field with admin's
814 password hash display field.
815 """
Siobhan Tully63b7ba42014-01-12 10:35:11 -0500816 password = ReadOnlyPasswordHashField(label='Password',
817 help_text= '<a href=\"password/\">Change Password</a>.')
Siobhan Tully53437282013-04-26 19:30:27 -0400818
819 class Meta:
Siobhan Tully30fd4292013-05-10 08:59:56 -0400820 model = User
Siobhan Tully53437282013-04-26 19:30:27 -0400821
822 def clean_password(self):
823 # Regardless of what the user provides, return the initial value.
824 # This is done here, rather than on the field, because the
825 # field does not have access to the initial value
826 return self.initial["password"]
827
Tony Mack2bd5b412013-06-11 21:05:06 -0400828class UserAdmin(UserAdmin):
Siobhan Tully53437282013-04-26 19:30:27 -0400829 class Meta:
830 app_label = "core"
831
832 # The forms to add and change user instances
833 form = UserChangeForm
834 add_form = UserCreationForm
835
836 # The fields to be used in displaying the User model.
837 # These override the definitions on the base UserAdmin
838 # that reference specific fields on auth.User.
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500839 list_display = ('email', 'firstname', 'lastname', 'site', 'last_login')
Siobhan Tullyce652d02013-10-08 21:52:35 -0400840 #list_display = ('email', 'username','firstname', 'lastname', 'is_admin', 'last_login')
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500841 list_filter = ('site',)
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400842 inlines = [SlicePrivilegeInline,SitePrivilegeInline,DeploymentPrivilegeInline]
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500843
844 fieldListLoginDetails = ['email','site','password','is_readonly','is_amin','public_key']
845 fieldListContactInfo = ['firstname','lastname','phone','timezone']
846
Siobhan Tully53437282013-04-26 19:30:27 -0400847 fieldsets = (
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500848 ('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 -0400849 ('Contact Information', {'fields': ('firstname','lastname','phone', 'timezone'), 'classes':['suit-tab suit-tab-contact']}),
Siobhan Tully53437282013-04-26 19:30:27 -0400850 #('Important dates', {'fields': ('last_login',)}),
851 )
852 add_fieldsets = (
853 (None, {
854 'classes': ('wide',),
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500855 'fields': ('email', 'firstname', 'lastname', 'is_readonly', 'phone', 'public_key','password1', 'password2')}
Siobhan Tully53437282013-04-26 19:30:27 -0400856 ),
857 )
858 search_fields = ('email',)
859 ordering = ('email',)
860 filter_horizontal = ()
861
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500862 user_readonly_fields = fieldListLoginDetails
863 user_readonly_inlines = [SlicePrivilegeROInline,SitePrivilegeROInline,DeploymentPrivilegeROInline]
864
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400865 suit_form_tabs =(('general','Login Details'),('contact','Contact Information'),('sliceprivileges','Slice Privileges'),('siteprivileges','Site Privileges'),('deploymentprivileges','Deployment Privileges'))
866
Tony Mackc2835a92013-05-28 09:18:49 -0400867 def formfield_for_foreignkey(self, db_field, request, **kwargs):
868 if db_field.name == 'site':
869 if not request.user.is_admin:
870 # show sites where caller is an admin or pi
871 sites = []
872 for site_privilege in SitePrivilege.objects.filer(user=request.user):
873 if site_privilege.role.role_type in ['admin', 'pi']:
874 sites.append(site_privilege.site.login_base)
875 kwargs['queryset'] = Site.objects.filter(login_base__in(list(sites)))
876
877 return super(UserAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)
878
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500879 def has_add_permission(self, request, obj=None):
880 return (not self.__user_is_readonly(request))
881
882 def has_delete_permission(self, request, obj=None):
883 return (not self.__user_is_readonly(request))
884
885 def get_actions(self,request):
886 actions = super(UserAdmin,self).get_actions(request)
887
888 if self.__user_is_readonly(request):
889 if 'delete_selected' in actions:
890 del actions['delete_selected']
891
892 return actions
893
894 def change_view(self,request,object_id, extra_context=None):
895
896 if self.__user_is_readonly(request):
897 self.readonly_fields=self.user_readonly_fields
898 self.inlines = self.user_readonly_inlines
899 try:
900 return super(UserAdmin, self).change_view(request, object_id, extra_context=extra_context)
901 except PermissionDenied:
902 pass
903 if request.method == 'POST':
904 raise PermissionDenied
905 request.readonly = True
906 return super(UserAdmin, self).change_view(request, object_id, extra_context=extra_context)
907
908 def __user_is_readonly(self, request):
909 #groups = [x.name for x in request.user.groups.all() ]
910 #return "readonly" in groups
911 return request.user.isReadOnlyUser()
912
913
914
915class ServiceResourceROInline(ReadOnlyTabularInline):
916 model = ServiceResource
917 extra = 0
918 fields = ['serviceClass', 'name', 'maxUnitsDeployment', 'maxUnitsNode', 'maxDuration', 'bucketInRate', 'bucketMaxSize', 'cost', 'calendarReservable']
919
Scott Baker3de3e372013-05-10 16:50:44 -0700920class ServiceResourceInline(admin.TabularInline):
921 model = ServiceResource
922 extra = 0
923
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500924class ServiceClassAdmin(PlanetStackBaseAdmin):
Scott Baker3de3e372013-05-10 16:50:44 -0700925 list_display = ('name', 'commitment', 'membershipFee')
926 inlines = [ServiceResourceInline]
927
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500928 user_readonly_fields = ['name', 'commitment', 'membershipFee']
929 user_readonly_inlines = []
930
931class ReservedResourceROInline(ReadOnlyTabularInline):
932 model = ReservedResource
933 extra = 0
934 fields = ['sliver', 'resource','quantity','reservationSet']
935 suit_classes = 'suit-tab suit-tab-reservedresources'
936
Scott Baker133c9212013-05-17 09:09:11 -0700937class ReservedResourceInline(admin.TabularInline):
938 model = ReservedResource
939 extra = 0
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400940 suit_classes = 'suit-tab suit-tab-reservedresources'
Scott Baker133c9212013-05-17 09:09:11 -0700941
942 def formfield_for_foreignkey(self, db_field, request=None, **kwargs):
943 field = super(ReservedResourceInline, self).formfield_for_foreignkey(db_field, request, **kwargs)
944
945 if db_field.name == 'resource':
946 # restrict resources to those that the slice's service class allows
947 if request._slice is not None:
948 field.queryset = field.queryset.filter(serviceClass = request._slice.serviceClass, calendarReservable=True)
949 if len(field.queryset) > 0:
950 field.initial = field.queryset.all()[0]
951 else:
952 field.queryset = field.queryset.none()
953 elif db_field.name == 'sliver':
954 # restrict slivers to those that belong to the slice
955 if request._slice is not None:
956 field.queryset = field.queryset.filter(slice = request._slice)
957 else:
958 field.queryset = field.queryset.none()
959
960 return field
961
962class ReservationChangeForm(forms.ModelForm):
963 class Meta:
964 model = Reservation
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400965 widgets = {
966 'slice' : LinkedSelect
967 }
Scott Baker133c9212013-05-17 09:09:11 -0700968
969class ReservationAddForm(forms.ModelForm):
970 slice = forms.ModelChoiceField(queryset=Slice.objects.all(), widget=forms.Select(attrs={"onChange":"document.getElementById('id_refresh').value=1; submit()"}))
971 refresh = forms.CharField(widget=forms.HiddenInput())
972
973 class Media:
974 css = {'all': ('planetstack.css',)} # .field-refresh { display: none; }
975
976 def clean_slice(self):
977 slice = self.cleaned_data.get("slice")
978 x = ServiceResource.objects.filter(serviceClass = slice.serviceClass, calendarReservable=True)
979 if len(x) == 0:
980 raise forms.ValidationError("The slice you selected does not have a service class that allows reservations")
981 return slice
982
983 class Meta:
984 model = Reservation
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400985 widgets = {
986 'slice' : LinkedSelect
987 }
988
Scott Baker133c9212013-05-17 09:09:11 -0700989
990class ReservationAddRefreshForm(ReservationAddForm):
991 """ This form is displayed when the Reservation Form receives an update
992 from the Slice dropdown onChange handler. It doesn't validate the
993 data and doesn't save the data. This will cause the form to be
994 redrawn.
995 """
996
Scott Baker8737e5f2013-05-17 09:35:32 -0700997 """ don't validate anything other than slice """
998 dont_validate_fields = ("startTime", "duration")
999
Scott Baker133c9212013-05-17 09:09:11 -07001000 def full_clean(self):
1001 result = super(ReservationAddForm, self).full_clean()
Scott Baker8737e5f2013-05-17 09:35:32 -07001002
1003 for fieldname in self.dont_validate_fields:
1004 if fieldname in self._errors:
1005 del self._errors[fieldname]
1006
Scott Baker133c9212013-05-17 09:09:11 -07001007 return result
1008
1009 """ don't save anything """
1010 def is_valid(self):
1011 return False
1012
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001013class ReservationAdmin(PlanetStackBaseAdmin):
1014 fieldList = ['slice', 'startTime', 'duration']
1015 fieldsets = [('Reservation Details', {'fields': fieldList, 'classes': ['suit-tab suit-tab-general']})]
Scott Baker133c9212013-05-17 09:09:11 -07001016 list_display = ('startTime', 'duration')
Scott Baker133c9212013-05-17 09:09:11 -07001017 form = ReservationAddForm
1018
Siobhan Tullybfd11dc2013-09-03 12:59:24 -04001019 suit_form_tabs = (('general','Reservation Details'), ('reservedresources','Reserved Resources'))
1020
1021 inlines = [ReservedResourceInline]
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001022 user_readonly_inlines = [ReservedResourceROInline]
1023 user_readonly_fields = fieldList
Siobhan Tullybfd11dc2013-09-03 12:59:24 -04001024
Scott Baker133c9212013-05-17 09:09:11 -07001025 def add_view(self, request, form_url='', extra_context=None):
Scott Bakeracd45142013-05-19 16:19:16 -07001026 timezone.activate(request.user.timezone)
Scott Baker133c9212013-05-17 09:09:11 -07001027 request._refresh = False
1028 request._slice = None
1029 if request.method == 'POST':
Scott Baker8737e5f2013-05-17 09:35:32 -07001030 # "refresh" will be set to "1" if the form was submitted due to
1031 # a change in the Slice dropdown.
Scott Baker133c9212013-05-17 09:09:11 -07001032 if request.POST.get("refresh","1") == "1":
1033 request._refresh = True
1034 request.POST["refresh"] = "0"
Scott Baker8737e5f2013-05-17 09:35:32 -07001035
1036 # Keep track of the slice that was selected, so the
1037 # reservedResource inline can filter items for the slice.
Scott Baker133c9212013-05-17 09:09:11 -07001038 request._slice = request.POST.get("slice",None)
1039 if (request._slice is not None):
1040 request._slice = Slice.objects.get(id=request._slice)
1041
1042 result = super(ReservationAdmin, self).add_view(request, form_url, extra_context)
1043 return result
1044
Scott Bakeracd45142013-05-19 16:19:16 -07001045 def changelist_view(self, request, extra_context = None):
1046 timezone.activate(request.user.timezone)
1047 return super(ReservationAdmin, self).changelist_view(request, extra_context)
1048
Scott Baker133c9212013-05-17 09:09:11 -07001049 def get_form(self, request, obj=None, **kwargs):
Siobhan Tullyd3515752013-06-21 16:34:53 -04001050 request._obj_ = obj
1051 if obj is not None:
1052 # For changes, set request._slice to the slice already set in the
1053 # object.
1054 request._slice = obj.slice
1055 self.form = ReservationChangeForm
1056 else:
1057 if getattr(request, "_refresh", False):
1058 self.form = ReservationAddRefreshForm
1059 else:
1060 self.form = ReservationAddForm
1061 return super(ReservationAdmin, self).get_form(request, obj, **kwargs)
1062
Scott Baker133c9212013-05-17 09:09:11 -07001063 def get_readonly_fields(self, request, obj=None):
Siobhan Tullyd3515752013-06-21 16:34:53 -04001064 if (obj is not None):
1065 # Prevent slice from being changed after the reservation has been
1066 # created.
1067 return ['slice']
1068 else:
Scott Baker133c9212013-05-17 09:09:11 -07001069 return []
Scott Baker3de3e372013-05-10 16:50:44 -07001070
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001071class NetworkParameterTypeAdmin(PlanetStackBaseAdmin):
Scott Baker74d8e622013-07-29 16:04:22 -07001072 list_display = ("name", )
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001073 user_readonly_fields = ['name']
1074 user_readonly_inlines = []
Scott Baker74d8e622013-07-29 16:04:22 -07001075
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001076class RouterAdmin(PlanetStackBaseAdmin):
Scott Baker74d8e622013-07-29 16:04:22 -07001077 list_display = ("name", )
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001078 user_readonly_fields = ['name']
1079 user_readonly_inlines = []
1080
1081class RouterROInline(ReadOnlyTabularInline):
1082 model = Router.networks.through
1083 extra = 0
1084 verbose_name_plural = "Routers"
1085 verbose_name = "Router"
1086 suit_classes = 'suit-tab suit-tab-routers'
1087
1088 fields = ['name', 'owner', 'permittedNetworks', 'networks']
Scott Baker74d8e622013-07-29 16:04:22 -07001089
1090class RouterInline(admin.TabularInline):
Scott Baker74d8e622013-07-29 16:04:22 -07001091 model = Router.networks.through
1092 extra = 0
1093 verbose_name_plural = "Routers"
1094 verbose_name = "Router"
Siobhan Tully2d95e482013-09-06 10:56:06 -04001095 suit_classes = 'suit-tab suit-tab-routers'
Scott Baker74d8e622013-07-29 16:04:22 -07001096
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001097class NetworkParameterROInline(ReadOnlyTabularInline):
1098 model = NetworkParameter
1099 extra = 1
1100 verbose_name_plural = "Parameters"
1101 verbose_name = "Parameter"
1102 suit_classes = 'suit-tab suit-tab-netparams'
1103 fields = ['parameter', 'value', 'content_type', 'object_id', 'content_object']
1104
Scott Baker74d8e622013-07-29 16:04:22 -07001105class NetworkParameterInline(generic.GenericTabularInline):
Scott Baker74d8e622013-07-29 16:04:22 -07001106 model = NetworkParameter
1107 extra = 1
1108 verbose_name_plural = "Parameters"
1109 verbose_name = "Parameter"
Siobhan Tully2d95e482013-09-06 10:56:06 -04001110 suit_classes = 'suit-tab suit-tab-netparams'
Scott Baker74d8e622013-07-29 16:04:22 -07001111
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001112class NetworkSliversROInline(ReadOnlyTabularInline):
1113 fields = ['network', 'sliver', 'ip', 'port_id']
1114 model = NetworkSliver
1115 extra = 0
1116 verbose_name_plural = "Slivers"
1117 verbose_name = "Sliver"
1118 suit_classes = 'suit-tab suit-tab-networkslivers'
1119
Scott Baker74d8e622013-07-29 16:04:22 -07001120class NetworkSliversInline(admin.TabularInline):
Scott Baker74d8e622013-07-29 16:04:22 -07001121 readonly_fields = ("ip", )
1122 model = NetworkSliver
1123 extra = 0
1124 verbose_name_plural = "Slivers"
1125 verbose_name = "Sliver"
Siobhan Tully2d95e482013-09-06 10:56:06 -04001126 suit_classes = 'suit-tab suit-tab-networkslivers'
Scott Baker74d8e622013-07-29 16:04:22 -07001127
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001128class NetworkSlicesROInline(ReadOnlyTabularInline):
1129 model = NetworkSlice
1130 extra = 0
1131 verbose_name_plural = "Slices"
1132 verbose_name = "Slice"
1133 suit_classes = 'suit-tab suit-tab-networkslices'
1134 fields = ['network','slice']
1135
Scott Bakerd7d2a392013-08-06 08:57:30 -07001136class NetworkSlicesInline(admin.TabularInline):
Scott Bakerd7d2a392013-08-06 08:57:30 -07001137 model = NetworkSlice
1138 extra = 0
1139 verbose_name_plural = "Slices"
1140 verbose_name = "Slice"
Siobhan Tully2d95e482013-09-06 10:56:06 -04001141 suit_classes = 'suit-tab suit-tab-networkslices'
Scott Bakerd7d2a392013-08-06 08:57:30 -07001142
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001143class NetworkAdmin(PlanetStackBaseAdmin):
Scott Baker74d8e622013-07-29 16:04:22 -07001144 list_display = ("name", "subnet", "ports", "labels")
1145 readonly_fields = ("subnet", )
Siobhan Tully2d95e482013-09-06 10:56:06 -04001146
Scott Bakerd7d2a392013-08-06 08:57:30 -07001147 inlines = [NetworkParameterInline, NetworkSliversInline, NetworkSlicesInline, RouterInline]
Scott Baker74d8e622013-07-29 16:04:22 -07001148
Siobhan Tully2d95e482013-09-06 10:56:06 -04001149 fieldsets = [
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001150 (None, {'fields': ['name','template','ports','labels','owner','guaranteedBandwidth', 'permitAllSlices','permittedSlices','network_id','router_id','subnet_id','subnet'], 'classes':['suit-tab suit-tab-general']}),]
1151
1152 user_readonly_fields = ['name','template','ports','labels','owner','guaranteedBandwidth', 'permitAllSlices','permittedSlices','network_id','router_id','subnet_id','subnet']
1153 user_readonly_inlines = [NetworkParameterROInline, NetworkSliversROInline, NetworkSlicesROInline, RouterROInline]
Siobhan Tully2d95e482013-09-06 10:56:06 -04001154
1155 suit_form_tabs =(
1156 ('general','Network Details'),
1157 ('netparams', 'Parameters'),
1158 ('networkslivers','Slivers'),
1159 ('networkslices','Slices'),
1160 ('routers','Routers'),
1161 )
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001162class NetworkTemplateAdmin(PlanetStackBaseAdmin):
Scott Baker74d8e622013-07-29 16:04:22 -07001163 list_display = ("name", "guaranteedBandwidth", "visibility")
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001164 user_readonly_fields = ["name", "guaranteedBandwidth", "visibility"]
1165 user_readonly_inlines = []
Scott Baker74d8e622013-07-29 16:04:22 -07001166
Tony Mack31c2b8f2013-04-26 20:01:42 -04001167# register a signal that caches the user's credentials when they log in
1168def cache_credentials(sender, user, request, **kwds):
1169 auth = {'username': request.POST['username'],
1170 'password': request.POST['password']}
1171 request.session['auth'] = auth
1172user_logged_in.connect(cache_credentials)
1173
Scott Baker15cddfa2013-12-09 13:45:19 -08001174def dollar_field(fieldName, short_description):
1175 def newFunc(self, obj):
1176 try:
1177 x= "$ %0.2f" % float(getattr(obj, fieldName, 0.0))
1178 except:
1179 x=getattr(obj, fieldName, 0.0)
1180 return x
1181 newFunc.short_description = short_description
1182 return newFunc
1183
1184def right_dollar_field(fieldName, short_description):
1185 def newFunc(self, obj):
1186 try:
1187 #x= '<div align=right style="width:6em">$ %0.2f</div>' % float(getattr(obj, fieldName, 0.0))
1188 x= '<div align=right>$ %0.2f</div>' % float(getattr(obj, fieldName, 0.0))
1189 except:
1190 x=getattr(obj, fieldName, 0.0)
1191 return x
1192 newFunc.short_description = short_description
1193 newFunc.allow_tags = True
1194 return newFunc
Scott Baker43105042013-12-06 23:23:36 -08001195
1196class InvoiceChargeInline(admin.TabularInline):
1197 model = Charge
Scott Baker15cddfa2013-12-09 13:45:19 -08001198 extra = 0
Scott Baker43105042013-12-06 23:23:36 -08001199 verbose_name_plural = "Charges"
1200 verbose_name = "Charge"
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001201 exclude = ['account']
Scott Baker9cb88a22013-12-09 18:56:00 -08001202 fields = ["date", "kind", "state", "object", "coreHours", "dollar_amount", "slice"]
1203 readonly_fields = ["date", "kind", "state", "object", "coreHours", "dollar_amount", "slice"]
1204 can_delete = False
1205 max_num = 0
1206
1207 dollar_amount = right_dollar_field("amount", "Amount")
Scott Baker43105042013-12-06 23:23:36 -08001208
1209class InvoiceAdmin(admin.ModelAdmin):
1210 list_display = ("date", "account")
1211
1212 inlines = [InvoiceChargeInline]
1213
Scott Baker9cb88a22013-12-09 18:56:00 -08001214 fields = ["date", "account", "dollar_amount"]
1215 readonly_fields = ["date", "account", "dollar_amount"]
1216
1217 dollar_amount = dollar_field("amount", "Amount")
Scott Baker43105042013-12-06 23:23:36 -08001218
Scott Baker15cddfa2013-12-09 13:45:19 -08001219class InvoiceInline(admin.TabularInline):
1220 model = Invoice
1221 extra = 0
1222 verbose_name_plural = "Invoices"
1223 verbose_name = "Invoice"
Scott Baker9cb88a22013-12-09 18:56:00 -08001224 fields = ["date", "dollar_amount", "invoiceLink"]
1225 readonly_fields = ["date", "dollar_amount", "invoiceLink"]
Scott Baker15cddfa2013-12-09 13:45:19 -08001226 suit_classes = 'suit-tab suit-tab-accountinvoice'
1227 can_delete=False
1228 max_num=0
1229
1230 dollar_amount = right_dollar_field("amount", "Amount")
1231
Scott Baker9cb88a22013-12-09 18:56:00 -08001232 def invoiceLink(self, obj):
1233 reverse_path = "admin:core_invoice_change"
1234 url = reverse(reverse_path, args =(obj.id,))
1235 return "<a href='%s'>%s</a>" % (url, "details")
1236 invoiceLink.allow_tags = True
1237 invoiceLink.short_description = "Details"
1238
Scott Baker43105042013-12-06 23:23:36 -08001239class PendingChargeInline(admin.TabularInline):
1240 model = Charge
Scott Baker15cddfa2013-12-09 13:45:19 -08001241 extra = 0
Scott Baker43105042013-12-06 23:23:36 -08001242 verbose_name_plural = "Charges"
1243 verbose_name = "Charge"
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001244 exclude = ["invoice"]
Scott Baker15cddfa2013-12-09 13:45:19 -08001245 fields = ["date", "kind", "state", "object", "coreHours", "dollar_amount", "slice"]
1246 readonly_fields = ["date", "kind", "state", "object", "coreHours", "dollar_amount", "slice"]
Scott Baker43105042013-12-06 23:23:36 -08001247 suit_classes = 'suit-tab suit-tab-accountpendingcharges'
Scott Baker15cddfa2013-12-09 13:45:19 -08001248 can_delete=False
1249 max_num=0
Scott Baker43105042013-12-06 23:23:36 -08001250
1251 def queryset(self, request):
1252 qs = super(PendingChargeInline, self).queryset(request)
1253 qs = qs.filter(state="pending")
1254 return qs
1255
Scott Baker15cddfa2013-12-09 13:45:19 -08001256 dollar_amount = right_dollar_field("amount", "Amount")
1257
Scott Baker43105042013-12-06 23:23:36 -08001258class PaymentInline(admin.TabularInline):
1259 model=Payment
1260 extra = 1
1261 verbose_name_plural = "Payments"
1262 verbose_name = "Payment"
Scott Baker15cddfa2013-12-09 13:45:19 -08001263 fields = ["date", "dollar_amount"]
1264 readonly_fields = ["date", "dollar_amount"]
Scott Baker43105042013-12-06 23:23:36 -08001265 suit_classes = 'suit-tab suit-tab-accountpayments'
Scott Baker15cddfa2013-12-09 13:45:19 -08001266 can_delete=False
1267 max_num=0
1268
1269 dollar_amount = right_dollar_field("amount", "Amount")
1270
Scott Baker43105042013-12-06 23:23:36 -08001271class AccountAdmin(admin.ModelAdmin):
1272 list_display = ("site", "balance_due")
1273
1274 inlines = [InvoiceInline, PaymentInline, PendingChargeInline]
1275
1276 fieldsets = [
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001277 (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 -08001278
Scott Baker15cddfa2013-12-09 13:45:19 -08001279 readonly_fields = ['site', 'dollar_balance_due', 'dollar_total_invoices', 'dollar_total_payments']
Scott Baker43105042013-12-06 23:23:36 -08001280
1281 suit_form_tabs =(
1282 ('general','Account Details'),
1283 ('accountinvoice', 'Invoices'),
1284 ('accountpayments', 'Payments'),
1285 ('accountpendingcharges','Pending Charges'),
1286 )
1287
Scott Baker15cddfa2013-12-09 13:45:19 -08001288 dollar_balance_due = dollar_field("balance_due", "Balance Due")
1289 dollar_total_invoices = dollar_field("total_invoices", "Total Invoices")
1290 dollar_total_payments = dollar_field("total_payments", "Total Payments")
1291
Siobhan Tullyce652d02013-10-08 21:52:35 -04001292
Siobhan Tully53437282013-04-26 19:30:27 -04001293# Now register the new UserAdmin...
Siobhan Tully30fd4292013-05-10 08:59:56 -04001294admin.site.register(User, UserAdmin)
Siobhan Tully53437282013-04-26 19:30:27 -04001295# ... and, since we're not using Django's builtin permissions,
1296# unregister the Group model from admin.
Siobhan Tullyce652d02013-10-08 21:52:35 -04001297#admin.site.unregister(Group)
Siobhan Tully53437282013-04-26 19:30:27 -04001298
Siobhan Tullybf1153a2013-05-27 20:53:48 -04001299#Do not show django evolution in the admin interface
1300from django_evolution.models import Version, Evolution
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001301#admin.site.unregister(Version)
1302#admin.site.unregister(Evolution)
Siobhan Tullybf1153a2013-05-27 20:53:48 -04001303
1304
1305# When debugging it is often easier to see all the classes, but for regular use
1306# only the top-levels should be displayed
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001307showAll = False
Scott Baker43105042013-12-06 23:23:36 -08001308
Siobhan Tullybf1153a2013-05-27 20:53:48 -04001309admin.site.register(Deployment, DeploymentAdmin)
Siobhan Tully4bc09f22013-04-10 21:15:21 -04001310admin.site.register(Site, SiteAdmin)
Siobhan Tully4bc09f22013-04-10 21:15:21 -04001311admin.site.register(Slice, SliceAdmin)
Siobhan Tullyce652d02013-10-08 21:52:35 -04001312admin.site.register(Service, ServiceAdmin)
smbakera3cf70c2013-06-27 02:01:41 -07001313admin.site.register(Reservation, ReservationAdmin)
Scott Baker74d8e622013-07-29 16:04:22 -07001314admin.site.register(Network, NetworkAdmin)
1315admin.site.register(Router, RouterAdmin)
Scott Baker74d8e622013-07-29 16:04:22 -07001316admin.site.register(NetworkTemplate, NetworkTemplateAdmin)
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001317admin.site.register(Account, AccountAdmin)
1318admin.site.register(Invoice, InvoiceAdmin)
Siobhan Tullybf1153a2013-05-27 20:53:48 -04001319
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001320if True:
1321 admin.site.register(NetworkParameterType, NetworkParameterTypeAdmin)
1322 admin.site.register(ServiceClass, ServiceClassAdmin)
Siobhan Tullybfd11dc2013-09-03 12:59:24 -04001323 #admin.site.register(PlanetStack)
Siobhan Tullyd3515752013-06-21 16:34:53 -04001324 admin.site.register(Tag, TagAdmin)
Siobhan Tullyce652d02013-10-08 21:52:35 -04001325 admin.site.register(DeploymentRole)
1326 admin.site.register(SiteRole)
1327 admin.site.register(SliceRole)
1328 admin.site.register(PlanetStackRole)
Siobhan Tullybf1153a2013-05-27 20:53:48 -04001329 admin.site.register(Node, NodeAdmin)
Siobhan Tullybfd11dc2013-09-03 12:59:24 -04001330 #admin.site.register(SlicePrivilege, SlicePrivilegeAdmin)
1331 #admin.site.register(SitePrivilege, SitePrivilegeAdmin)
Siobhan Tullybf1153a2013-05-27 20:53:48 -04001332 admin.site.register(Sliver, SliverAdmin)
Siobhan Tullybf1153a2013-05-27 20:53:48 -04001333 admin.site.register(Image, ImageAdmin)
Tony Mack7130ac32013-03-22 21:58:00 -04001334