blob: 2a77f3fbc9a63ac65e1670c2d36eba5ddcb46476 [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
Tony Macke4be32f2014-03-11 20:45:25 -0400348class SiteDeploymentROInline(ReadOnlyTabularInline):
349 model = SiteDeployments
350 #model = Site.deployments.through
351 extra = 0
352 suit_classes = 'suit-tab suit-tab-sitedeployments'
353 fields = ['deployment','site']
354
355class SiteDeploymentInline(PlStackTabularInline):
356 model = SiteDeployments
357 #model = Site.deployments.through
358 extra = 0
359 suit_classes = 'suit-tab suit-tab-deployments'
360 fields = ['deployment','site']
361
362 def formfield_for_foreignkey(self, db_field, request, **kwargs):
363 if db_field.name == 'site':
364 kwargs['queryset'] = Site.select_by_user(request.user)
365
366 if db_field.name == 'deployment':
367 kwargs['queryset'] = Deployment.select_by_user(request.user)
368 return super(SiteDeploymentInline, self).formfield_for_foreignkey(db_field, request, **kwargs)
369
370 def queryset(self, request):
371 return SiteDeployments.select_by_user(request.user)
372
373
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500374class SlicePrivilegeROInline(ReadOnlyTabularInline):
375 model = SlicePrivilege
376 extra = 0
377 suit_classes = 'suit-tab suit-tab-sliceprivileges'
378 fields = ['user', 'slice', 'role']
379
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400380class SlicePrivilegeInline(PlStackTabularInline):
381 model = SlicePrivilege
382 suit_classes = 'suit-tab suit-tab-sliceprivileges'
383 extra = 0
384 fields = ('user', 'slice','role')
Siobhan Tullyaa1bcd52013-05-10 12:43:09 -0400385
Tony Mackc2835a92013-05-28 09:18:49 -0400386 def formfield_for_foreignkey(self, db_field, request, **kwargs):
387 if db_field.name == 'slice':
Tony Mack5b061472014-02-04 07:57:10 -0500388 kwargs['queryset'] = Slice.select_by_user(request.user)
Tony Mackc2835a92013-05-28 09:18:49 -0400389 if db_field.name == 'user':
Tony Mack5b061472014-02-04 07:57:10 -0500390 kwargs['queryset'] = User.select_by_user(request.user)
Tony Mackc2835a92013-05-28 09:18:49 -0400391
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400392 return super(SlicePrivilegeInline, self).formfield_for_foreignkey(db_field, request, **kwargs)
Tony Mackc2835a92013-05-28 09:18:49 -0400393
Tony Mack5b061472014-02-04 07:57:10 -0500394 def queryset(self, request):
395 return SlicePrivilege.select_by_user(request.user)
396
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500397class SliceNetworkROInline(ReadOnlyTabularInline):
398 model = Network.slices.through
399 extra = 0
400 verbose_name = "Network Connection"
401 verbose_name_plural = "Network Connections"
402 suit_classes = 'suit-tab suit-tab-slicenetworks'
403 fields = ['network']
404
Scott Bakera0015eb2013-08-14 17:28:14 -0700405class SliceNetworkInline(PlStackTabularInline):
Scott Baker74d8e622013-07-29 16:04:22 -0700406 model = Network.slices.through
Scott Baker874936e2014-01-13 18:15:34 -0800407 selflink_fieldname = "network"
Scott Baker74d8e622013-07-29 16:04:22 -0700408 extra = 0
409 verbose_name = "Network Connection"
410 verbose_name_plural = "Network Connections"
Siobhan Tully2d95e482013-09-06 10:56:06 -0400411 suit_classes = 'suit-tab suit-tab-slicenetworks'
Scott Baker74d8e622013-07-29 16:04:22 -0700412
Tony Mack5e71a662013-05-03 23:30:41 -0400413class PlainTextWidget(forms.HiddenInput):
414 input_type = 'hidden'
415
416 def render(self, name, value, attrs=None):
417 if value is None:
418 value = ''
Tony Mack1d6b85f2013-05-07 18:49:14 -0400419 return mark_safe(str(value) + super(PlainTextWidget, self).render(name, value, attrs))
Tony Mack9bcbe4f2013-04-29 08:13:27 -0400420
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500421class PlanetStackBaseAdmin(ReadOnlyAwareAdmin):
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400422 save_on_top = False
Tony Mack332ee1d2014-02-04 15:33:45 -0500423
424 def save_model(self, request, obj, form, change):
Tony Mack3d042792014-03-17 19:18:37 -0400425 obj.caller = request.user
Tony Mack332ee1d2014-02-04 15:33:45 -0500426 # update openstack connection to use this site/tenant
427 obj.save_by_user(request.user)
428
429 def delete_model(self, request, obj):
430 obj.delete_by_user(request.user)
431
432 def save_formset(self, request, form, formset, change):
433 instances = formset.save(commit=False)
434 for instance in instances:
435 instance.save_by_user(request.user)
436 formset.save_m2m()
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400437
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400438class SliceRoleAdmin(PlanetStackBaseAdmin):
439 model = SliceRole
440 pass
441
442class SiteRoleAdmin(PlanetStackBaseAdmin):
443 model = SiteRole
444 pass
445
Siobhan Tullybf1153a2013-05-27 20:53:48 -0400446class DeploymentAdminForm(forms.ModelForm):
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400447 sites = forms.ModelMultipleChoiceField(
448 queryset=Site.objects.all(),
449 required=False,
450 widget=FilteredSelectMultiple(
451 verbose_name=('Sites'), is_stacked=False
452 )
453 )
454 class Meta:
Siobhan Tullybf1153a2013-05-27 20:53:48 -0400455 model = Deployment
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400456
Siobhan Tully320b4622014-01-17 15:11:14 -0500457 def __init__(self, *args, **kwargs):
458 super(DeploymentAdminForm, self).__init__(*args, **kwargs)
459
460 if self.instance and self.instance.pk:
461 self.fields['sites'].initial = self.instance.sites.all()
462
463 def save(self, commit=True):
464 deployment = super(DeploymentAdminForm, self).save(commit=False)
465
466 if commit:
467 deployment.save()
468
469 if deployment.pk:
470 deployment.sites = self.cleaned_data['sites']
471 self.save_m2m()
472
473 return deployment
474
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500475class SiteAssocInline(PlStackTabularInline):
476 model = Site.deployments.through
477 extra = 0
478 suit_classes = 'suit-tab suit-tab-sites'
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400479
Siobhan Tullybf1153a2013-05-27 20:53:48 -0400480class DeploymentAdmin(PlanetStackBaseAdmin):
481 form = DeploymentAdminForm
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500482 model = Deployment
483 fieldList = ['name','sites']
484 fieldsets = [(None, {'fields': fieldList, 'classes':['suit-tab suit-tab-sites']})]
Siobhan Tully2d95e482013-09-06 10:56:06 -0400485 inlines = [DeploymentPrivilegeInline,NodeInline,TagInline]
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500486
487 user_readonly_inlines = [DeploymentPrivilegeROInline,NodeROInline,TagROInline]
488 user_readonly_fields = ['name']
489
490 suit_form_tabs =(('sites','Deployment Details'),('nodes','Nodes'),('deploymentprivileges','Privileges'),('tags','Tags'))
491
492class ServiceAttrAsTabROInline(ReadOnlyTabularInline):
493 model = ServiceAttribute
494 fields = ['name','value']
495 extra = 0
496 suit_classes = 'suit-tab suit-tab-serviceattrs'
Tony Mack5cd13202013-05-01 21:48:38 -0400497
Siobhan Tullyce652d02013-10-08 21:52:35 -0400498class ServiceAttrAsTabInline(PlStackTabularInline):
499 model = ServiceAttribute
500 fields = ['name','value']
501 extra = 0
502 suit_classes = 'suit-tab suit-tab-serviceattrs'
503
Siobhan Tullyce652d02013-10-08 21:52:35 -0400504class ServiceAdmin(PlanetStackBaseAdmin):
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500505 list_display = ("name","description","versionNumber","enabled","published")
506 fieldList = ["name","description","versionNumber","enabled","published"]
507 fieldsets = [(None, {'fields': fieldList, 'classes':['suit-tab suit-tab-general']})]
508 inlines = [ServiceAttrAsTabInline,SliceInline]
509
510 user_readonly_fields = fieldList
511 user_readonly_inlines = [ServiceAttrAsTabROInline,SliceROInline]
512
513 suit_form_tabs =(('general', 'Service Details'),
514 ('slices','Slices'),
515 ('serviceattrs','Additional Attributes'),
516 )
Siobhan Tullyce652d02013-10-08 21:52:35 -0400517
Tony Mack0553f282013-06-10 22:54:50 -0400518class SiteAdmin(PlanetStackBaseAdmin):
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500519 fieldList = ['name', 'site_url', 'enabled', 'is_public', 'login_base', 'accountLink','location']
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400520 fieldsets = [
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500521 (None, {'fields': fieldList, 'classes':['suit-tab suit-tab-general']}),
Tony Macke4be32f2014-03-11 20:45:25 -0400522 #('Deployment Networks', {'fields': ['deployments'], 'classes':['suit-tab suit-tab-deployments']}),
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400523 ]
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400524 suit_form_tabs =(('general', 'Site Details'),
525 ('users','Users'),
Siobhan Tully2d95e482013-09-06 10:56:06 -0400526 ('siteprivileges','Privileges'),
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400527 ('deployments','Deployments'),
528 ('slices','Slices'),
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500529 ('nodes','Nodes'),
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400530 ('tags','Tags'),
531 )
Scott Baker545db2a2013-12-09 18:44:43 -0800532 readonly_fields = ['accountLink']
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500533
534 user_readonly_fields = ['name', 'deployments','site_url', 'enabled', 'is_public', 'login_base', 'accountLink']
Tony Macke4be32f2014-03-11 20:45:25 -0400535 user_readonly_inlines = [SliceROInline,UserROInline,TagROInline, NodeROInline, SitePrivilegeROInline,SiteDeploymentROInline]
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500536
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400537 list_display = ('name', 'login_base','site_url', 'enabled')
538 filter_horizontal = ('deployments',)
Tony Macke4be32f2014-03-11 20:45:25 -0400539 inlines = [SliceInline,UserInline,TagInline, NodeInline, SitePrivilegeInline, SiteDeploymentInline]
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400540 search_fields = ['name']
541
Tony Mack04062832013-05-10 08:22:44 -0400542 def queryset(self, request):
Tony Mack5b061472014-02-04 07:57:10 -0500543 #print dir(UserInline)
544 return Site.select_by_user(request.user)
Tony Mack04062832013-05-10 08:22:44 -0400545
Tony Mack5cd13202013-05-01 21:48:38 -0400546 def get_formsets(self, request, obj=None):
547 for inline in self.get_inline_instances(request, obj):
548 # hide MyInline in the add view
549 if obj is None:
550 continue
Tony Mack2bd5b412013-06-11 21:05:06 -0400551 if isinstance(inline, SliceInline):
552 inline.model.caller = request.user
553 yield inline.get_formset(request, obj)
554
555 def get_formsets(self, request, obj=None):
556 for inline in self.get_inline_instances(request, obj):
557 # hide MyInline in the add view
558 if obj is None:
559 continue
560 if isinstance(inline, SliverInline):
561 inline.model.caller = request.user
Tony Mack5cd13202013-05-01 21:48:38 -0400562 yield inline.get_formset(request, obj)
563
Scott Baker545db2a2013-12-09 18:44:43 -0800564 def accountLink(self, obj):
565 link_obj = obj.accounts.all()
566 if link_obj:
567 reverse_path = "admin:core_account_change"
568 url = reverse(reverse_path, args =(link_obj[0].id,))
569 return "<a href='%s'>%s</a>" % (url, "view billing details")
570 else:
571 return "no billing data for this site"
572 accountLink.allow_tags = True
573 accountLink.short_description = "Billing"
574
Tony Mack332ee1d2014-02-04 15:33:45 -0500575 def save_model(self, request, obj, form, change):
576 # update openstack connection to use this site/tenant
577 obj.save_by_user(request.user)
578
579 def delete_model(self, request, obj):
580 obj.delete_by_user(request.user)
581
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500582
Tony Mack9bcbe4f2013-04-29 08:13:27 -0400583class SitePrivilegeAdmin(PlanetStackBaseAdmin):
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500584 fieldList = ['user', 'site', 'role']
Tony Mack00d361f2013-04-28 10:28:42 -0400585 fieldsets = [
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500586 (None, {'fields': fieldList, 'classes':['collapse']})
Tony Mack00d361f2013-04-28 10:28:42 -0400587 ]
588 list_display = ('user', 'site', 'role')
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500589 user_readonly_fields = fieldList
590 user_readonly_inlines = []
Tony Mack00d361f2013-04-28 10:28:42 -0400591
Tony Mackc2835a92013-05-28 09:18:49 -0400592 def formfield_for_foreignkey(self, db_field, request, **kwargs):
593 if db_field.name == 'site':
594 if not request.user.is_admin:
595 # only show sites where user is an admin or pi
596 sites = set()
597 for site_privilege in SitePrivilege.objects.filer(user=request.user):
598 if site_privilege.role.role_type in ['admin', 'pi']:
599 sites.add(site_privilege.site)
600 kwargs['queryset'] = Site.objects.filter(site__in=list(sites))
601
602 if db_field.name == 'user':
603 if not request.user.is_admin:
604 # only show users from sites where caller has admin or pi role
605 roles = Role.objects.filter(role_type__in=['admin', 'pi'])
606 site_privileges = SitePrivilege.objects.filter(user=request.user).filter(role__in=roles)
607 sites = [site_privilege.site for site_privilege in site_privileges]
608 site_privileges = SitePrivilege.objects.filter(site__in=sites)
609 emails = [site_privilege.user.email for site_privilege in site_privileges]
610 users = User.objects.filter(email__in=emails)
611 kwargs['queryset'] = users
612
613 return super(SitePrivilegeAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)
614
Tony Mack04062832013-05-10 08:22:44 -0400615 def queryset(self, request):
616 # admins can see all privileges. Users can only see privileges at sites
Tony Mackc2835a92013-05-28 09:18:49 -0400617 # where they have the admin role or pi role.
Tony Mack04062832013-05-10 08:22:44 -0400618 qs = super(SitePrivilegeAdmin, self).queryset(request)
Tony Mack5b061472014-02-04 07:57:10 -0500619 #if not request.user.is_admin:
620 # roles = Role.objects.filter(role_type__in=['admin', 'pi'])
621 # site_privileges = SitePrivilege.objects.filter(user=request.user).filter(role__in=roles)
622 # login_bases = [site_privilege.site.login_base for site_privilege in site_privileges]
623 # sites = Site.objects.filter(login_base__in=login_bases)
624 # qs = qs.filter(site__in=sites)
Tony Mack04062832013-05-10 08:22:44 -0400625 return qs
626
Siobhan Tullyce652d02013-10-08 21:52:35 -0400627class SliceForm(forms.ModelForm):
628 class Meta:
629 model = Slice
630 widgets = {
631 'service': LinkedSelect
632 }
633
Tony Mack2bd5b412013-06-11 21:05:06 -0400634class SliceAdmin(PlanetStackBaseAdmin):
Siobhan Tullyce652d02013-10-08 21:52:35 -0400635 form = SliceForm
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500636 fieldList = ['name', 'site', 'serviceClass', 'enabled','description', 'service', 'slice_url']
637 fieldsets = [('Slice Details', {'fields': fieldList, 'classes':['suit-tab suit-tab-general']}),]
Siobhan Tully30fd4292013-05-10 08:59:56 -0400638 list_display = ('name', 'site','serviceClass', 'slice_url')
Siobhan Tully2d95e482013-09-06 10:56:06 -0400639 inlines = [SlicePrivilegeInline,SliverInline, TagInline, ReservationInline,SliceNetworkInline]
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400640
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500641 user_readonly_fields = fieldList
642 user_readonly_inlines = [SlicePrivilegeROInline,SliverROInline,TagROInline, ReservationROInline, SliceNetworkROInline]
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400643
644 suit_form_tabs =(('general', 'Slice Details'),
Siobhan Tully2d95e482013-09-06 10:56:06 -0400645 ('slicenetworks','Networks'),
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400646 ('sliceprivileges','Privileges'),
647 ('slivers','Slivers'),
648 ('tags','Tags'),
649 ('reservations','Reservations'),
650 )
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400651
Tony Mackc2835a92013-05-28 09:18:49 -0400652 def formfield_for_foreignkey(self, db_field, request, **kwargs):
653 if db_field.name == 'site':
Tony Mack5b061472014-02-04 07:57:10 -0500654 kwargs['queryset'] = Site.select_by_user(request.user)
655
Tony Mackc2835a92013-05-28 09:18:49 -0400656 return super(SliceAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)
657
Tony Mack04062832013-05-10 08:22:44 -0400658 def queryset(self, request):
659 # admins can see all keys. Users can only see slices they belong to.
Tony Mack5b061472014-02-04 07:57:10 -0500660 return Slice.select_by_user(request.user)
Tony Mack04062832013-05-10 08:22:44 -0400661
Tony Mack79748612013-05-01 14:52:03 -0400662 def get_formsets(self, request, obj=None):
663 for inline in self.get_inline_instances(request, obj):
664 # hide MyInline in the add view
665 if obj is None:
666 continue
Tony Mack2bd5b412013-06-11 21:05:06 -0400667 if isinstance(inline, SliverInline):
668 inline.model.caller = request.user
Tony Mack79748612013-05-01 14:52:03 -0400669 yield inline.get_formset(request, obj)
670
Tony Mack2bd5b412013-06-11 21:05:06 -0400671
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400672class SlicePrivilegeAdmin(PlanetStackBaseAdmin):
Tony Mack00d361f2013-04-28 10:28:42 -0400673 fieldsets = [
674 (None, {'fields': ['user', 'slice', 'role']})
675 ]
676 list_display = ('user', 'slice', 'role')
Tony Mack00d361f2013-04-28 10:28:42 -0400677
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500678 user_readonly_fields = ['user', 'slice', 'role']
679 user_readonly_inlines = []
680
Tony Mackc2835a92013-05-28 09:18:49 -0400681 def formfield_for_foreignkey(self, db_field, request, **kwargs):
682 if db_field.name == 'slice':
Tony Mack5b061472014-02-04 07:57:10 -0500683 kwargs['queryset'] = Slice.select_by_user(request.user)
Tony Mackc2835a92013-05-28 09:18:49 -0400684
685 if db_field.name == 'user':
Tony Mack5b061472014-02-04 07:57:10 -0500686 kwargs['queryset'] = User.select_by_user(request.user)
Tony Mackc2835a92013-05-28 09:18:49 -0400687
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400688 return super(SlicePrivilegeAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)
Tony Mackc2835a92013-05-28 09:18:49 -0400689
Tony Mack04062832013-05-10 08:22:44 -0400690 def queryset(self, request):
691 # admins can see all memberships. Users can only see memberships of
692 # slices where they have the admin role.
Tony Mack5b061472014-02-04 07:57:10 -0500693 return SlicePrivilege.select_by_user(request.user)
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400694
Tony Mack9bcbe4f2013-04-29 08:13:27 -0400695 def save_model(self, request, obj, form, change):
Tony Mack951dab42013-05-02 19:51:45 -0400696 # update openstack connection to use this site/tenant
697 auth = request.session.get('auth', {})
698 auth['tenant'] = obj.slice.name
699 obj.os_manager = OpenStackManager(auth=auth, caller=request.user)
Tony Mack9bcbe4f2013-04-29 08:13:27 -0400700 obj.save()
701
702 def delete_model(self, request, obj):
Tony Mack951dab42013-05-02 19:51:45 -0400703 # update openstack connection to use this site/tenant
704 auth = request.session.get('auth', {})
705 auth['tenant'] = obj.slice.name
706 obj.os_manager = OpenStackManager(auth=auth, caller=request.user)
Tony Mack9bcbe4f2013-04-29 08:13:27 -0400707 obj.delete()
708
Siobhan Tully567e3e62013-06-21 18:03:16 -0400709
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400710class ImageAdmin(PlanetStackBaseAdmin):
711
712 fieldsets = [('Image Details',
713 {'fields': ['image_id', 'name', 'disk_format', 'container_format'],
714 'classes': ['suit-tab suit-tab-general']})
715 ]
716
717 suit_form_tabs =(('general','Image Details'),('slivers','Slivers'))
718
719 inlines = [SliverInline]
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500720
721 user_readonly_fields = ['image_id', 'name', 'disk_format', 'container_format']
722 user_readonly_inlines = [SliverROInline]
723
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400724class NodeForm(forms.ModelForm):
725 class Meta:
726 widgets = {
727 'site': LinkedSelect,
728 'deployment': LinkedSelect
729 }
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400730
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500731class NodeAdmin(PlanetStackBaseAdmin):
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400732 form = NodeForm
Siobhan Tullybf1153a2013-05-27 20:53:48 -0400733 list_display = ('name', 'site', 'deployment')
734 list_filter = ('deployment',)
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500735
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400736 inlines = [TagInline,SliverInline]
737 fieldsets = [('Node Details', {'fields': ['name','site','deployment'], 'classes':['suit-tab suit-tab-details']})]
738
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500739 user_readonly_fields = ['name','site','deployment']
740 user_readonly_inlines = [TagInline,SliverInline]
741
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400742 suit_form_tabs =(('details','Node Details'),('slivers','Slivers'),('tags','Tags'))
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400743
Siobhan Tully567e3e62013-06-21 18:03:16 -0400744
Tony Mackd90cdbf2013-04-16 22:48:40 -0400745class SliverForm(forms.ModelForm):
746 class Meta:
Tony Mack1d6b85f2013-05-07 18:49:14 -0400747 model = Sliver
Tony Mackd90cdbf2013-04-16 22:48:40 -0400748 ip = forms.CharField(widget=PlainTextWidget)
Tony Mack18261812013-05-02 16:39:20 -0400749 instance_name = forms.CharField(widget=PlainTextWidget)
Tony Mackd90cdbf2013-04-16 22:48:40 -0400750 widgets = {
751 'ip': PlainTextWidget(),
Tony Mack18261812013-05-02 16:39:20 -0400752 'instance_name': PlainTextWidget(),
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400753 'slice': LinkedSelect,
754 'deploymentNetwork': LinkedSelect,
755 'node': LinkedSelect,
756 'image': LinkedSelect
Siobhan Tully53437282013-04-26 19:30:27 -0400757 }
Tony Mackd90cdbf2013-04-16 22:48:40 -0400758
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500759class TagAdmin(PlanetStackBaseAdmin):
Siobhan Tullyce652d02013-10-08 21:52:35 -0400760 list_display = ['service', 'name', 'value', 'content_type', 'content_object',]
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500761 user_readonly_fields = ['service', 'name', 'value', 'content_type', 'content_object',]
762 user_readonly_inlines = []
Siobhan Tullyd3515752013-06-21 16:34:53 -0400763
Tony Mack9bcbe4f2013-04-29 08:13:27 -0400764class SliverAdmin(PlanetStackBaseAdmin):
Tony Mackd90cdbf2013-04-16 22:48:40 -0400765 form = SliverForm
Tony Mackcdec0902013-04-15 00:38:49 -0400766 fieldsets = [
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400767 ('Sliver Details', {'fields': ['slice', 'deploymentNetwork', 'node', 'ip', 'instance_name', 'numberCores', 'image', ], 'classes': ['suit-tab suit-tab-general'], })
Tony Mackcdec0902013-04-15 00:38:49 -0400768 ]
Siobhan Tully5d7dc8d2013-07-02 13:17:33 -0400769 list_display = ['ip', 'instance_name', 'slice', 'numberCores', 'image', 'node', 'deploymentNetwork']
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400770
771 suit_form_tabs =(('general', 'Sliver Details'),
772 ('tags','Tags'),
773 )
774
Siobhan Tullyde5450d2013-06-21 11:35:33 -0400775 inlines = [TagInline]
Tony Mack53106f32013-04-27 16:43:01 -0400776
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500777 user_readonly_fields = ['slice', 'deploymentNetwork', 'node', 'ip', 'instance_name', 'numberCores', 'image']
778 user_readonly_inlines = [TagROInline]
779
Tony Mackc2835a92013-05-28 09:18:49 -0400780 def formfield_for_foreignkey(self, db_field, request, **kwargs):
781 if db_field.name == 'slice':
Tony Mack5b061472014-02-04 07:57:10 -0500782 kwargs['queryset'] = Slice.select_by_user(request.user)
Tony Mackc2835a92013-05-28 09:18:49 -0400783
784 return super(SliverAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)
785
Tony Mack04062832013-05-10 08:22:44 -0400786 def queryset(self, request):
787 # admins can see all slivers. Users can only see slivers of
788 # the slices they belong to.
Tony Mack5b061472014-02-04 07:57:10 -0500789 return Sliver.select_by_user(request.user)
790
Tony Mack04062832013-05-10 08:22:44 -0400791
Tony Mack1d6b85f2013-05-07 18:49:14 -0400792 def get_formsets(self, request, obj=None):
793 # make some fields read only if we are updating an existing record
794 if obj == None:
795 #self.readonly_fields = ('ip', 'instance_name')
796 self.readonly_fields = ()
797 else:
Tony Mack1e889462013-05-10 21:34:54 -0400798 self.readonly_fields = ()
799 #self.readonly_fields = ('ip', 'instance_name', 'slice', 'image', 'key')
Tony Mack1d6b85f2013-05-07 18:49:14 -0400800
801 for inline in self.get_inline_instances(request, obj):
802 # hide MyInline in the add view
803 if obj is None:
804 continue
Tony Mack53106f32013-04-27 16:43:01 -0400805
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500806 #def save_model(self, request, obj, form, change):
807 # # update openstack connection to use this site/tenant
808 # auth = request.session.get('auth', {})
809 # auth['tenant'] = obj.slice.name
810 # obj.os_manager = OpenStackManager(auth=auth, caller=request.user)
811 # obj.creator = request.user
812 # obj.save()
Tony Mack53106f32013-04-27 16:43:01 -0400813
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500814 #def delete_model(self, request, obj):
815 # # update openstack connection to use this site/tenant
816 # auth = request.session.get('auth', {})
817 # auth['tenant'] = obj.slice.name
818 # obj.os_manager = OpenStackManager(auth=auth, caller=request.user)
819 # obj.delete()
Tony Mackcdec0902013-04-15 00:38:49 -0400820
Siobhan Tully53437282013-04-26 19:30:27 -0400821class UserCreationForm(forms.ModelForm):
822 """A form for creating new users. Includes all the required
823 fields, plus a repeated password."""
824 password1 = forms.CharField(label='Password', widget=forms.PasswordInput)
825 password2 = forms.CharField(label='Password confirmation', widget=forms.PasswordInput)
826
827 class Meta:
Siobhan Tully30fd4292013-05-10 08:59:56 -0400828 model = User
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400829 fields = ('email', 'firstname', 'lastname', 'phone', 'public_key')
Siobhan Tully53437282013-04-26 19:30:27 -0400830
831 def clean_password2(self):
832 # Check that the two password entries match
833 password1 = self.cleaned_data.get("password1")
834 password2 = self.cleaned_data.get("password2")
835 if password1 and password2 and password1 != password2:
836 raise forms.ValidationError("Passwords don't match")
837 return password2
838
839 def save(self, commit=True):
840 # Save the provided password in hashed format
841 user = super(UserCreationForm, self).save(commit=False)
Tony Mackf9f4afb2013-05-01 21:02:12 -0400842 user.password = self.cleaned_data["password1"]
843 #user.set_password(self.cleaned_data["password1"])
Siobhan Tully53437282013-04-26 19:30:27 -0400844 if commit:
845 user.save()
846 return user
847
Siobhan Tully567e3e62013-06-21 18:03:16 -0400848
Siobhan Tully53437282013-04-26 19:30:27 -0400849class UserChangeForm(forms.ModelForm):
850 """A form for updating users. Includes all the fields on
851 the user, but replaces the password field with admin's
852 password hash display field.
853 """
Siobhan Tully63b7ba42014-01-12 10:35:11 -0500854 password = ReadOnlyPasswordHashField(label='Password',
855 help_text= '<a href=\"password/\">Change Password</a>.')
Siobhan Tully53437282013-04-26 19:30:27 -0400856
857 class Meta:
Siobhan Tully30fd4292013-05-10 08:59:56 -0400858 model = User
Siobhan Tully53437282013-04-26 19:30:27 -0400859
860 def clean_password(self):
861 # Regardless of what the user provides, return the initial value.
862 # This is done here, rather than on the field, because the
863 # field does not have access to the initial value
864 return self.initial["password"]
865
Tony Mack2bd5b412013-06-11 21:05:06 -0400866class UserAdmin(UserAdmin):
Siobhan Tully53437282013-04-26 19:30:27 -0400867 class Meta:
868 app_label = "core"
869
870 # The forms to add and change user instances
871 form = UserChangeForm
872 add_form = UserCreationForm
873
874 # The fields to be used in displaying the User model.
875 # These override the definitions on the base UserAdmin
876 # that reference specific fields on auth.User.
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500877 list_display = ('email', 'firstname', 'lastname', 'site', 'last_login')
Siobhan Tullyce652d02013-10-08 21:52:35 -0400878 #list_display = ('email', 'username','firstname', 'lastname', 'is_admin', 'last_login')
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500879 list_filter = ('site',)
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400880 inlines = [SlicePrivilegeInline,SitePrivilegeInline,DeploymentPrivilegeInline]
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500881
882 fieldListLoginDetails = ['email','site','password','is_readonly','is_amin','public_key']
883 fieldListContactInfo = ['firstname','lastname','phone','timezone']
884
Siobhan Tully53437282013-04-26 19:30:27 -0400885 fieldsets = (
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500886 ('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 -0400887 ('Contact Information', {'fields': ('firstname','lastname','phone', 'timezone'), 'classes':['suit-tab suit-tab-contact']}),
Siobhan Tully53437282013-04-26 19:30:27 -0400888 #('Important dates', {'fields': ('last_login',)}),
889 )
890 add_fieldsets = (
891 (None, {
892 'classes': ('wide',),
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500893 'fields': ('email', 'firstname', 'lastname', 'is_readonly', 'phone', 'public_key','password1', 'password2')}
Siobhan Tully53437282013-04-26 19:30:27 -0400894 ),
895 )
896 search_fields = ('email',)
897 ordering = ('email',)
898 filter_horizontal = ()
899
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500900 user_readonly_fields = fieldListLoginDetails
901 user_readonly_inlines = [SlicePrivilegeROInline,SitePrivilegeROInline,DeploymentPrivilegeROInline]
902
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400903 suit_form_tabs =(('general','Login Details'),('contact','Contact Information'),('sliceprivileges','Slice Privileges'),('siteprivileges','Site Privileges'),('deploymentprivileges','Deployment Privileges'))
904
Tony Mackc2835a92013-05-28 09:18:49 -0400905 def formfield_for_foreignkey(self, db_field, request, **kwargs):
906 if db_field.name == 'site':
Tony Mack5b061472014-02-04 07:57:10 -0500907 kwargs['queryset'] = Site.select_by_user(request.user)
Tony Mackc2835a92013-05-28 09:18:49 -0400908
909 return super(UserAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)
910
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500911 def has_add_permission(self, request, obj=None):
912 return (not self.__user_is_readonly(request))
913
914 def has_delete_permission(self, request, obj=None):
915 return (not self.__user_is_readonly(request))
916
917 def get_actions(self,request):
918 actions = super(UserAdmin,self).get_actions(request)
919
920 if self.__user_is_readonly(request):
921 if 'delete_selected' in actions:
922 del actions['delete_selected']
923
924 return actions
925
926 def change_view(self,request,object_id, extra_context=None):
927
928 if self.__user_is_readonly(request):
929 self.readonly_fields=self.user_readonly_fields
930 self.inlines = self.user_readonly_inlines
931 try:
932 return super(UserAdmin, self).change_view(request, object_id, extra_context=extra_context)
933 except PermissionDenied:
934 pass
935 if request.method == 'POST':
936 raise PermissionDenied
937 request.readonly = True
938 return super(UserAdmin, self).change_view(request, object_id, extra_context=extra_context)
939
940 def __user_is_readonly(self, request):
941 #groups = [x.name for x in request.user.groups.all() ]
942 #return "readonly" in groups
943 return request.user.isReadOnlyUser()
944
Tony Mack5b061472014-02-04 07:57:10 -0500945 def queryset(self, request):
946 return User.select_by_user(request.user)
947
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500948
949
950class ServiceResourceROInline(ReadOnlyTabularInline):
951 model = ServiceResource
952 extra = 0
953 fields = ['serviceClass', 'name', 'maxUnitsDeployment', 'maxUnitsNode', 'maxDuration', 'bucketInRate', 'bucketMaxSize', 'cost', 'calendarReservable']
954
Scott Baker0165fac2014-01-13 11:49:26 -0800955class ServiceResourceInline(PlStackTabularInline):
Scott Baker3de3e372013-05-10 16:50:44 -0700956 model = ServiceResource
957 extra = 0
958
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500959class ServiceClassAdmin(PlanetStackBaseAdmin):
Scott Baker3de3e372013-05-10 16:50:44 -0700960 list_display = ('name', 'commitment', 'membershipFee')
961 inlines = [ServiceResourceInline]
962
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500963 user_readonly_fields = ['name', 'commitment', 'membershipFee']
964 user_readonly_inlines = []
965
966class ReservedResourceROInline(ReadOnlyTabularInline):
967 model = ReservedResource
968 extra = 0
969 fields = ['sliver', 'resource','quantity','reservationSet']
970 suit_classes = 'suit-tab suit-tab-reservedresources'
971
Scott Baker0165fac2014-01-13 11:49:26 -0800972class ReservedResourceInline(PlStackTabularInline):
Scott Baker133c9212013-05-17 09:09:11 -0700973 model = ReservedResource
974 extra = 0
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400975 suit_classes = 'suit-tab suit-tab-reservedresources'
Scott Baker133c9212013-05-17 09:09:11 -0700976
977 def formfield_for_foreignkey(self, db_field, request=None, **kwargs):
978 field = super(ReservedResourceInline, self).formfield_for_foreignkey(db_field, request, **kwargs)
979
980 if db_field.name == 'resource':
981 # restrict resources to those that the slice's service class allows
982 if request._slice is not None:
983 field.queryset = field.queryset.filter(serviceClass = request._slice.serviceClass, calendarReservable=True)
984 if len(field.queryset) > 0:
985 field.initial = field.queryset.all()[0]
986 else:
987 field.queryset = field.queryset.none()
988 elif db_field.name == 'sliver':
989 # restrict slivers to those that belong to the slice
990 if request._slice is not None:
991 field.queryset = field.queryset.filter(slice = request._slice)
992 else:
993 field.queryset = field.queryset.none()
994
995 return field
996
Tony Mack5b061472014-02-04 07:57:10 -0500997 def queryset(self, request):
998 return ReservedResource.select_by_user(request.user)
999
Scott Baker133c9212013-05-17 09:09:11 -07001000class ReservationChangeForm(forms.ModelForm):
1001 class Meta:
1002 model = Reservation
Siobhan Tullybfd11dc2013-09-03 12:59:24 -04001003 widgets = {
1004 'slice' : LinkedSelect
1005 }
Scott Baker133c9212013-05-17 09:09:11 -07001006
1007class ReservationAddForm(forms.ModelForm):
1008 slice = forms.ModelChoiceField(queryset=Slice.objects.all(), widget=forms.Select(attrs={"onChange":"document.getElementById('id_refresh').value=1; submit()"}))
1009 refresh = forms.CharField(widget=forms.HiddenInput())
1010
1011 class Media:
1012 css = {'all': ('planetstack.css',)} # .field-refresh { display: none; }
1013
1014 def clean_slice(self):
1015 slice = self.cleaned_data.get("slice")
1016 x = ServiceResource.objects.filter(serviceClass = slice.serviceClass, calendarReservable=True)
1017 if len(x) == 0:
1018 raise forms.ValidationError("The slice you selected does not have a service class that allows reservations")
1019 return slice
1020
1021 class Meta:
1022 model = Reservation
Siobhan Tullybfd11dc2013-09-03 12:59:24 -04001023 widgets = {
1024 'slice' : LinkedSelect
1025 }
1026
Scott Baker133c9212013-05-17 09:09:11 -07001027
1028class ReservationAddRefreshForm(ReservationAddForm):
1029 """ This form is displayed when the Reservation Form receives an update
1030 from the Slice dropdown onChange handler. It doesn't validate the
1031 data and doesn't save the data. This will cause the form to be
1032 redrawn.
1033 """
1034
Scott Baker8737e5f2013-05-17 09:35:32 -07001035 """ don't validate anything other than slice """
1036 dont_validate_fields = ("startTime", "duration")
1037
Scott Baker133c9212013-05-17 09:09:11 -07001038 def full_clean(self):
1039 result = super(ReservationAddForm, self).full_clean()
Scott Baker8737e5f2013-05-17 09:35:32 -07001040
1041 for fieldname in self.dont_validate_fields:
1042 if fieldname in self._errors:
1043 del self._errors[fieldname]
1044
Scott Baker133c9212013-05-17 09:09:11 -07001045 return result
1046
1047 """ don't save anything """
1048 def is_valid(self):
1049 return False
1050
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001051class ReservationAdmin(PlanetStackBaseAdmin):
1052 fieldList = ['slice', 'startTime', 'duration']
1053 fieldsets = [('Reservation Details', {'fields': fieldList, 'classes': ['suit-tab suit-tab-general']})]
Scott Baker133c9212013-05-17 09:09:11 -07001054 list_display = ('startTime', 'duration')
Scott Baker133c9212013-05-17 09:09:11 -07001055 form = ReservationAddForm
1056
Siobhan Tullybfd11dc2013-09-03 12:59:24 -04001057 suit_form_tabs = (('general','Reservation Details'), ('reservedresources','Reserved Resources'))
1058
1059 inlines = [ReservedResourceInline]
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001060 user_readonly_inlines = [ReservedResourceROInline]
1061 user_readonly_fields = fieldList
Siobhan Tullybfd11dc2013-09-03 12:59:24 -04001062
Scott Baker133c9212013-05-17 09:09:11 -07001063 def add_view(self, request, form_url='', extra_context=None):
Scott Bakeracd45142013-05-19 16:19:16 -07001064 timezone.activate(request.user.timezone)
Scott Baker133c9212013-05-17 09:09:11 -07001065 request._refresh = False
1066 request._slice = None
1067 if request.method == 'POST':
Scott Baker8737e5f2013-05-17 09:35:32 -07001068 # "refresh" will be set to "1" if the form was submitted due to
1069 # a change in the Slice dropdown.
Scott Baker133c9212013-05-17 09:09:11 -07001070 if request.POST.get("refresh","1") == "1":
1071 request._refresh = True
1072 request.POST["refresh"] = "0"
Scott Baker8737e5f2013-05-17 09:35:32 -07001073
1074 # Keep track of the slice that was selected, so the
1075 # reservedResource inline can filter items for the slice.
Scott Baker133c9212013-05-17 09:09:11 -07001076 request._slice = request.POST.get("slice",None)
1077 if (request._slice is not None):
1078 request._slice = Slice.objects.get(id=request._slice)
1079
1080 result = super(ReservationAdmin, self).add_view(request, form_url, extra_context)
1081 return result
1082
Scott Bakeracd45142013-05-19 16:19:16 -07001083 def changelist_view(self, request, extra_context = None):
1084 timezone.activate(request.user.timezone)
1085 return super(ReservationAdmin, self).changelist_view(request, extra_context)
1086
Scott Baker133c9212013-05-17 09:09:11 -07001087 def get_form(self, request, obj=None, **kwargs):
Siobhan Tullyd3515752013-06-21 16:34:53 -04001088 request._obj_ = obj
1089 if obj is not None:
1090 # For changes, set request._slice to the slice already set in the
1091 # object.
1092 request._slice = obj.slice
1093 self.form = ReservationChangeForm
1094 else:
1095 if getattr(request, "_refresh", False):
1096 self.form = ReservationAddRefreshForm
1097 else:
1098 self.form = ReservationAddForm
1099 return super(ReservationAdmin, self).get_form(request, obj, **kwargs)
1100
Scott Baker133c9212013-05-17 09:09:11 -07001101 def get_readonly_fields(self, request, obj=None):
Siobhan Tullyd3515752013-06-21 16:34:53 -04001102 if (obj is not None):
1103 # Prevent slice from being changed after the reservation has been
1104 # created.
1105 return ['slice']
1106 else:
Scott Baker133c9212013-05-17 09:09:11 -07001107 return []
Scott Baker3de3e372013-05-10 16:50:44 -07001108
Tony Mack5b061472014-02-04 07:57:10 -05001109 def queryset(self, request):
1110 return Reservation.select_by_user(request.user)
1111
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001112class NetworkParameterTypeAdmin(PlanetStackBaseAdmin):
Scott Baker74d8e622013-07-29 16:04:22 -07001113 list_display = ("name", )
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001114 user_readonly_fields = ['name']
1115 user_readonly_inlines = []
Scott Baker74d8e622013-07-29 16:04:22 -07001116
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001117class RouterAdmin(PlanetStackBaseAdmin):
Scott Baker74d8e622013-07-29 16:04:22 -07001118 list_display = ("name", )
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001119 user_readonly_fields = ['name']
1120 user_readonly_inlines = []
1121
1122class RouterROInline(ReadOnlyTabularInline):
1123 model = Router.networks.through
1124 extra = 0
1125 verbose_name_plural = "Routers"
1126 verbose_name = "Router"
1127 suit_classes = 'suit-tab suit-tab-routers'
1128
1129 fields = ['name', 'owner', 'permittedNetworks', 'networks']
Scott Baker74d8e622013-07-29 16:04:22 -07001130
Scott Baker0165fac2014-01-13 11:49:26 -08001131class RouterInline(PlStackTabularInline):
Scott Baker74d8e622013-07-29 16:04:22 -07001132 model = Router.networks.through
1133 extra = 0
1134 verbose_name_plural = "Routers"
1135 verbose_name = "Router"
Siobhan Tully2d95e482013-09-06 10:56:06 -04001136 suit_classes = 'suit-tab suit-tab-routers'
Scott Baker74d8e622013-07-29 16:04:22 -07001137
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001138class NetworkParameterROInline(ReadOnlyTabularInline):
1139 model = NetworkParameter
1140 extra = 1
1141 verbose_name_plural = "Parameters"
1142 verbose_name = "Parameter"
1143 suit_classes = 'suit-tab suit-tab-netparams'
1144 fields = ['parameter', 'value', 'content_type', 'object_id', 'content_object']
1145
Scott Baker74d8e622013-07-29 16:04:22 -07001146class NetworkParameterInline(generic.GenericTabularInline):
Scott Baker74d8e622013-07-29 16:04:22 -07001147 model = NetworkParameter
1148 extra = 1
1149 verbose_name_plural = "Parameters"
1150 verbose_name = "Parameter"
Siobhan Tully2d95e482013-09-06 10:56:06 -04001151 suit_classes = 'suit-tab suit-tab-netparams'
Scott Baker74d8e622013-07-29 16:04:22 -07001152
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001153class NetworkSliversROInline(ReadOnlyTabularInline):
1154 fields = ['network', 'sliver', 'ip', 'port_id']
1155 model = NetworkSliver
1156 extra = 0
1157 verbose_name_plural = "Slivers"
1158 verbose_name = "Sliver"
1159 suit_classes = 'suit-tab suit-tab-networkslivers'
1160
Scott Baker0165fac2014-01-13 11:49:26 -08001161class NetworkSliversInline(PlStackTabularInline):
Scott Baker74d8e622013-07-29 16:04:22 -07001162 readonly_fields = ("ip", )
1163 model = NetworkSliver
Scott Baker874936e2014-01-13 18:15:34 -08001164 selflink_fieldname = "sliver"
Scott Baker74d8e622013-07-29 16:04:22 -07001165 extra = 0
1166 verbose_name_plural = "Slivers"
1167 verbose_name = "Sliver"
Siobhan Tully2d95e482013-09-06 10:56:06 -04001168 suit_classes = 'suit-tab suit-tab-networkslivers'
Scott Baker74d8e622013-07-29 16:04:22 -07001169
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001170class NetworkSlicesROInline(ReadOnlyTabularInline):
1171 model = NetworkSlice
1172 extra = 0
1173 verbose_name_plural = "Slices"
1174 verbose_name = "Slice"
1175 suit_classes = 'suit-tab suit-tab-networkslices'
1176 fields = ['network','slice']
1177
Scott Baker0165fac2014-01-13 11:49:26 -08001178class NetworkSlicesInline(PlStackTabularInline):
Scott Bakerd7d2a392013-08-06 08:57:30 -07001179 model = NetworkSlice
Scott Baker874936e2014-01-13 18:15:34 -08001180 selflink_fieldname = "slice"
Scott Bakerd7d2a392013-08-06 08:57:30 -07001181 extra = 0
1182 verbose_name_plural = "Slices"
1183 verbose_name = "Slice"
Siobhan Tully2d95e482013-09-06 10:56:06 -04001184 suit_classes = 'suit-tab suit-tab-networkslices'
Scott Bakerd7d2a392013-08-06 08:57:30 -07001185
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001186class NetworkAdmin(PlanetStackBaseAdmin):
Scott Baker74d8e622013-07-29 16:04:22 -07001187 list_display = ("name", "subnet", "ports", "labels")
1188 readonly_fields = ("subnet", )
Siobhan Tully2d95e482013-09-06 10:56:06 -04001189
Scott Bakerd7d2a392013-08-06 08:57:30 -07001190 inlines = [NetworkParameterInline, NetworkSliversInline, NetworkSlicesInline, RouterInline]
Scott Baker74d8e622013-07-29 16:04:22 -07001191
Siobhan Tully2d95e482013-09-06 10:56:06 -04001192 fieldsets = [
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001193 (None, {'fields': ['name','template','ports','labels','owner','guaranteedBandwidth', 'permitAllSlices','permittedSlices','network_id','router_id','subnet_id','subnet'], 'classes':['suit-tab suit-tab-general']}),]
1194
1195 user_readonly_fields = ['name','template','ports','labels','owner','guaranteedBandwidth', 'permitAllSlices','permittedSlices','network_id','router_id','subnet_id','subnet']
1196 user_readonly_inlines = [NetworkParameterROInline, NetworkSliversROInline, NetworkSlicesROInline, RouterROInline]
Siobhan Tully2d95e482013-09-06 10:56:06 -04001197
1198 suit_form_tabs =(
1199 ('general','Network Details'),
1200 ('netparams', 'Parameters'),
1201 ('networkslivers','Slivers'),
1202 ('networkslices','Slices'),
1203 ('routers','Routers'),
1204 )
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001205class NetworkTemplateAdmin(PlanetStackBaseAdmin):
Scott Baker74d8e622013-07-29 16:04:22 -07001206 list_display = ("name", "guaranteedBandwidth", "visibility")
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001207 user_readonly_fields = ["name", "guaranteedBandwidth", "visibility"]
1208 user_readonly_inlines = []
Scott Baker74d8e622013-07-29 16:04:22 -07001209
Tony Mack31c2b8f2013-04-26 20:01:42 -04001210# register a signal that caches the user's credentials when they log in
1211def cache_credentials(sender, user, request, **kwds):
1212 auth = {'username': request.POST['username'],
1213 'password': request.POST['password']}
1214 request.session['auth'] = auth
1215user_logged_in.connect(cache_credentials)
1216
Scott Baker15cddfa2013-12-09 13:45:19 -08001217def dollar_field(fieldName, short_description):
1218 def newFunc(self, obj):
1219 try:
1220 x= "$ %0.2f" % float(getattr(obj, fieldName, 0.0))
1221 except:
1222 x=getattr(obj, fieldName, 0.0)
1223 return x
1224 newFunc.short_description = short_description
1225 return newFunc
1226
1227def right_dollar_field(fieldName, short_description):
1228 def newFunc(self, obj):
1229 try:
1230 #x= '<div align=right style="width:6em">$ %0.2f</div>' % float(getattr(obj, fieldName, 0.0))
1231 x= '<div align=right>$ %0.2f</div>' % float(getattr(obj, fieldName, 0.0))
1232 except:
1233 x=getattr(obj, fieldName, 0.0)
1234 return x
1235 newFunc.short_description = short_description
1236 newFunc.allow_tags = True
1237 return newFunc
Scott Baker43105042013-12-06 23:23:36 -08001238
Scott Baker0165fac2014-01-13 11:49:26 -08001239class InvoiceChargeInline(PlStackTabularInline):
Scott Baker43105042013-12-06 23:23:36 -08001240 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 = ['account']
Scott Baker9cb88a22013-12-09 18:56:00 -08001245 fields = ["date", "kind", "state", "object", "coreHours", "dollar_amount", "slice"]
1246 readonly_fields = ["date", "kind", "state", "object", "coreHours", "dollar_amount", "slice"]
1247 can_delete = False
1248 max_num = 0
1249
1250 dollar_amount = right_dollar_field("amount", "Amount")
Scott Baker43105042013-12-06 23:23:36 -08001251
1252class InvoiceAdmin(admin.ModelAdmin):
1253 list_display = ("date", "account")
1254
1255 inlines = [InvoiceChargeInline]
1256
Scott Baker9cb88a22013-12-09 18:56:00 -08001257 fields = ["date", "account", "dollar_amount"]
1258 readonly_fields = ["date", "account", "dollar_amount"]
1259
1260 dollar_amount = dollar_field("amount", "Amount")
Scott Baker43105042013-12-06 23:23:36 -08001261
Scott Baker0165fac2014-01-13 11:49:26 -08001262class InvoiceInline(PlStackTabularInline):
Scott Baker15cddfa2013-12-09 13:45:19 -08001263 model = Invoice
1264 extra = 0
1265 verbose_name_plural = "Invoices"
1266 verbose_name = "Invoice"
Scott Baker0165fac2014-01-13 11:49:26 -08001267 fields = ["date", "dollar_amount"]
1268 readonly_fields = ["date", "dollar_amount"]
Scott Baker15cddfa2013-12-09 13:45:19 -08001269 suit_classes = 'suit-tab suit-tab-accountinvoice'
1270 can_delete=False
1271 max_num=0
1272
1273 dollar_amount = right_dollar_field("amount", "Amount")
1274
Scott Baker0165fac2014-01-13 11:49:26 -08001275class PendingChargeInline(PlStackTabularInline):
Scott Baker43105042013-12-06 23:23:36 -08001276 model = Charge
Scott Baker15cddfa2013-12-09 13:45:19 -08001277 extra = 0
Scott Baker43105042013-12-06 23:23:36 -08001278 verbose_name_plural = "Charges"
1279 verbose_name = "Charge"
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001280 exclude = ["invoice"]
Scott Baker15cddfa2013-12-09 13:45:19 -08001281 fields = ["date", "kind", "state", "object", "coreHours", "dollar_amount", "slice"]
1282 readonly_fields = ["date", "kind", "state", "object", "coreHours", "dollar_amount", "slice"]
Scott Baker43105042013-12-06 23:23:36 -08001283 suit_classes = 'suit-tab suit-tab-accountpendingcharges'
Scott Baker15cddfa2013-12-09 13:45:19 -08001284 can_delete=False
1285 max_num=0
Scott Baker43105042013-12-06 23:23:36 -08001286
1287 def queryset(self, request):
1288 qs = super(PendingChargeInline, self).queryset(request)
1289 qs = qs.filter(state="pending")
1290 return qs
1291
Scott Baker15cddfa2013-12-09 13:45:19 -08001292 dollar_amount = right_dollar_field("amount", "Amount")
1293
Scott Baker0165fac2014-01-13 11:49:26 -08001294class PaymentInline(PlStackTabularInline):
Scott Baker43105042013-12-06 23:23:36 -08001295 model=Payment
1296 extra = 1
1297 verbose_name_plural = "Payments"
1298 verbose_name = "Payment"
Scott Baker15cddfa2013-12-09 13:45:19 -08001299 fields = ["date", "dollar_amount"]
1300 readonly_fields = ["date", "dollar_amount"]
Scott Baker43105042013-12-06 23:23:36 -08001301 suit_classes = 'suit-tab suit-tab-accountpayments'
Scott Baker15cddfa2013-12-09 13:45:19 -08001302 can_delete=False
1303 max_num=0
1304
1305 dollar_amount = right_dollar_field("amount", "Amount")
1306
Scott Baker43105042013-12-06 23:23:36 -08001307class AccountAdmin(admin.ModelAdmin):
1308 list_display = ("site", "balance_due")
1309
1310 inlines = [InvoiceInline, PaymentInline, PendingChargeInline]
1311
1312 fieldsets = [
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001313 (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 -08001314
Scott Baker15cddfa2013-12-09 13:45:19 -08001315 readonly_fields = ['site', 'dollar_balance_due', 'dollar_total_invoices', 'dollar_total_payments']
Scott Baker43105042013-12-06 23:23:36 -08001316
1317 suit_form_tabs =(
1318 ('general','Account Details'),
1319 ('accountinvoice', 'Invoices'),
1320 ('accountpayments', 'Payments'),
1321 ('accountpendingcharges','Pending Charges'),
1322 )
1323
Scott Baker15cddfa2013-12-09 13:45:19 -08001324 dollar_balance_due = dollar_field("balance_due", "Balance Due")
1325 dollar_total_invoices = dollar_field("total_invoices", "Total Invoices")
1326 dollar_total_payments = dollar_field("total_payments", "Total Payments")
1327
Siobhan Tullyce652d02013-10-08 21:52:35 -04001328
Siobhan Tully53437282013-04-26 19:30:27 -04001329# Now register the new UserAdmin...
Siobhan Tully30fd4292013-05-10 08:59:56 -04001330admin.site.register(User, UserAdmin)
Siobhan Tully53437282013-04-26 19:30:27 -04001331# ... and, since we're not using Django's builtin permissions,
1332# unregister the Group model from admin.
Siobhan Tullyce652d02013-10-08 21:52:35 -04001333#admin.site.unregister(Group)
Siobhan Tully53437282013-04-26 19:30:27 -04001334
Siobhan Tullybf1153a2013-05-27 20:53:48 -04001335#Do not show django evolution in the admin interface
1336from django_evolution.models import Version, Evolution
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001337#admin.site.unregister(Version)
1338#admin.site.unregister(Evolution)
Siobhan Tullybf1153a2013-05-27 20:53:48 -04001339
1340
1341# When debugging it is often easier to see all the classes, but for regular use
1342# only the top-levels should be displayed
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001343showAll = False
Scott Baker43105042013-12-06 23:23:36 -08001344
Siobhan Tullybf1153a2013-05-27 20:53:48 -04001345admin.site.register(Deployment, DeploymentAdmin)
Siobhan Tully4bc09f22013-04-10 21:15:21 -04001346admin.site.register(Site, SiteAdmin)
Siobhan Tully4bc09f22013-04-10 21:15:21 -04001347admin.site.register(Slice, SliceAdmin)
Siobhan Tullyce652d02013-10-08 21:52:35 -04001348admin.site.register(Service, ServiceAdmin)
smbakera3cf70c2013-06-27 02:01:41 -07001349admin.site.register(Reservation, ReservationAdmin)
Scott Baker74d8e622013-07-29 16:04:22 -07001350admin.site.register(Network, NetworkAdmin)
1351admin.site.register(Router, RouterAdmin)
Scott Baker74d8e622013-07-29 16:04:22 -07001352admin.site.register(NetworkTemplate, NetworkTemplateAdmin)
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001353admin.site.register(Account, AccountAdmin)
1354admin.site.register(Invoice, InvoiceAdmin)
Siobhan Tullybf1153a2013-05-27 20:53:48 -04001355
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001356if True:
1357 admin.site.register(NetworkParameterType, NetworkParameterTypeAdmin)
1358 admin.site.register(ServiceClass, ServiceClassAdmin)
Siobhan Tullybfd11dc2013-09-03 12:59:24 -04001359 #admin.site.register(PlanetStack)
Siobhan Tullyd3515752013-06-21 16:34:53 -04001360 admin.site.register(Tag, TagAdmin)
Siobhan Tullyce652d02013-10-08 21:52:35 -04001361 admin.site.register(DeploymentRole)
1362 admin.site.register(SiteRole)
1363 admin.site.register(SliceRole)
1364 admin.site.register(PlanetStackRole)
Siobhan Tullybf1153a2013-05-27 20:53:48 -04001365 admin.site.register(Node, NodeAdmin)
Siobhan Tullybfd11dc2013-09-03 12:59:24 -04001366 #admin.site.register(SlicePrivilege, SlicePrivilegeAdmin)
1367 #admin.site.register(SitePrivilege, SitePrivilegeAdmin)
Siobhan Tullybf1153a2013-05-27 20:53:48 -04001368 admin.site.register(Sliver, SliverAdmin)
Siobhan Tullybf1153a2013-05-27 20:53:48 -04001369 admin.site.register(Image, ImageAdmin)
Tony Mack7130ac32013-03-22 21:58:00 -04001370