blob: 2dbf2c43fb4872a2f7bfdb79c7ec986c4b9135a8 [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
Scott Bakere2bbf7e2014-01-13 12:09:31 -080017from django.core.urlresolvers import reverse, NoReverseMatch
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
Scott Bakere2bbf7e2014-01-13 12:09:31 -080081 self.setup_selflink()
82
Scott Baker874936e2014-01-13 18:15:34 -080083 def get_change_url(self, model, id):
84 """ Get the URL to a change form in the admin for this model """
85 reverse_path = "admin:%s_change" % (model._meta.db_table)
Scott Bakere2bbf7e2014-01-13 12:09:31 -080086 try:
Scott Baker874936e2014-01-13 18:15:34 -080087 url = reverse(reverse_path, args=(id,))
Scott Bakere2bbf7e2014-01-13 12:09:31 -080088 except NoReverseMatch:
Scott Baker874936e2014-01-13 18:15:34 -080089 return None
90
91 return url
92
93 def setup_selflink(self):
94 if hasattr(self, "selflink_fieldname"):
95 """ self.selflink_model can be defined to punch through a relation
96 to its target object. For example, in SliceNetworkInline, set
97 selflink_model = "network", and the URL will lead to the Network
98 object instead of trying to bring up a change view of the
99 SliceNetwork object.
100 """
101 self.selflink_model = getattr(self.model,self.selflink_fieldname).field.rel.to
102 else:
103 self.selflink_model = self.model
104
105 url = self.get_change_url(self.selflink_model, 0)
106
107 # We don't have an admin for this object, so don't create the
108 # selflink.
109 if (url == None):
Scott Bakere2bbf7e2014-01-13 12:09:31 -0800110 return
111
Scott Baker874936e2014-01-13 18:15:34 -0800112 # Since we need to add "selflink" to the field list, we need to create
113 # self.fields if it is None.
Scott Baker0165fac2014-01-13 11:49:26 -0800114 if (self.fields is None):
115 self.fields = []
116 for f in self.model._meta.fields:
117 if f.editable and f.name != "id":
118 self.fields.append(f.name)
Scott Baker86568322014-01-12 16:53:31 -0800119
Scott Baker874936e2014-01-13 18:15:34 -0800120 self.fields = tuple(self.fields) + ("selflink", )
Scott Baker86568322014-01-12 16:53:31 -0800121
Scott Baker874936e2014-01-13 18:15:34 -0800122 if self.readonly_fields is None:
123 self.readonly_fields = ()
Scott Baker86568322014-01-12 16:53:31 -0800124
Scott Baker874936e2014-01-13 18:15:34 -0800125 self.readonly_fields = tuple(self.readonly_fields) + ("selflink", )
Scott Baker86568322014-01-12 16:53:31 -0800126
127 def selflink(self, obj):
Scott Baker874936e2014-01-13 18:15:34 -0800128 if hasattr(self, "selflink_fieldname"):
129 obj = getattr(obj, self.selflink_fieldname)
130
Scott Baker86568322014-01-12 16:53:31 -0800131 if obj.id:
Scott Baker874936e2014-01-13 18:15:34 -0800132 url = self.get_change_url(self.selflink_model, obj.id)
133 return "<a href='%s'>Details</a>" % str(url)
Scott Baker86568322014-01-12 16:53:31 -0800134 else:
Scott Bakere2bbf7e2014-01-13 12:09:31 -0800135 return "Not present"
Scott Baker86568322014-01-12 16:53:31 -0800136
137 selflink.allow_tags = True
138 selflink.short_description = "Details"
Siobhan Tullyd3515752013-06-21 16:34:53 -0400139
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500140class ReadOnlyTabularInline(PlStackTabularInline):
141 can_delete = False
142
143 def get_readonly_fields(self, request, obj=None):
144 return self.fields
145
146 def has_add_permission(self, request):
147 return False
148
149class ReservationROInline(ReadOnlyTabularInline):
150 model = Reservation
151 extra = 0
152 suit_classes = 'suit-tab suit-tab-reservations'
153 fields = ['startTime','slice','duration']
154
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400155class ReservationInline(PlStackTabularInline):
156 model = Reservation
157 extra = 0
158 suit_classes = 'suit-tab suit-tab-reservations'
Tony Mack5b061472014-02-04 07:57:10 -0500159
160 def queryset(self, request):
161 return Reservation.select_by_user(request.user)
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400162
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500163class TagROInline(generic.GenericTabularInline):
164 model = Tag
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400165 extra = 0
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500166 suit_classes = 'suit-tab suit-tab-tags'
167 can_delete = False
168 fields = ['service', 'name', 'value']
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400169
170 def get_readonly_fields(self, request, obj=None):
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500171 return self.fields
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400172
173 def has_add_permission(self, request):
174 return False
175
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500176
Siobhan Tullyde5450d2013-06-21 11:35:33 -0400177class TagInline(generic.GenericTabularInline):
178 model = Tag
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400179 extra = 0
180 suit_classes = 'suit-tab suit-tab-tags'
Tony Mack5b061472014-02-04 07:57:10 -0500181 fields = ['service', 'name', 'value']
182
183 def queryset(self, request):
184 return Tag.select_by_user(request.user)
Siobhan Tullyde5450d2013-06-21 11:35:33 -0400185
Scott Baker74d8e622013-07-29 16:04:22 -0700186class NetworkLookerUpper:
Siobhan Tully2c780ad2013-09-06 11:22:40 -0400187 """ This is a callable that looks up a network name in a sliver and returns
188 the ip address for that network.
189 """
190
191 def __init__(self, name):
192 self.short_description = name
193 self.__name__ = name
194 self.network_name = name
195
196 def __call__(self, obj):
197 if obj is not None:
198 for nbs in obj.networksliver_set.all():
199 if (nbs.network.name == self.network_name):
200 return nbs.ip
Scott Baker74d8e622013-07-29 16:04:22 -0700201 return ""
202
203 def __str__(self):
204 return self.network_name
205
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500206class SliverROInline(ReadOnlyTabularInline):
207 model = Sliver
208 fields = ['ip', 'instance_name', 'slice', 'numberCores', 'image', 'node', 'deploymentNetwork']
209 suit_classes = 'suit-tab suit-tab-slivers'
210
Siobhan Tullyd3515752013-06-21 16:34:53 -0400211class SliverInline(PlStackTabularInline):
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400212 model = Sliver
Tony Mackb0d97422013-06-10 09:57:45 -0400213 fields = ['ip', 'instance_name', 'slice', 'numberCores', 'image', 'node', 'deploymentNetwork']
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400214 extra = 0
Tony Mack3777b012013-05-07 21:38:06 -0400215 readonly_fields = ['ip', 'instance_name']
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400216 suit_classes = 'suit-tab suit-tab-slivers'
Scott Baker74d8e622013-07-29 16:04:22 -0700217
Tony Mack5b061472014-02-04 07:57:10 -0500218 def queryset(self, request):
219 return Sliver.select_by_user(request.user)
220
Siobhan Tully2d95e482013-09-06 10:56:06 -0400221# Note this is breaking in the admin.py when trying to use an inline to add a node/image
222# def _declared_fieldsets(self):
223# # Return None so django will call get_fieldsets and we can insert our
224# # dynamic fields
225# return None
226#
227# def get_readonly_fields(self, request, obj=None):
228# readonly_fields = super(SliverInline, self).get_readonly_fields(request, obj)
229#
230# # Lookup the networks that are bound to the slivers, and add those
231# # network names to the list of readonly fields.
232#
233# for sliver in obj.slivers.all():
234# for nbs in sliver.networksliver_set.all():
235# if nbs.ip:
236# network_name = nbs.network.name
237# if network_name not in [str(x) for x in readonly_fields]:
238# readonly_fields.append(NetworkLookerUpper(network_name))
239#
240# return readonly_fields
241#
242# def get_fieldsets(self, request, obj=None):
243# form = self.get_formset(request, obj).form
244# # fields = the read/write files + the read-only fields
245# fields = self.fields
246# for fieldName in self.get_readonly_fields(request,obj):
247# if not fieldName in fields:
248# fields.append(fieldName)
249#
250# return [(None, {'fields': fields})]
Scott Baker74d8e622013-07-29 16:04:22 -0700251
Tony Mackc2835a92013-05-28 09:18:49 -0400252
Siobhan Tully567e3e62013-06-21 18:03:16 -0400253
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500254class SiteROInline(ReadOnlyTabularInline):
255 model = Site
256 extra = 0
257 fields = ['name', 'login_base', 'site_url', 'enabled']
258 suit_classes = 'suit-tab suit-tab-sites'
259
Siobhan Tullyd3515752013-06-21 16:34:53 -0400260class SiteInline(PlStackTabularInline):
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400261 model = Site
262 extra = 0
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400263 suit_classes = 'suit-tab suit-tab-sites'
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400264
Tony Mack5b061472014-02-04 07:57:10 -0500265 def queryset(self, request):
266 return Site.select_by_user(request.user)
267
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500268class UserROInline(ReadOnlyTabularInline):
269 model = User
270 fields = ['email', 'firstname', 'lastname']
271 extra = 0
272 suit_classes = 'suit-tab suit-tab-users'
273
Siobhan Tullyd3515752013-06-21 16:34:53 -0400274class UserInline(PlStackTabularInline):
Siobhan Tully30fd4292013-05-10 08:59:56 -0400275 model = User
Siobhan Tully47ae1b52013-05-10 15:53:14 -0400276 fields = ['email', 'firstname', 'lastname']
Siobhan Tully30fd4292013-05-10 08:59:56 -0400277 extra = 0
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400278 suit_classes = 'suit-tab suit-tab-users'
Siobhan Tully30fd4292013-05-10 08:59:56 -0400279
Tony Mack5b061472014-02-04 07:57:10 -0500280 def queryset(self, request):
281 return User.select_by_user(request.user)
282
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500283class SliceROInline(ReadOnlyTabularInline):
284 model = Slice
285 suit_classes = 'suit-tab suit-tab-slices'
286 fields = ['name','site', 'serviceClass', 'service']
287
Siobhan Tullyd3515752013-06-21 16:34:53 -0400288class SliceInline(PlStackTabularInline):
Tony Mack00d361f2013-04-28 10:28:42 -0400289 model = Slice
Siobhan Tullyce652d02013-10-08 21:52:35 -0400290 fields = ['name','site', 'serviceClass', 'service']
Tony Mack00d361f2013-04-28 10:28:42 -0400291 extra = 0
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400292 suit_classes = 'suit-tab suit-tab-slices'
293
Tony Mack5b061472014-02-04 07:57:10 -0500294 def queryset(self, request):
295 return Slice.select_by_user(request.user)
296
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500297class NodeROInline(ReadOnlyTabularInline):
298 model = Node
299 extra = 0
300 suit_classes = 'suit-tab suit-tab-nodes'
301 fields = ['name','deployment']
Tony Mack00d361f2013-04-28 10:28:42 -0400302
Siobhan Tullyd3515752013-06-21 16:34:53 -0400303class NodeInline(PlStackTabularInline):
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400304 model = Node
305 extra = 0
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400306 suit_classes = 'suit-tab suit-tab-nodes'
Tony Mack5b061472014-02-04 07:57:10 -0500307 fields = ['name','deployment']
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400308
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500309class DeploymentPrivilegeROInline(ReadOnlyTabularInline):
310 model = DeploymentPrivilege
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400311 extra = 0
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500312 suit_classes = 'suit-tab suit-tab-deploymentprivileges'
313 fields = ['user','role']
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400314
315class DeploymentPrivilegeInline(PlStackTabularInline):
316 model = DeploymentPrivilege
317 extra = 0
318 suit_classes = 'suit-tab suit-tab-deploymentprivileges'
Tony Mack5b061472014-02-04 07:57:10 -0500319 fields = ['user','role']
320
321 def queryset(self, request):
322 return DeploymentPrivilege.select_by_user(request.user)
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400323
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500324#CLEANUP DOUBLE SitePrivilegeInline
325class SitePrivilegeROInline(ReadOnlyTabularInline):
326 model = SitePrivilege
327 extra = 0
328 suit_classes = 'suit-tab suit-tab-siteprivileges'
329 fields = ['user','site', 'role']
330
Siobhan Tullyd3515752013-06-21 16:34:53 -0400331class SitePrivilegeInline(PlStackTabularInline):
Siobhan Tullyaa1bcd52013-05-10 12:43:09 -0400332 model = SitePrivilege
333 extra = 0
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400334 suit_classes = 'suit-tab suit-tab-siteprivileges'
Tony Mack5b061472014-02-04 07:57:10 -0500335 fields = ['user','site', 'role']
Siobhan Tullyaa1bcd52013-05-10 12:43:09 -0400336
Tony Mackc2835a92013-05-28 09:18:49 -0400337 def formfield_for_foreignkey(self, db_field, request, **kwargs):
338 if db_field.name == 'site':
Tony Mack5b061472014-02-04 07:57:10 -0500339 kwargs['queryset'] = Site.select_by_user(request.user)
Tony Mackc2835a92013-05-28 09:18:49 -0400340
341 if db_field.name == 'user':
Tony Mack5b061472014-02-04 07:57:10 -0500342 kwargs['queryset'] = User.select_by_user(request.user)
Tony Mackc2835a92013-05-28 09:18:49 -0400343 return super(SitePrivilegeInline, self).formfield_for_foreignkey(db_field, request, **kwargs)
344
Tony Mack5b061472014-02-04 07:57:10 -0500345 def queryset(self, request):
346 return SitePrivilege.select_by_user(request.user)
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400347
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500348class SlicePrivilegeROInline(ReadOnlyTabularInline):
349 model = SlicePrivilege
350 extra = 0
351 suit_classes = 'suit-tab suit-tab-sliceprivileges'
352 fields = ['user', 'slice', 'role']
353
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400354class SlicePrivilegeInline(PlStackTabularInline):
355 model = SlicePrivilege
356 suit_classes = 'suit-tab suit-tab-sliceprivileges'
357 extra = 0
358 fields = ('user', 'slice','role')
Siobhan Tullyaa1bcd52013-05-10 12:43:09 -0400359
Tony Mackc2835a92013-05-28 09:18:49 -0400360 def formfield_for_foreignkey(self, db_field, request, **kwargs):
361 if db_field.name == 'slice':
Tony Mack5b061472014-02-04 07:57:10 -0500362 kwargs['queryset'] = Slice.select_by_user(request.user)
Tony Mackc2835a92013-05-28 09:18:49 -0400363 if db_field.name == 'user':
Tony Mack5b061472014-02-04 07:57:10 -0500364 kwargs['queryset'] = User.select_by_user(request.user)
Tony Mackc2835a92013-05-28 09:18:49 -0400365
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400366 return super(SlicePrivilegeInline, self).formfield_for_foreignkey(db_field, request, **kwargs)
Tony Mackc2835a92013-05-28 09:18:49 -0400367
Tony Mack5b061472014-02-04 07:57:10 -0500368 def queryset(self, request):
369 return SlicePrivilege.select_by_user(request.user)
370
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500371class SliceNetworkROInline(ReadOnlyTabularInline):
372 model = Network.slices.through
373 extra = 0
374 verbose_name = "Network Connection"
375 verbose_name_plural = "Network Connections"
376 suit_classes = 'suit-tab suit-tab-slicenetworks'
377 fields = ['network']
378
Scott Bakera0015eb2013-08-14 17:28:14 -0700379class SliceNetworkInline(PlStackTabularInline):
Scott Baker74d8e622013-07-29 16:04:22 -0700380 model = Network.slices.through
Scott Baker874936e2014-01-13 18:15:34 -0800381 selflink_fieldname = "network"
Scott Baker74d8e622013-07-29 16:04:22 -0700382 extra = 0
383 verbose_name = "Network Connection"
384 verbose_name_plural = "Network Connections"
Siobhan Tully2d95e482013-09-06 10:56:06 -0400385 suit_classes = 'suit-tab suit-tab-slicenetworks'
Scott Baker74d8e622013-07-29 16:04:22 -0700386
Tony Mack5e71a662013-05-03 23:30:41 -0400387class PlainTextWidget(forms.HiddenInput):
388 input_type = 'hidden'
389
390 def render(self, name, value, attrs=None):
391 if value is None:
392 value = ''
Tony Mack1d6b85f2013-05-07 18:49:14 -0400393 return mark_safe(str(value) + super(PlainTextWidget, self).render(name, value, attrs))
Tony Mack9bcbe4f2013-04-29 08:13:27 -0400394
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500395class PlanetStackBaseAdmin(ReadOnlyAwareAdmin):
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400396 save_on_top = False
397
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400398class SliceRoleAdmin(PlanetStackBaseAdmin):
399 model = SliceRole
400 pass
401
402class SiteRoleAdmin(PlanetStackBaseAdmin):
403 model = SiteRole
404 pass
405
Siobhan Tullybf1153a2013-05-27 20:53:48 -0400406class DeploymentAdminForm(forms.ModelForm):
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400407 sites = forms.ModelMultipleChoiceField(
408 queryset=Site.objects.all(),
409 required=False,
410 widget=FilteredSelectMultiple(
411 verbose_name=('Sites'), is_stacked=False
412 )
413 )
414 class Meta:
Siobhan Tullybf1153a2013-05-27 20:53:48 -0400415 model = Deployment
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400416
Siobhan Tully320b4622014-01-17 15:11:14 -0500417 def __init__(self, *args, **kwargs):
418 super(DeploymentAdminForm, self).__init__(*args, **kwargs)
419
420 if self.instance and self.instance.pk:
421 self.fields['sites'].initial = self.instance.sites.all()
422
423 def save(self, commit=True):
424 deployment = super(DeploymentAdminForm, self).save(commit=False)
425
426 if commit:
427 deployment.save()
428
429 if deployment.pk:
430 deployment.sites = self.cleaned_data['sites']
431 self.save_m2m()
432
433 return deployment
434
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500435class SiteAssocInline(PlStackTabularInline):
436 model = Site.deployments.through
437 extra = 0
438 suit_classes = 'suit-tab suit-tab-sites'
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400439
Siobhan Tullybf1153a2013-05-27 20:53:48 -0400440class DeploymentAdmin(PlanetStackBaseAdmin):
441 form = DeploymentAdminForm
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500442 model = Deployment
443 fieldList = ['name','sites']
444 fieldsets = [(None, {'fields': fieldList, 'classes':['suit-tab suit-tab-sites']})]
Siobhan Tully2d95e482013-09-06 10:56:06 -0400445 inlines = [DeploymentPrivilegeInline,NodeInline,TagInline]
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500446
447 user_readonly_inlines = [DeploymentPrivilegeROInline,NodeROInline,TagROInline]
448 user_readonly_fields = ['name']
449
450 suit_form_tabs =(('sites','Deployment Details'),('nodes','Nodes'),('deploymentprivileges','Privileges'),('tags','Tags'))
451
452class ServiceAttrAsTabROInline(ReadOnlyTabularInline):
453 model = ServiceAttribute
454 fields = ['name','value']
455 extra = 0
456 suit_classes = 'suit-tab suit-tab-serviceattrs'
Tony Mack5cd13202013-05-01 21:48:38 -0400457
Siobhan Tullyce652d02013-10-08 21:52:35 -0400458class ServiceAttrAsTabInline(PlStackTabularInline):
459 model = ServiceAttribute
460 fields = ['name','value']
461 extra = 0
462 suit_classes = 'suit-tab suit-tab-serviceattrs'
463
Siobhan Tullyce652d02013-10-08 21:52:35 -0400464class ServiceAdmin(PlanetStackBaseAdmin):
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500465 list_display = ("name","description","versionNumber","enabled","published")
466 fieldList = ["name","description","versionNumber","enabled","published"]
467 fieldsets = [(None, {'fields': fieldList, 'classes':['suit-tab suit-tab-general']})]
468 inlines = [ServiceAttrAsTabInline,SliceInline]
469
470 user_readonly_fields = fieldList
471 user_readonly_inlines = [ServiceAttrAsTabROInline,SliceROInline]
472
473 suit_form_tabs =(('general', 'Service Details'),
474 ('slices','Slices'),
475 ('serviceattrs','Additional Attributes'),
476 )
Siobhan Tullyce652d02013-10-08 21:52:35 -0400477
Tony Mack0553f282013-06-10 22:54:50 -0400478class SiteAdmin(PlanetStackBaseAdmin):
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500479 fieldList = ['name', 'site_url', 'enabled', 'is_public', 'login_base', 'accountLink','location']
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400480 fieldsets = [
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500481 (None, {'fields': fieldList, 'classes':['suit-tab suit-tab-general']}),
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400482 ('Deployment Networks', {'fields': ['deployments'], 'classes':['suit-tab suit-tab-deployments']}),
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400483 ]
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400484 suit_form_tabs =(('general', 'Site Details'),
485 ('users','Users'),
Siobhan Tully2d95e482013-09-06 10:56:06 -0400486 ('siteprivileges','Privileges'),
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400487 ('deployments','Deployments'),
488 ('slices','Slices'),
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500489 ('nodes','Nodes'),
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400490 ('tags','Tags'),
491 )
Scott Baker545db2a2013-12-09 18:44:43 -0800492 readonly_fields = ['accountLink']
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500493
494 user_readonly_fields = ['name', 'deployments','site_url', 'enabled', 'is_public', 'login_base', 'accountLink']
495 user_readonly_inlines = [SliceROInline,UserROInline,TagROInline, NodeROInline, SitePrivilegeROInline]
496
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400497 list_display = ('name', 'login_base','site_url', 'enabled')
498 filter_horizontal = ('deployments',)
Siobhan Tully2d95e482013-09-06 10:56:06 -0400499 inlines = [SliceInline,UserInline,TagInline, NodeInline, SitePrivilegeInline]
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400500 search_fields = ['name']
501
Tony Mack04062832013-05-10 08:22:44 -0400502 def queryset(self, request):
Tony Mack5b061472014-02-04 07:57:10 -0500503 #print dir(UserInline)
504 return Site.select_by_user(request.user)
Tony Mack04062832013-05-10 08:22:44 -0400505
Tony Mack5cd13202013-05-01 21:48:38 -0400506 def get_formsets(self, request, obj=None):
507 for inline in self.get_inline_instances(request, obj):
508 # hide MyInline in the add view
509 if obj is None:
510 continue
Tony Mack2bd5b412013-06-11 21:05:06 -0400511 if isinstance(inline, SliceInline):
512 inline.model.caller = request.user
513 yield inline.get_formset(request, obj)
514
515 def get_formsets(self, request, obj=None):
516 for inline in self.get_inline_instances(request, obj):
517 # hide MyInline in the add view
518 if obj is None:
519 continue
520 if isinstance(inline, SliverInline):
521 inline.model.caller = request.user
Tony Mack5cd13202013-05-01 21:48:38 -0400522 yield inline.get_formset(request, obj)
523
Scott Baker545db2a2013-12-09 18:44:43 -0800524 def accountLink(self, obj):
525 link_obj = obj.accounts.all()
526 if link_obj:
527 reverse_path = "admin:core_account_change"
528 url = reverse(reverse_path, args =(link_obj[0].id,))
529 return "<a href='%s'>%s</a>" % (url, "view billing details")
530 else:
531 return "no billing data for this site"
532 accountLink.allow_tags = True
533 accountLink.short_description = "Billing"
534
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500535
Tony Mack9bcbe4f2013-04-29 08:13:27 -0400536class SitePrivilegeAdmin(PlanetStackBaseAdmin):
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500537 fieldList = ['user', 'site', 'role']
Tony Mack00d361f2013-04-28 10:28:42 -0400538 fieldsets = [
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500539 (None, {'fields': fieldList, 'classes':['collapse']})
Tony Mack00d361f2013-04-28 10:28:42 -0400540 ]
541 list_display = ('user', 'site', 'role')
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500542 user_readonly_fields = fieldList
543 user_readonly_inlines = []
Tony Mack00d361f2013-04-28 10:28:42 -0400544
Tony Mackc2835a92013-05-28 09:18:49 -0400545 def formfield_for_foreignkey(self, db_field, request, **kwargs):
546 if db_field.name == 'site':
547 if not request.user.is_admin:
548 # only show sites where user is an admin or pi
549 sites = set()
550 for site_privilege in SitePrivilege.objects.filer(user=request.user):
551 if site_privilege.role.role_type in ['admin', 'pi']:
552 sites.add(site_privilege.site)
553 kwargs['queryset'] = Site.objects.filter(site__in=list(sites))
554
555 if db_field.name == 'user':
556 if not request.user.is_admin:
557 # only show users from sites where caller has admin or pi role
558 roles = Role.objects.filter(role_type__in=['admin', 'pi'])
559 site_privileges = SitePrivilege.objects.filter(user=request.user).filter(role__in=roles)
560 sites = [site_privilege.site for site_privilege in site_privileges]
561 site_privileges = SitePrivilege.objects.filter(site__in=sites)
562 emails = [site_privilege.user.email for site_privilege in site_privileges]
563 users = User.objects.filter(email__in=emails)
564 kwargs['queryset'] = users
565
566 return super(SitePrivilegeAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)
567
Tony Mack04062832013-05-10 08:22:44 -0400568 def queryset(self, request):
569 # admins can see all privileges. Users can only see privileges at sites
Tony Mackc2835a92013-05-28 09:18:49 -0400570 # where they have the admin role or pi role.
Tony Mack04062832013-05-10 08:22:44 -0400571 qs = super(SitePrivilegeAdmin, self).queryset(request)
Tony Mack5b061472014-02-04 07:57:10 -0500572 #if not request.user.is_admin:
573 # roles = Role.objects.filter(role_type__in=['admin', 'pi'])
574 # site_privileges = SitePrivilege.objects.filter(user=request.user).filter(role__in=roles)
575 # login_bases = [site_privilege.site.login_base for site_privilege in site_privileges]
576 # sites = Site.objects.filter(login_base__in=login_bases)
577 # qs = qs.filter(site__in=sites)
Tony Mack04062832013-05-10 08:22:44 -0400578 return qs
579
Siobhan Tullyce652d02013-10-08 21:52:35 -0400580class SliceForm(forms.ModelForm):
581 class Meta:
582 model = Slice
583 widgets = {
584 'service': LinkedSelect
585 }
586
Tony Mack2bd5b412013-06-11 21:05:06 -0400587class SliceAdmin(PlanetStackBaseAdmin):
Siobhan Tullyce652d02013-10-08 21:52:35 -0400588 form = SliceForm
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500589 fieldList = ['name', 'site', 'serviceClass', 'enabled','description', 'service', 'slice_url']
590 fieldsets = [('Slice Details', {'fields': fieldList, 'classes':['suit-tab suit-tab-general']}),]
Siobhan Tully30fd4292013-05-10 08:59:56 -0400591 list_display = ('name', 'site','serviceClass', 'slice_url')
Siobhan Tully2d95e482013-09-06 10:56:06 -0400592 inlines = [SlicePrivilegeInline,SliverInline, TagInline, ReservationInline,SliceNetworkInline]
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400593
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500594 user_readonly_fields = fieldList
595 user_readonly_inlines = [SlicePrivilegeROInline,SliverROInline,TagROInline, ReservationROInline, SliceNetworkROInline]
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400596
597 suit_form_tabs =(('general', 'Slice Details'),
Siobhan Tully2d95e482013-09-06 10:56:06 -0400598 ('slicenetworks','Networks'),
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400599 ('sliceprivileges','Privileges'),
600 ('slivers','Slivers'),
601 ('tags','Tags'),
602 ('reservations','Reservations'),
603 )
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400604
Tony Mackc2835a92013-05-28 09:18:49 -0400605 def formfield_for_foreignkey(self, db_field, request, **kwargs):
606 if db_field.name == 'site':
Tony Mack5b061472014-02-04 07:57:10 -0500607 kwargs['queryset'] = Site.select_by_user(request.user)
608
Tony Mackc2835a92013-05-28 09:18:49 -0400609 return super(SliceAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)
610
Tony Mack04062832013-05-10 08:22:44 -0400611 def queryset(self, request):
612 # admins can see all keys. Users can only see slices they belong to.
Tony Mack5b061472014-02-04 07:57:10 -0500613 return Slice.select_by_user(request.user)
Tony Mack04062832013-05-10 08:22:44 -0400614
Tony Mack79748612013-05-01 14:52:03 -0400615 def get_formsets(self, request, obj=None):
616 for inline in self.get_inline_instances(request, obj):
617 # hide MyInline in the add view
618 if obj is None:
619 continue
Tony Mack2bd5b412013-06-11 21:05:06 -0400620 if isinstance(inline, SliverInline):
621 inline.model.caller = request.user
Tony Mack79748612013-05-01 14:52:03 -0400622 yield inline.get_formset(request, obj)
623
Tony Mack2bd5b412013-06-11 21:05:06 -0400624
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400625class SlicePrivilegeAdmin(PlanetStackBaseAdmin):
Tony Mack00d361f2013-04-28 10:28:42 -0400626 fieldsets = [
627 (None, {'fields': ['user', 'slice', 'role']})
628 ]
629 list_display = ('user', 'slice', 'role')
Tony Mack00d361f2013-04-28 10:28:42 -0400630
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500631 user_readonly_fields = ['user', 'slice', 'role']
632 user_readonly_inlines = []
633
Tony Mackc2835a92013-05-28 09:18:49 -0400634 def formfield_for_foreignkey(self, db_field, request, **kwargs):
635 if db_field.name == 'slice':
Tony Mack5b061472014-02-04 07:57:10 -0500636 kwargs['queryset'] = Slice.select_by_user(request.user)
Tony Mackc2835a92013-05-28 09:18:49 -0400637
638 if db_field.name == 'user':
Tony Mack5b061472014-02-04 07:57:10 -0500639 kwargs['queryset'] = User.select_by_user(request.user)
Tony Mackc2835a92013-05-28 09:18:49 -0400640
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400641 return super(SlicePrivilegeAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)
Tony Mackc2835a92013-05-28 09:18:49 -0400642
Tony Mack04062832013-05-10 08:22:44 -0400643 def queryset(self, request):
644 # admins can see all memberships. Users can only see memberships of
645 # slices where they have the admin role.
Tony Mack5b061472014-02-04 07:57:10 -0500646 return SlicePrivilege.select_by_user(request.user)
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400647
Tony Mack9bcbe4f2013-04-29 08:13:27 -0400648 def save_model(self, request, obj, form, change):
Tony Mack951dab42013-05-02 19:51:45 -0400649 # update openstack connection to use this site/tenant
650 auth = request.session.get('auth', {})
651 auth['tenant'] = obj.slice.name
652 obj.os_manager = OpenStackManager(auth=auth, caller=request.user)
Tony Mack9bcbe4f2013-04-29 08:13:27 -0400653 obj.save()
654
655 def delete_model(self, request, obj):
Tony Mack951dab42013-05-02 19:51:45 -0400656 # update openstack connection to use this site/tenant
657 auth = request.session.get('auth', {})
658 auth['tenant'] = obj.slice.name
659 obj.os_manager = OpenStackManager(auth=auth, caller=request.user)
Tony Mack9bcbe4f2013-04-29 08:13:27 -0400660 obj.delete()
661
Siobhan Tully567e3e62013-06-21 18:03:16 -0400662
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400663class ImageAdmin(PlanetStackBaseAdmin):
664
665 fieldsets = [('Image Details',
666 {'fields': ['image_id', 'name', 'disk_format', 'container_format'],
667 'classes': ['suit-tab suit-tab-general']})
668 ]
669
670 suit_form_tabs =(('general','Image Details'),('slivers','Slivers'))
671
672 inlines = [SliverInline]
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500673
674 user_readonly_fields = ['image_id', 'name', 'disk_format', 'container_format']
675 user_readonly_inlines = [SliverROInline]
676
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400677class NodeForm(forms.ModelForm):
678 class Meta:
679 widgets = {
680 'site': LinkedSelect,
681 'deployment': LinkedSelect
682 }
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400683
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500684class NodeAdmin(PlanetStackBaseAdmin):
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400685 form = NodeForm
Siobhan Tullybf1153a2013-05-27 20:53:48 -0400686 list_display = ('name', 'site', 'deployment')
687 list_filter = ('deployment',)
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500688
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400689 inlines = [TagInline,SliverInline]
690 fieldsets = [('Node Details', {'fields': ['name','site','deployment'], 'classes':['suit-tab suit-tab-details']})]
691
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500692 user_readonly_fields = ['name','site','deployment']
693 user_readonly_inlines = [TagInline,SliverInline]
694
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400695 suit_form_tabs =(('details','Node Details'),('slivers','Slivers'),('tags','Tags'))
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400696
Siobhan Tully567e3e62013-06-21 18:03:16 -0400697
Tony Mackd90cdbf2013-04-16 22:48:40 -0400698class SliverForm(forms.ModelForm):
699 class Meta:
Tony Mack1d6b85f2013-05-07 18:49:14 -0400700 model = Sliver
Tony Mackd90cdbf2013-04-16 22:48:40 -0400701 ip = forms.CharField(widget=PlainTextWidget)
Tony Mack18261812013-05-02 16:39:20 -0400702 instance_name = forms.CharField(widget=PlainTextWidget)
Tony Mackd90cdbf2013-04-16 22:48:40 -0400703 widgets = {
704 'ip': PlainTextWidget(),
Tony Mack18261812013-05-02 16:39:20 -0400705 'instance_name': PlainTextWidget(),
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400706 'slice': LinkedSelect,
707 'deploymentNetwork': LinkedSelect,
708 'node': LinkedSelect,
709 'image': LinkedSelect
Siobhan Tully53437282013-04-26 19:30:27 -0400710 }
Tony Mackd90cdbf2013-04-16 22:48:40 -0400711
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500712class TagAdmin(PlanetStackBaseAdmin):
Siobhan Tullyce652d02013-10-08 21:52:35 -0400713 list_display = ['service', 'name', 'value', 'content_type', 'content_object',]
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500714 user_readonly_fields = ['service', 'name', 'value', 'content_type', 'content_object',]
715 user_readonly_inlines = []
Siobhan Tullyd3515752013-06-21 16:34:53 -0400716
Tony Mack9bcbe4f2013-04-29 08:13:27 -0400717class SliverAdmin(PlanetStackBaseAdmin):
Tony Mackd90cdbf2013-04-16 22:48:40 -0400718 form = SliverForm
Tony Mackcdec0902013-04-15 00:38:49 -0400719 fieldsets = [
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400720 ('Sliver Details', {'fields': ['slice', 'deploymentNetwork', 'node', 'ip', 'instance_name', 'numberCores', 'image', ], 'classes': ['suit-tab suit-tab-general'], })
Tony Mackcdec0902013-04-15 00:38:49 -0400721 ]
Siobhan Tully5d7dc8d2013-07-02 13:17:33 -0400722 list_display = ['ip', 'instance_name', 'slice', 'numberCores', 'image', 'node', 'deploymentNetwork']
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400723
724 suit_form_tabs =(('general', 'Sliver Details'),
725 ('tags','Tags'),
726 )
727
Siobhan Tullyde5450d2013-06-21 11:35:33 -0400728 inlines = [TagInline]
Tony Mack53106f32013-04-27 16:43:01 -0400729
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500730 user_readonly_fields = ['slice', 'deploymentNetwork', 'node', 'ip', 'instance_name', 'numberCores', 'image']
731 user_readonly_inlines = [TagROInline]
732
Tony Mackc2835a92013-05-28 09:18:49 -0400733 def formfield_for_foreignkey(self, db_field, request, **kwargs):
734 if db_field.name == 'slice':
Tony Mack5b061472014-02-04 07:57:10 -0500735 kwargs['queryset'] = Slice.select_by_user(request.user)
Tony Mackc2835a92013-05-28 09:18:49 -0400736
737 return super(SliverAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)
738
Tony Mack04062832013-05-10 08:22:44 -0400739 def queryset(self, request):
740 # admins can see all slivers. Users can only see slivers of
741 # the slices they belong to.
Tony Mack5b061472014-02-04 07:57:10 -0500742 return Sliver.select_by_user(request.user)
743
Tony Mack04062832013-05-10 08:22:44 -0400744
Tony Mack1d6b85f2013-05-07 18:49:14 -0400745 def get_formsets(self, request, obj=None):
746 # make some fields read only if we are updating an existing record
747 if obj == None:
748 #self.readonly_fields = ('ip', 'instance_name')
749 self.readonly_fields = ()
750 else:
Tony Mack1e889462013-05-10 21:34:54 -0400751 self.readonly_fields = ()
752 #self.readonly_fields = ('ip', 'instance_name', 'slice', 'image', 'key')
Tony Mack1d6b85f2013-05-07 18:49:14 -0400753
754 for inline in self.get_inline_instances(request, obj):
755 # hide MyInline in the add view
756 if obj is None:
757 continue
Tony Mack53106f32013-04-27 16:43:01 -0400758
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500759 #def save_model(self, request, obj, form, change):
760 # # update openstack connection to use this site/tenant
761 # auth = request.session.get('auth', {})
762 # auth['tenant'] = obj.slice.name
763 # obj.os_manager = OpenStackManager(auth=auth, caller=request.user)
764 # obj.creator = request.user
765 # obj.save()
Tony Mack53106f32013-04-27 16:43:01 -0400766
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500767 #def delete_model(self, request, obj):
768 # # update openstack connection to use this site/tenant
769 # auth = request.session.get('auth', {})
770 # auth['tenant'] = obj.slice.name
771 # obj.os_manager = OpenStackManager(auth=auth, caller=request.user)
772 # obj.delete()
Tony Mackcdec0902013-04-15 00:38:49 -0400773
Siobhan Tully53437282013-04-26 19:30:27 -0400774class UserCreationForm(forms.ModelForm):
775 """A form for creating new users. Includes all the required
776 fields, plus a repeated password."""
777 password1 = forms.CharField(label='Password', widget=forms.PasswordInput)
778 password2 = forms.CharField(label='Password confirmation', widget=forms.PasswordInput)
779
780 class Meta:
Siobhan Tully30fd4292013-05-10 08:59:56 -0400781 model = User
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400782 fields = ('email', 'firstname', 'lastname', 'phone', 'public_key')
Siobhan Tully53437282013-04-26 19:30:27 -0400783
784 def clean_password2(self):
785 # Check that the two password entries match
786 password1 = self.cleaned_data.get("password1")
787 password2 = self.cleaned_data.get("password2")
788 if password1 and password2 and password1 != password2:
789 raise forms.ValidationError("Passwords don't match")
790 return password2
791
792 def save(self, commit=True):
793 # Save the provided password in hashed format
794 user = super(UserCreationForm, self).save(commit=False)
Tony Mackf9f4afb2013-05-01 21:02:12 -0400795 user.password = self.cleaned_data["password1"]
796 #user.set_password(self.cleaned_data["password1"])
Siobhan Tully53437282013-04-26 19:30:27 -0400797 if commit:
798 user.save()
799 return user
800
Siobhan Tully567e3e62013-06-21 18:03:16 -0400801
Siobhan Tully53437282013-04-26 19:30:27 -0400802class UserChangeForm(forms.ModelForm):
803 """A form for updating users. Includes all the fields on
804 the user, but replaces the password field with admin's
805 password hash display field.
806 """
Siobhan Tully63b7ba42014-01-12 10:35:11 -0500807 password = ReadOnlyPasswordHashField(label='Password',
808 help_text= '<a href=\"password/\">Change Password</a>.')
Siobhan Tully53437282013-04-26 19:30:27 -0400809
810 class Meta:
Siobhan Tully30fd4292013-05-10 08:59:56 -0400811 model = User
Siobhan Tully53437282013-04-26 19:30:27 -0400812
813 def clean_password(self):
814 # Regardless of what the user provides, return the initial value.
815 # This is done here, rather than on the field, because the
816 # field does not have access to the initial value
817 return self.initial["password"]
818
Tony Mack2bd5b412013-06-11 21:05:06 -0400819class UserAdmin(UserAdmin):
Siobhan Tully53437282013-04-26 19:30:27 -0400820 class Meta:
821 app_label = "core"
822
823 # The forms to add and change user instances
824 form = UserChangeForm
825 add_form = UserCreationForm
826
827 # The fields to be used in displaying the User model.
828 # These override the definitions on the base UserAdmin
829 # that reference specific fields on auth.User.
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500830 list_display = ('email', 'firstname', 'lastname', 'site', 'last_login')
Siobhan Tullyce652d02013-10-08 21:52:35 -0400831 #list_display = ('email', 'username','firstname', 'lastname', 'is_admin', 'last_login')
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500832 list_filter = ('site',)
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400833 inlines = [SlicePrivilegeInline,SitePrivilegeInline,DeploymentPrivilegeInline]
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500834
835 fieldListLoginDetails = ['email','site','password','is_readonly','is_amin','public_key']
836 fieldListContactInfo = ['firstname','lastname','phone','timezone']
837
Siobhan Tully53437282013-04-26 19:30:27 -0400838 fieldsets = (
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500839 ('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 -0400840 ('Contact Information', {'fields': ('firstname','lastname','phone', 'timezone'), 'classes':['suit-tab suit-tab-contact']}),
Siobhan Tully53437282013-04-26 19:30:27 -0400841 #('Important dates', {'fields': ('last_login',)}),
842 )
843 add_fieldsets = (
844 (None, {
845 'classes': ('wide',),
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500846 'fields': ('email', 'firstname', 'lastname', 'is_readonly', 'phone', 'public_key','password1', 'password2')}
Siobhan Tully53437282013-04-26 19:30:27 -0400847 ),
848 )
849 search_fields = ('email',)
850 ordering = ('email',)
851 filter_horizontal = ()
852
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500853 user_readonly_fields = fieldListLoginDetails
854 user_readonly_inlines = [SlicePrivilegeROInline,SitePrivilegeROInline,DeploymentPrivilegeROInline]
855
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400856 suit_form_tabs =(('general','Login Details'),('contact','Contact Information'),('sliceprivileges','Slice Privileges'),('siteprivileges','Site Privileges'),('deploymentprivileges','Deployment Privileges'))
857
Tony Mackc2835a92013-05-28 09:18:49 -0400858 def formfield_for_foreignkey(self, db_field, request, **kwargs):
859 if db_field.name == 'site':
Tony Mack5b061472014-02-04 07:57:10 -0500860 kwargs['queryset'] = Site.select_by_user(request.user)
Tony Mackc2835a92013-05-28 09:18:49 -0400861
862 return super(UserAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)
863
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500864 def has_add_permission(self, request, obj=None):
865 return (not self.__user_is_readonly(request))
866
867 def has_delete_permission(self, request, obj=None):
868 return (not self.__user_is_readonly(request))
869
870 def get_actions(self,request):
871 actions = super(UserAdmin,self).get_actions(request)
872
873 if self.__user_is_readonly(request):
874 if 'delete_selected' in actions:
875 del actions['delete_selected']
876
877 return actions
878
879 def change_view(self,request,object_id, extra_context=None):
880
881 if self.__user_is_readonly(request):
882 self.readonly_fields=self.user_readonly_fields
883 self.inlines = self.user_readonly_inlines
884 try:
885 return super(UserAdmin, self).change_view(request, object_id, extra_context=extra_context)
886 except PermissionDenied:
887 pass
888 if request.method == 'POST':
889 raise PermissionDenied
890 request.readonly = True
891 return super(UserAdmin, self).change_view(request, object_id, extra_context=extra_context)
892
893 def __user_is_readonly(self, request):
894 #groups = [x.name for x in request.user.groups.all() ]
895 #return "readonly" in groups
896 return request.user.isReadOnlyUser()
897
Tony Mack5b061472014-02-04 07:57:10 -0500898 def queryset(self, request):
899 return User.select_by_user(request.user)
900
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500901
902
903class ServiceResourceROInline(ReadOnlyTabularInline):
904 model = ServiceResource
905 extra = 0
906 fields = ['serviceClass', 'name', 'maxUnitsDeployment', 'maxUnitsNode', 'maxDuration', 'bucketInRate', 'bucketMaxSize', 'cost', 'calendarReservable']
907
Scott Baker0165fac2014-01-13 11:49:26 -0800908class ServiceResourceInline(PlStackTabularInline):
Scott Baker3de3e372013-05-10 16:50:44 -0700909 model = ServiceResource
910 extra = 0
911
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500912class ServiceClassAdmin(PlanetStackBaseAdmin):
Scott Baker3de3e372013-05-10 16:50:44 -0700913 list_display = ('name', 'commitment', 'membershipFee')
914 inlines = [ServiceResourceInline]
915
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500916 user_readonly_fields = ['name', 'commitment', 'membershipFee']
917 user_readonly_inlines = []
918
919class ReservedResourceROInline(ReadOnlyTabularInline):
920 model = ReservedResource
921 extra = 0
922 fields = ['sliver', 'resource','quantity','reservationSet']
923 suit_classes = 'suit-tab suit-tab-reservedresources'
924
Scott Baker0165fac2014-01-13 11:49:26 -0800925class ReservedResourceInline(PlStackTabularInline):
Scott Baker133c9212013-05-17 09:09:11 -0700926 model = ReservedResource
927 extra = 0
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400928 suit_classes = 'suit-tab suit-tab-reservedresources'
Scott Baker133c9212013-05-17 09:09:11 -0700929
930 def formfield_for_foreignkey(self, db_field, request=None, **kwargs):
931 field = super(ReservedResourceInline, self).formfield_for_foreignkey(db_field, request, **kwargs)
932
933 if db_field.name == 'resource':
934 # restrict resources to those that the slice's service class allows
935 if request._slice is not None:
936 field.queryset = field.queryset.filter(serviceClass = request._slice.serviceClass, calendarReservable=True)
937 if len(field.queryset) > 0:
938 field.initial = field.queryset.all()[0]
939 else:
940 field.queryset = field.queryset.none()
941 elif db_field.name == 'sliver':
942 # restrict slivers to those that belong to the slice
943 if request._slice is not None:
944 field.queryset = field.queryset.filter(slice = request._slice)
945 else:
946 field.queryset = field.queryset.none()
947
948 return field
949
Tony Mack5b061472014-02-04 07:57:10 -0500950 def queryset(self, request):
951 return ReservedResource.select_by_user(request.user)
952
Scott Baker133c9212013-05-17 09:09:11 -0700953class ReservationChangeForm(forms.ModelForm):
954 class Meta:
955 model = Reservation
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400956 widgets = {
957 'slice' : LinkedSelect
958 }
Scott Baker133c9212013-05-17 09:09:11 -0700959
960class ReservationAddForm(forms.ModelForm):
961 slice = forms.ModelChoiceField(queryset=Slice.objects.all(), widget=forms.Select(attrs={"onChange":"document.getElementById('id_refresh').value=1; submit()"}))
962 refresh = forms.CharField(widget=forms.HiddenInput())
963
964 class Media:
965 css = {'all': ('planetstack.css',)} # .field-refresh { display: none; }
966
967 def clean_slice(self):
968 slice = self.cleaned_data.get("slice")
969 x = ServiceResource.objects.filter(serviceClass = slice.serviceClass, calendarReservable=True)
970 if len(x) == 0:
971 raise forms.ValidationError("The slice you selected does not have a service class that allows reservations")
972 return slice
973
974 class Meta:
975 model = Reservation
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400976 widgets = {
977 'slice' : LinkedSelect
978 }
979
Scott Baker133c9212013-05-17 09:09:11 -0700980
981class ReservationAddRefreshForm(ReservationAddForm):
982 """ This form is displayed when the Reservation Form receives an update
983 from the Slice dropdown onChange handler. It doesn't validate the
984 data and doesn't save the data. This will cause the form to be
985 redrawn.
986 """
987
Scott Baker8737e5f2013-05-17 09:35:32 -0700988 """ don't validate anything other than slice """
989 dont_validate_fields = ("startTime", "duration")
990
Scott Baker133c9212013-05-17 09:09:11 -0700991 def full_clean(self):
992 result = super(ReservationAddForm, self).full_clean()
Scott Baker8737e5f2013-05-17 09:35:32 -0700993
994 for fieldname in self.dont_validate_fields:
995 if fieldname in self._errors:
996 del self._errors[fieldname]
997
Scott Baker133c9212013-05-17 09:09:11 -0700998 return result
999
1000 """ don't save anything """
1001 def is_valid(self):
1002 return False
1003
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001004class ReservationAdmin(PlanetStackBaseAdmin):
1005 fieldList = ['slice', 'startTime', 'duration']
1006 fieldsets = [('Reservation Details', {'fields': fieldList, 'classes': ['suit-tab suit-tab-general']})]
Scott Baker133c9212013-05-17 09:09:11 -07001007 list_display = ('startTime', 'duration')
Scott Baker133c9212013-05-17 09:09:11 -07001008 form = ReservationAddForm
1009
Siobhan Tullybfd11dc2013-09-03 12:59:24 -04001010 suit_form_tabs = (('general','Reservation Details'), ('reservedresources','Reserved Resources'))
1011
1012 inlines = [ReservedResourceInline]
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001013 user_readonly_inlines = [ReservedResourceROInline]
1014 user_readonly_fields = fieldList
Siobhan Tullybfd11dc2013-09-03 12:59:24 -04001015
Scott Baker133c9212013-05-17 09:09:11 -07001016 def add_view(self, request, form_url='', extra_context=None):
Scott Bakeracd45142013-05-19 16:19:16 -07001017 timezone.activate(request.user.timezone)
Scott Baker133c9212013-05-17 09:09:11 -07001018 request._refresh = False
1019 request._slice = None
1020 if request.method == 'POST':
Scott Baker8737e5f2013-05-17 09:35:32 -07001021 # "refresh" will be set to "1" if the form was submitted due to
1022 # a change in the Slice dropdown.
Scott Baker133c9212013-05-17 09:09:11 -07001023 if request.POST.get("refresh","1") == "1":
1024 request._refresh = True
1025 request.POST["refresh"] = "0"
Scott Baker8737e5f2013-05-17 09:35:32 -07001026
1027 # Keep track of the slice that was selected, so the
1028 # reservedResource inline can filter items for the slice.
Scott Baker133c9212013-05-17 09:09:11 -07001029 request._slice = request.POST.get("slice",None)
1030 if (request._slice is not None):
1031 request._slice = Slice.objects.get(id=request._slice)
1032
1033 result = super(ReservationAdmin, self).add_view(request, form_url, extra_context)
1034 return result
1035
Scott Bakeracd45142013-05-19 16:19:16 -07001036 def changelist_view(self, request, extra_context = None):
1037 timezone.activate(request.user.timezone)
1038 return super(ReservationAdmin, self).changelist_view(request, extra_context)
1039
Scott Baker133c9212013-05-17 09:09:11 -07001040 def get_form(self, request, obj=None, **kwargs):
Siobhan Tullyd3515752013-06-21 16:34:53 -04001041 request._obj_ = obj
1042 if obj is not None:
1043 # For changes, set request._slice to the slice already set in the
1044 # object.
1045 request._slice = obj.slice
1046 self.form = ReservationChangeForm
1047 else:
1048 if getattr(request, "_refresh", False):
1049 self.form = ReservationAddRefreshForm
1050 else:
1051 self.form = ReservationAddForm
1052 return super(ReservationAdmin, self).get_form(request, obj, **kwargs)
1053
Scott Baker133c9212013-05-17 09:09:11 -07001054 def get_readonly_fields(self, request, obj=None):
Siobhan Tullyd3515752013-06-21 16:34:53 -04001055 if (obj is not None):
1056 # Prevent slice from being changed after the reservation has been
1057 # created.
1058 return ['slice']
1059 else:
Scott Baker133c9212013-05-17 09:09:11 -07001060 return []
Scott Baker3de3e372013-05-10 16:50:44 -07001061
Tony Mack5b061472014-02-04 07:57:10 -05001062 def queryset(self, request):
1063 return Reservation.select_by_user(request.user)
1064
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001065class NetworkParameterTypeAdmin(PlanetStackBaseAdmin):
Scott Baker74d8e622013-07-29 16:04:22 -07001066 list_display = ("name", )
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001067 user_readonly_fields = ['name']
1068 user_readonly_inlines = []
Scott Baker74d8e622013-07-29 16:04:22 -07001069
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001070class RouterAdmin(PlanetStackBaseAdmin):
Scott Baker74d8e622013-07-29 16:04:22 -07001071 list_display = ("name", )
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001072 user_readonly_fields = ['name']
1073 user_readonly_inlines = []
1074
1075class RouterROInline(ReadOnlyTabularInline):
1076 model = Router.networks.through
1077 extra = 0
1078 verbose_name_plural = "Routers"
1079 verbose_name = "Router"
1080 suit_classes = 'suit-tab suit-tab-routers'
1081
1082 fields = ['name', 'owner', 'permittedNetworks', 'networks']
Scott Baker74d8e622013-07-29 16:04:22 -07001083
Scott Baker0165fac2014-01-13 11:49:26 -08001084class RouterInline(PlStackTabularInline):
Scott Baker74d8e622013-07-29 16:04:22 -07001085 model = Router.networks.through
1086 extra = 0
1087 verbose_name_plural = "Routers"
1088 verbose_name = "Router"
Siobhan Tully2d95e482013-09-06 10:56:06 -04001089 suit_classes = 'suit-tab suit-tab-routers'
Scott Baker74d8e622013-07-29 16:04:22 -07001090
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001091class NetworkParameterROInline(ReadOnlyTabularInline):
1092 model = NetworkParameter
1093 extra = 1
1094 verbose_name_plural = "Parameters"
1095 verbose_name = "Parameter"
1096 suit_classes = 'suit-tab suit-tab-netparams'
1097 fields = ['parameter', 'value', 'content_type', 'object_id', 'content_object']
1098
Scott Baker74d8e622013-07-29 16:04:22 -07001099class NetworkParameterInline(generic.GenericTabularInline):
Scott Baker74d8e622013-07-29 16:04:22 -07001100 model = NetworkParameter
1101 extra = 1
1102 verbose_name_plural = "Parameters"
1103 verbose_name = "Parameter"
Siobhan Tully2d95e482013-09-06 10:56:06 -04001104 suit_classes = 'suit-tab suit-tab-netparams'
Scott Baker74d8e622013-07-29 16:04:22 -07001105
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001106class NetworkSliversROInline(ReadOnlyTabularInline):
1107 fields = ['network', 'sliver', 'ip', 'port_id']
1108 model = NetworkSliver
1109 extra = 0
1110 verbose_name_plural = "Slivers"
1111 verbose_name = "Sliver"
1112 suit_classes = 'suit-tab suit-tab-networkslivers'
1113
Scott Baker0165fac2014-01-13 11:49:26 -08001114class NetworkSliversInline(PlStackTabularInline):
Scott Baker74d8e622013-07-29 16:04:22 -07001115 readonly_fields = ("ip", )
1116 model = NetworkSliver
Scott Baker874936e2014-01-13 18:15:34 -08001117 selflink_fieldname = "sliver"
Scott Baker74d8e622013-07-29 16:04:22 -07001118 extra = 0
1119 verbose_name_plural = "Slivers"
1120 verbose_name = "Sliver"
Siobhan Tully2d95e482013-09-06 10:56:06 -04001121 suit_classes = 'suit-tab suit-tab-networkslivers'
Scott Baker74d8e622013-07-29 16:04:22 -07001122
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001123class NetworkSlicesROInline(ReadOnlyTabularInline):
1124 model = NetworkSlice
1125 extra = 0
1126 verbose_name_plural = "Slices"
1127 verbose_name = "Slice"
1128 suit_classes = 'suit-tab suit-tab-networkslices'
1129 fields = ['network','slice']
1130
Scott Baker0165fac2014-01-13 11:49:26 -08001131class NetworkSlicesInline(PlStackTabularInline):
Scott Bakerd7d2a392013-08-06 08:57:30 -07001132 model = NetworkSlice
Scott Baker874936e2014-01-13 18:15:34 -08001133 selflink_fieldname = "slice"
Scott Bakerd7d2a392013-08-06 08:57:30 -07001134 extra = 0
1135 verbose_name_plural = "Slices"
1136 verbose_name = "Slice"
Siobhan Tully2d95e482013-09-06 10:56:06 -04001137 suit_classes = 'suit-tab suit-tab-networkslices'
Scott Bakerd7d2a392013-08-06 08:57:30 -07001138
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001139class NetworkAdmin(PlanetStackBaseAdmin):
Scott Baker74d8e622013-07-29 16:04:22 -07001140 list_display = ("name", "subnet", "ports", "labels")
1141 readonly_fields = ("subnet", )
Siobhan Tully2d95e482013-09-06 10:56:06 -04001142
Scott Bakerd7d2a392013-08-06 08:57:30 -07001143 inlines = [NetworkParameterInline, NetworkSliversInline, NetworkSlicesInline, RouterInline]
Scott Baker74d8e622013-07-29 16:04:22 -07001144
Siobhan Tully2d95e482013-09-06 10:56:06 -04001145 fieldsets = [
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001146 (None, {'fields': ['name','template','ports','labels','owner','guaranteedBandwidth', 'permitAllSlices','permittedSlices','network_id','router_id','subnet_id','subnet'], 'classes':['suit-tab suit-tab-general']}),]
1147
1148 user_readonly_fields = ['name','template','ports','labels','owner','guaranteedBandwidth', 'permitAllSlices','permittedSlices','network_id','router_id','subnet_id','subnet']
1149 user_readonly_inlines = [NetworkParameterROInline, NetworkSliversROInline, NetworkSlicesROInline, RouterROInline]
Siobhan Tully2d95e482013-09-06 10:56:06 -04001150
1151 suit_form_tabs =(
1152 ('general','Network Details'),
1153 ('netparams', 'Parameters'),
1154 ('networkslivers','Slivers'),
1155 ('networkslices','Slices'),
1156 ('routers','Routers'),
1157 )
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001158class NetworkTemplateAdmin(PlanetStackBaseAdmin):
Scott Baker74d8e622013-07-29 16:04:22 -07001159 list_display = ("name", "guaranteedBandwidth", "visibility")
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001160 user_readonly_fields = ["name", "guaranteedBandwidth", "visibility"]
1161 user_readonly_inlines = []
Scott Baker74d8e622013-07-29 16:04:22 -07001162
Tony Mack31c2b8f2013-04-26 20:01:42 -04001163# register a signal that caches the user's credentials when they log in
1164def cache_credentials(sender, user, request, **kwds):
1165 auth = {'username': request.POST['username'],
1166 'password': request.POST['password']}
1167 request.session['auth'] = auth
1168user_logged_in.connect(cache_credentials)
1169
Scott Baker15cddfa2013-12-09 13:45:19 -08001170def dollar_field(fieldName, short_description):
1171 def newFunc(self, obj):
1172 try:
1173 x= "$ %0.2f" % float(getattr(obj, fieldName, 0.0))
1174 except:
1175 x=getattr(obj, fieldName, 0.0)
1176 return x
1177 newFunc.short_description = short_description
1178 return newFunc
1179
1180def right_dollar_field(fieldName, short_description):
1181 def newFunc(self, obj):
1182 try:
1183 #x= '<div align=right style="width:6em">$ %0.2f</div>' % float(getattr(obj, fieldName, 0.0))
1184 x= '<div align=right>$ %0.2f</div>' % float(getattr(obj, fieldName, 0.0))
1185 except:
1186 x=getattr(obj, fieldName, 0.0)
1187 return x
1188 newFunc.short_description = short_description
1189 newFunc.allow_tags = True
1190 return newFunc
Scott Baker43105042013-12-06 23:23:36 -08001191
Scott Baker0165fac2014-01-13 11:49:26 -08001192class InvoiceChargeInline(PlStackTabularInline):
Scott Baker43105042013-12-06 23:23:36 -08001193 model = Charge
Scott Baker15cddfa2013-12-09 13:45:19 -08001194 extra = 0
Scott Baker43105042013-12-06 23:23:36 -08001195 verbose_name_plural = "Charges"
1196 verbose_name = "Charge"
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001197 exclude = ['account']
Scott Baker9cb88a22013-12-09 18:56:00 -08001198 fields = ["date", "kind", "state", "object", "coreHours", "dollar_amount", "slice"]
1199 readonly_fields = ["date", "kind", "state", "object", "coreHours", "dollar_amount", "slice"]
1200 can_delete = False
1201 max_num = 0
1202
1203 dollar_amount = right_dollar_field("amount", "Amount")
Scott Baker43105042013-12-06 23:23:36 -08001204
1205class InvoiceAdmin(admin.ModelAdmin):
1206 list_display = ("date", "account")
1207
1208 inlines = [InvoiceChargeInline]
1209
Scott Baker9cb88a22013-12-09 18:56:00 -08001210 fields = ["date", "account", "dollar_amount"]
1211 readonly_fields = ["date", "account", "dollar_amount"]
1212
1213 dollar_amount = dollar_field("amount", "Amount")
Scott Baker43105042013-12-06 23:23:36 -08001214
Scott Baker0165fac2014-01-13 11:49:26 -08001215class InvoiceInline(PlStackTabularInline):
Scott Baker15cddfa2013-12-09 13:45:19 -08001216 model = Invoice
1217 extra = 0
1218 verbose_name_plural = "Invoices"
1219 verbose_name = "Invoice"
Scott Baker0165fac2014-01-13 11:49:26 -08001220 fields = ["date", "dollar_amount"]
1221 readonly_fields = ["date", "dollar_amount"]
Scott Baker15cddfa2013-12-09 13:45:19 -08001222 suit_classes = 'suit-tab suit-tab-accountinvoice'
1223 can_delete=False
1224 max_num=0
1225
1226 dollar_amount = right_dollar_field("amount", "Amount")
1227
Scott Baker0165fac2014-01-13 11:49:26 -08001228class PendingChargeInline(PlStackTabularInline):
Scott Baker43105042013-12-06 23:23:36 -08001229 model = Charge
Scott Baker15cddfa2013-12-09 13:45:19 -08001230 extra = 0
Scott Baker43105042013-12-06 23:23:36 -08001231 verbose_name_plural = "Charges"
1232 verbose_name = "Charge"
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001233 exclude = ["invoice"]
Scott Baker15cddfa2013-12-09 13:45:19 -08001234 fields = ["date", "kind", "state", "object", "coreHours", "dollar_amount", "slice"]
1235 readonly_fields = ["date", "kind", "state", "object", "coreHours", "dollar_amount", "slice"]
Scott Baker43105042013-12-06 23:23:36 -08001236 suit_classes = 'suit-tab suit-tab-accountpendingcharges'
Scott Baker15cddfa2013-12-09 13:45:19 -08001237 can_delete=False
1238 max_num=0
Scott Baker43105042013-12-06 23:23:36 -08001239
1240 def queryset(self, request):
1241 qs = super(PendingChargeInline, self).queryset(request)
1242 qs = qs.filter(state="pending")
1243 return qs
1244
Scott Baker15cddfa2013-12-09 13:45:19 -08001245 dollar_amount = right_dollar_field("amount", "Amount")
1246
Scott Baker0165fac2014-01-13 11:49:26 -08001247class PaymentInline(PlStackTabularInline):
Scott Baker43105042013-12-06 23:23:36 -08001248 model=Payment
1249 extra = 1
1250 verbose_name_plural = "Payments"
1251 verbose_name = "Payment"
Scott Baker15cddfa2013-12-09 13:45:19 -08001252 fields = ["date", "dollar_amount"]
1253 readonly_fields = ["date", "dollar_amount"]
Scott Baker43105042013-12-06 23:23:36 -08001254 suit_classes = 'suit-tab suit-tab-accountpayments'
Scott Baker15cddfa2013-12-09 13:45:19 -08001255 can_delete=False
1256 max_num=0
1257
1258 dollar_amount = right_dollar_field("amount", "Amount")
1259
Scott Baker43105042013-12-06 23:23:36 -08001260class AccountAdmin(admin.ModelAdmin):
1261 list_display = ("site", "balance_due")
1262
1263 inlines = [InvoiceInline, PaymentInline, PendingChargeInline]
1264
1265 fieldsets = [
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001266 (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 -08001267
Scott Baker15cddfa2013-12-09 13:45:19 -08001268 readonly_fields = ['site', 'dollar_balance_due', 'dollar_total_invoices', 'dollar_total_payments']
Scott Baker43105042013-12-06 23:23:36 -08001269
1270 suit_form_tabs =(
1271 ('general','Account Details'),
1272 ('accountinvoice', 'Invoices'),
1273 ('accountpayments', 'Payments'),
1274 ('accountpendingcharges','Pending Charges'),
1275 )
1276
Scott Baker15cddfa2013-12-09 13:45:19 -08001277 dollar_balance_due = dollar_field("balance_due", "Balance Due")
1278 dollar_total_invoices = dollar_field("total_invoices", "Total Invoices")
1279 dollar_total_payments = dollar_field("total_payments", "Total Payments")
1280
Siobhan Tullyce652d02013-10-08 21:52:35 -04001281
Siobhan Tully53437282013-04-26 19:30:27 -04001282# Now register the new UserAdmin...
Siobhan Tully30fd4292013-05-10 08:59:56 -04001283admin.site.register(User, UserAdmin)
Siobhan Tully53437282013-04-26 19:30:27 -04001284# ... and, since we're not using Django's builtin permissions,
1285# unregister the Group model from admin.
Siobhan Tullyce652d02013-10-08 21:52:35 -04001286#admin.site.unregister(Group)
Siobhan Tully53437282013-04-26 19:30:27 -04001287
Siobhan Tullybf1153a2013-05-27 20:53:48 -04001288#Do not show django evolution in the admin interface
1289from django_evolution.models import Version, Evolution
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001290#admin.site.unregister(Version)
1291#admin.site.unregister(Evolution)
Siobhan Tullybf1153a2013-05-27 20:53:48 -04001292
1293
1294# When debugging it is often easier to see all the classes, but for regular use
1295# only the top-levels should be displayed
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001296showAll = False
Scott Baker43105042013-12-06 23:23:36 -08001297
Siobhan Tullybf1153a2013-05-27 20:53:48 -04001298admin.site.register(Deployment, DeploymentAdmin)
Siobhan Tully4bc09f22013-04-10 21:15:21 -04001299admin.site.register(Site, SiteAdmin)
Siobhan Tully4bc09f22013-04-10 21:15:21 -04001300admin.site.register(Slice, SliceAdmin)
Siobhan Tullyce652d02013-10-08 21:52:35 -04001301admin.site.register(Service, ServiceAdmin)
smbakera3cf70c2013-06-27 02:01:41 -07001302admin.site.register(Reservation, ReservationAdmin)
Scott Baker74d8e622013-07-29 16:04:22 -07001303admin.site.register(Network, NetworkAdmin)
1304admin.site.register(Router, RouterAdmin)
Scott Baker74d8e622013-07-29 16:04:22 -07001305admin.site.register(NetworkTemplate, NetworkTemplateAdmin)
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001306admin.site.register(Account, AccountAdmin)
1307admin.site.register(Invoice, InvoiceAdmin)
Siobhan Tullybf1153a2013-05-27 20:53:48 -04001308
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001309if True:
1310 admin.site.register(NetworkParameterType, NetworkParameterTypeAdmin)
1311 admin.site.register(ServiceClass, ServiceClassAdmin)
Siobhan Tullybfd11dc2013-09-03 12:59:24 -04001312 #admin.site.register(PlanetStack)
Siobhan Tullyd3515752013-06-21 16:34:53 -04001313 admin.site.register(Tag, TagAdmin)
Siobhan Tullyce652d02013-10-08 21:52:35 -04001314 admin.site.register(DeploymentRole)
1315 admin.site.register(SiteRole)
1316 admin.site.register(SliceRole)
1317 admin.site.register(PlanetStackRole)
Siobhan Tullybf1153a2013-05-27 20:53:48 -04001318 admin.site.register(Node, NodeAdmin)
Siobhan Tullybfd11dc2013-09-03 12:59:24 -04001319 #admin.site.register(SlicePrivilege, SlicePrivilegeAdmin)
1320 #admin.site.register(SitePrivilege, SitePrivilegeAdmin)
Siobhan Tullybf1153a2013-05-27 20:53:48 -04001321 admin.site.register(Sliver, SliverAdmin)
Siobhan Tullybf1153a2013-05-27 20:53:48 -04001322 admin.site.register(Image, ImageAdmin)
Tony Mack7130ac32013-03-22 21:58:00 -04001323