blob: 3875477f39e21d1791df4b50e0879b006d5a3c9b [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:
Tony Mackdd06ca82014-03-26 08:10:14 -0400461 self.fields['sites'].initial = self.instance.site_set.all()
Siobhan Tully320b4622014-01-17 15:11:14 -0500462 self.fields['sites'].initial = self.instance.sites.all()
463
464 def save(self, commit=True):
465 deployment = super(DeploymentAdminForm, self).save(commit=False)
466
467 if commit:
468 deployment.save()
469
470 if deployment.pk:
471 deployment.sites = self.cleaned_data['sites']
472 self.save_m2m()
473
474 return deployment
475
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500476class SiteAssocInline(PlStackTabularInline):
477 model = Site.deployments.through
478 extra = 0
479 suit_classes = 'suit-tab suit-tab-sites'
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400480
Siobhan Tullybf1153a2013-05-27 20:53:48 -0400481class DeploymentAdmin(PlanetStackBaseAdmin):
482 form = DeploymentAdminForm
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500483 model = Deployment
484 fieldList = ['name','sites']
485 fieldsets = [(None, {'fields': fieldList, 'classes':['suit-tab suit-tab-sites']})]
Siobhan Tully2d95e482013-09-06 10:56:06 -0400486 inlines = [DeploymentPrivilegeInline,NodeInline,TagInline]
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500487
488 user_readonly_inlines = [DeploymentPrivilegeROInline,NodeROInline,TagROInline]
489 user_readonly_fields = ['name']
490
491 suit_form_tabs =(('sites','Deployment Details'),('nodes','Nodes'),('deploymentprivileges','Privileges'),('tags','Tags'))
492
493class ServiceAttrAsTabROInline(ReadOnlyTabularInline):
494 model = ServiceAttribute
495 fields = ['name','value']
496 extra = 0
497 suit_classes = 'suit-tab suit-tab-serviceattrs'
Tony Mack5cd13202013-05-01 21:48:38 -0400498
Siobhan Tullyce652d02013-10-08 21:52:35 -0400499class ServiceAttrAsTabInline(PlStackTabularInline):
500 model = ServiceAttribute
501 fields = ['name','value']
502 extra = 0
503 suit_classes = 'suit-tab suit-tab-serviceattrs'
504
Siobhan Tullyce652d02013-10-08 21:52:35 -0400505class ServiceAdmin(PlanetStackBaseAdmin):
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500506 list_display = ("name","description","versionNumber","enabled","published")
507 fieldList = ["name","description","versionNumber","enabled","published"]
508 fieldsets = [(None, {'fields': fieldList, 'classes':['suit-tab suit-tab-general']})]
509 inlines = [ServiceAttrAsTabInline,SliceInline]
510
511 user_readonly_fields = fieldList
512 user_readonly_inlines = [ServiceAttrAsTabROInline,SliceROInline]
513
514 suit_form_tabs =(('general', 'Service Details'),
515 ('slices','Slices'),
516 ('serviceattrs','Additional Attributes'),
517 )
Siobhan Tullyce652d02013-10-08 21:52:35 -0400518
Tony Mack0553f282013-06-10 22:54:50 -0400519class SiteAdmin(PlanetStackBaseAdmin):
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500520 fieldList = ['name', 'site_url', 'enabled', 'is_public', 'login_base', 'accountLink','location']
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400521 fieldsets = [
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500522 (None, {'fields': fieldList, 'classes':['suit-tab suit-tab-general']}),
Tony Macke4be32f2014-03-11 20:45:25 -0400523 #('Deployment Networks', {'fields': ['deployments'], 'classes':['suit-tab suit-tab-deployments']}),
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400524 ]
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400525 suit_form_tabs =(('general', 'Site Details'),
526 ('users','Users'),
Siobhan Tully2d95e482013-09-06 10:56:06 -0400527 ('siteprivileges','Privileges'),
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400528 ('deployments','Deployments'),
529 ('slices','Slices'),
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500530 ('nodes','Nodes'),
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400531 ('tags','Tags'),
532 )
Scott Baker545db2a2013-12-09 18:44:43 -0800533 readonly_fields = ['accountLink']
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500534
535 user_readonly_fields = ['name', 'deployments','site_url', 'enabled', 'is_public', 'login_base', 'accountLink']
Tony Macke4be32f2014-03-11 20:45:25 -0400536 user_readonly_inlines = [SliceROInline,UserROInline,TagROInline, NodeROInline, SitePrivilegeROInline,SiteDeploymentROInline]
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500537
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400538 list_display = ('name', 'login_base','site_url', 'enabled')
539 filter_horizontal = ('deployments',)
Tony Macke4be32f2014-03-11 20:45:25 -0400540 inlines = [SliceInline,UserInline,TagInline, NodeInline, SitePrivilegeInline, SiteDeploymentInline]
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400541 search_fields = ['name']
542
Tony Mack04062832013-05-10 08:22:44 -0400543 def queryset(self, request):
Tony Mack5b061472014-02-04 07:57:10 -0500544 #print dir(UserInline)
545 return Site.select_by_user(request.user)
Tony Mack04062832013-05-10 08:22:44 -0400546
Tony Mack5cd13202013-05-01 21:48:38 -0400547 def get_formsets(self, request, obj=None):
548 for inline in self.get_inline_instances(request, obj):
549 # hide MyInline in the add view
550 if obj is None:
551 continue
Tony Mack2bd5b412013-06-11 21:05:06 -0400552 if isinstance(inline, SliceInline):
553 inline.model.caller = request.user
554 yield inline.get_formset(request, obj)
555
556 def get_formsets(self, request, obj=None):
557 for inline in self.get_inline_instances(request, obj):
558 # hide MyInline in the add view
559 if obj is None:
560 continue
561 if isinstance(inline, SliverInline):
562 inline.model.caller = request.user
Tony Mack5cd13202013-05-01 21:48:38 -0400563 yield inline.get_formset(request, obj)
564
Scott Baker545db2a2013-12-09 18:44:43 -0800565 def accountLink(self, obj):
566 link_obj = obj.accounts.all()
567 if link_obj:
568 reverse_path = "admin:core_account_change"
569 url = reverse(reverse_path, args =(link_obj[0].id,))
570 return "<a href='%s'>%s</a>" % (url, "view billing details")
571 else:
572 return "no billing data for this site"
573 accountLink.allow_tags = True
574 accountLink.short_description = "Billing"
575
Tony Mack332ee1d2014-02-04 15:33:45 -0500576 def save_model(self, request, obj, form, change):
577 # update openstack connection to use this site/tenant
578 obj.save_by_user(request.user)
579
580 def delete_model(self, request, obj):
581 obj.delete_by_user(request.user)
582
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500583
Tony Mack9bcbe4f2013-04-29 08:13:27 -0400584class SitePrivilegeAdmin(PlanetStackBaseAdmin):
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500585 fieldList = ['user', 'site', 'role']
Tony Mack00d361f2013-04-28 10:28:42 -0400586 fieldsets = [
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500587 (None, {'fields': fieldList, 'classes':['collapse']})
Tony Mack00d361f2013-04-28 10:28:42 -0400588 ]
589 list_display = ('user', 'site', 'role')
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500590 user_readonly_fields = fieldList
591 user_readonly_inlines = []
Tony Mack00d361f2013-04-28 10:28:42 -0400592
Tony Mackc2835a92013-05-28 09:18:49 -0400593 def formfield_for_foreignkey(self, db_field, request, **kwargs):
594 if db_field.name == 'site':
595 if not request.user.is_admin:
596 # only show sites where user is an admin or pi
597 sites = set()
598 for site_privilege in SitePrivilege.objects.filer(user=request.user):
599 if site_privilege.role.role_type in ['admin', 'pi']:
600 sites.add(site_privilege.site)
601 kwargs['queryset'] = Site.objects.filter(site__in=list(sites))
602
603 if db_field.name == 'user':
604 if not request.user.is_admin:
605 # only show users from sites where caller has admin or pi role
606 roles = Role.objects.filter(role_type__in=['admin', 'pi'])
607 site_privileges = SitePrivilege.objects.filter(user=request.user).filter(role__in=roles)
608 sites = [site_privilege.site for site_privilege in site_privileges]
609 site_privileges = SitePrivilege.objects.filter(site__in=sites)
610 emails = [site_privilege.user.email for site_privilege in site_privileges]
611 users = User.objects.filter(email__in=emails)
612 kwargs['queryset'] = users
613
614 return super(SitePrivilegeAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)
615
Tony Mack04062832013-05-10 08:22:44 -0400616 def queryset(self, request):
617 # admins can see all privileges. Users can only see privileges at sites
Tony Mackc2835a92013-05-28 09:18:49 -0400618 # where they have the admin role or pi role.
Tony Mack04062832013-05-10 08:22:44 -0400619 qs = super(SitePrivilegeAdmin, self).queryset(request)
Tony Mack5b061472014-02-04 07:57:10 -0500620 #if not request.user.is_admin:
621 # roles = Role.objects.filter(role_type__in=['admin', 'pi'])
622 # site_privileges = SitePrivilege.objects.filter(user=request.user).filter(role__in=roles)
623 # login_bases = [site_privilege.site.login_base for site_privilege in site_privileges]
624 # sites = Site.objects.filter(login_base__in=login_bases)
625 # qs = qs.filter(site__in=sites)
Tony Mack04062832013-05-10 08:22:44 -0400626 return qs
627
Siobhan Tullyce652d02013-10-08 21:52:35 -0400628class SliceForm(forms.ModelForm):
629 class Meta:
630 model = Slice
631 widgets = {
632 'service': LinkedSelect
633 }
634
Tony Mack2bd5b412013-06-11 21:05:06 -0400635class SliceAdmin(PlanetStackBaseAdmin):
Siobhan Tullyce652d02013-10-08 21:52:35 -0400636 form = SliceForm
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500637 fieldList = ['name', 'site', 'serviceClass', 'enabled','description', 'service', 'slice_url']
638 fieldsets = [('Slice Details', {'fields': fieldList, 'classes':['suit-tab suit-tab-general']}),]
Siobhan Tully30fd4292013-05-10 08:59:56 -0400639 list_display = ('name', 'site','serviceClass', 'slice_url')
Siobhan Tully2d95e482013-09-06 10:56:06 -0400640 inlines = [SlicePrivilegeInline,SliverInline, TagInline, ReservationInline,SliceNetworkInline]
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400641
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500642 user_readonly_fields = fieldList
643 user_readonly_inlines = [SlicePrivilegeROInline,SliverROInline,TagROInline, ReservationROInline, SliceNetworkROInline]
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400644
645 suit_form_tabs =(('general', 'Slice Details'),
Siobhan Tully2d95e482013-09-06 10:56:06 -0400646 ('slicenetworks','Networks'),
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400647 ('sliceprivileges','Privileges'),
648 ('slivers','Slivers'),
649 ('tags','Tags'),
650 ('reservations','Reservations'),
651 )
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400652
Tony Mackc2835a92013-05-28 09:18:49 -0400653 def formfield_for_foreignkey(self, db_field, request, **kwargs):
654 if db_field.name == 'site':
Tony Mack5b061472014-02-04 07:57:10 -0500655 kwargs['queryset'] = Site.select_by_user(request.user)
656
Tony Mackc2835a92013-05-28 09:18:49 -0400657 return super(SliceAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)
658
Tony Mack04062832013-05-10 08:22:44 -0400659 def queryset(self, request):
660 # admins can see all keys. Users can only see slices they belong to.
Tony Mack5b061472014-02-04 07:57:10 -0500661 return Slice.select_by_user(request.user)
Tony Mack04062832013-05-10 08:22:44 -0400662
Tony Mack79748612013-05-01 14:52:03 -0400663 def get_formsets(self, request, obj=None):
664 for inline in self.get_inline_instances(request, obj):
665 # hide MyInline in the add view
666 if obj is None:
667 continue
Tony Mack2bd5b412013-06-11 21:05:06 -0400668 if isinstance(inline, SliverInline):
669 inline.model.caller = request.user
Tony Mack79748612013-05-01 14:52:03 -0400670 yield inline.get_formset(request, obj)
671
Tony Mack2bd5b412013-06-11 21:05:06 -0400672
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400673class SlicePrivilegeAdmin(PlanetStackBaseAdmin):
Tony Mack00d361f2013-04-28 10:28:42 -0400674 fieldsets = [
675 (None, {'fields': ['user', 'slice', 'role']})
676 ]
677 list_display = ('user', 'slice', 'role')
Tony Mack00d361f2013-04-28 10:28:42 -0400678
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500679 user_readonly_fields = ['user', 'slice', 'role']
680 user_readonly_inlines = []
681
Tony Mackc2835a92013-05-28 09:18:49 -0400682 def formfield_for_foreignkey(self, db_field, request, **kwargs):
683 if db_field.name == 'slice':
Tony Mack5b061472014-02-04 07:57:10 -0500684 kwargs['queryset'] = Slice.select_by_user(request.user)
Tony Mackc2835a92013-05-28 09:18:49 -0400685
686 if db_field.name == 'user':
Tony Mack5b061472014-02-04 07:57:10 -0500687 kwargs['queryset'] = User.select_by_user(request.user)
Tony Mackc2835a92013-05-28 09:18:49 -0400688
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400689 return super(SlicePrivilegeAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)
Tony Mackc2835a92013-05-28 09:18:49 -0400690
Tony Mack04062832013-05-10 08:22:44 -0400691 def queryset(self, request):
692 # admins can see all memberships. Users can only see memberships of
693 # slices where they have the admin role.
Tony Mack5b061472014-02-04 07:57:10 -0500694 return SlicePrivilege.select_by_user(request.user)
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400695
Tony Mack9bcbe4f2013-04-29 08:13:27 -0400696 def save_model(self, request, obj, form, change):
Tony Mack951dab42013-05-02 19:51:45 -0400697 # update openstack connection to use this site/tenant
698 auth = request.session.get('auth', {})
699 auth['tenant'] = obj.slice.name
700 obj.os_manager = OpenStackManager(auth=auth, caller=request.user)
Tony Mack9bcbe4f2013-04-29 08:13:27 -0400701 obj.save()
702
703 def delete_model(self, request, obj):
Tony Mack951dab42013-05-02 19:51:45 -0400704 # update openstack connection to use this site/tenant
705 auth = request.session.get('auth', {})
706 auth['tenant'] = obj.slice.name
707 obj.os_manager = OpenStackManager(auth=auth, caller=request.user)
Tony Mack9bcbe4f2013-04-29 08:13:27 -0400708 obj.delete()
709
Siobhan Tully567e3e62013-06-21 18:03:16 -0400710
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400711class ImageAdmin(PlanetStackBaseAdmin):
712
713 fieldsets = [('Image Details',
714 {'fields': ['image_id', 'name', 'disk_format', 'container_format'],
715 'classes': ['suit-tab suit-tab-general']})
716 ]
717
718 suit_form_tabs =(('general','Image Details'),('slivers','Slivers'))
719
720 inlines = [SliverInline]
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500721
722 user_readonly_fields = ['image_id', 'name', 'disk_format', 'container_format']
723 user_readonly_inlines = [SliverROInline]
724
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400725class NodeForm(forms.ModelForm):
726 class Meta:
727 widgets = {
728 'site': LinkedSelect,
729 'deployment': LinkedSelect
730 }
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400731
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500732class NodeAdmin(PlanetStackBaseAdmin):
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400733 form = NodeForm
Siobhan Tullybf1153a2013-05-27 20:53:48 -0400734 list_display = ('name', 'site', 'deployment')
735 list_filter = ('deployment',)
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500736
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400737 inlines = [TagInline,SliverInline]
738 fieldsets = [('Node Details', {'fields': ['name','site','deployment'], 'classes':['suit-tab suit-tab-details']})]
739
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500740 user_readonly_fields = ['name','site','deployment']
741 user_readonly_inlines = [TagInline,SliverInline]
742
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400743 suit_form_tabs =(('details','Node Details'),('slivers','Slivers'),('tags','Tags'))
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400744
Siobhan Tully567e3e62013-06-21 18:03:16 -0400745
Tony Mackd90cdbf2013-04-16 22:48:40 -0400746class SliverForm(forms.ModelForm):
747 class Meta:
Tony Mack1d6b85f2013-05-07 18:49:14 -0400748 model = Sliver
Tony Mackd90cdbf2013-04-16 22:48:40 -0400749 ip = forms.CharField(widget=PlainTextWidget)
Tony Mack18261812013-05-02 16:39:20 -0400750 instance_name = forms.CharField(widget=PlainTextWidget)
Tony Mackd90cdbf2013-04-16 22:48:40 -0400751 widgets = {
752 'ip': PlainTextWidget(),
Tony Mack18261812013-05-02 16:39:20 -0400753 'instance_name': PlainTextWidget(),
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400754 'slice': LinkedSelect,
755 'deploymentNetwork': LinkedSelect,
756 'node': LinkedSelect,
757 'image': LinkedSelect
Siobhan Tully53437282013-04-26 19:30:27 -0400758 }
Tony Mackd90cdbf2013-04-16 22:48:40 -0400759
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500760class TagAdmin(PlanetStackBaseAdmin):
Siobhan Tullyce652d02013-10-08 21:52:35 -0400761 list_display = ['service', 'name', 'value', 'content_type', 'content_object',]
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500762 user_readonly_fields = ['service', 'name', 'value', 'content_type', 'content_object',]
763 user_readonly_inlines = []
Siobhan Tullyd3515752013-06-21 16:34:53 -0400764
Tony Mack9bcbe4f2013-04-29 08:13:27 -0400765class SliverAdmin(PlanetStackBaseAdmin):
Tony Mackd90cdbf2013-04-16 22:48:40 -0400766 form = SliverForm
Tony Mackcdec0902013-04-15 00:38:49 -0400767 fieldsets = [
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400768 ('Sliver Details', {'fields': ['slice', 'deploymentNetwork', 'node', 'ip', 'instance_name', 'numberCores', 'image', ], 'classes': ['suit-tab suit-tab-general'], })
Tony Mackcdec0902013-04-15 00:38:49 -0400769 ]
Siobhan Tully5d7dc8d2013-07-02 13:17:33 -0400770 list_display = ['ip', 'instance_name', 'slice', 'numberCores', 'image', 'node', 'deploymentNetwork']
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400771
772 suit_form_tabs =(('general', 'Sliver Details'),
773 ('tags','Tags'),
774 )
775
Siobhan Tullyde5450d2013-06-21 11:35:33 -0400776 inlines = [TagInline]
Tony Mack53106f32013-04-27 16:43:01 -0400777
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500778 user_readonly_fields = ['slice', 'deploymentNetwork', 'node', 'ip', 'instance_name', 'numberCores', 'image']
779 user_readonly_inlines = [TagROInline]
780
Tony Mackc2835a92013-05-28 09:18:49 -0400781 def formfield_for_foreignkey(self, db_field, request, **kwargs):
782 if db_field.name == 'slice':
Tony Mack5b061472014-02-04 07:57:10 -0500783 kwargs['queryset'] = Slice.select_by_user(request.user)
Tony Mackc2835a92013-05-28 09:18:49 -0400784
785 return super(SliverAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)
786
Tony Mack04062832013-05-10 08:22:44 -0400787 def queryset(self, request):
788 # admins can see all slivers. Users can only see slivers of
789 # the slices they belong to.
Tony Mack5b061472014-02-04 07:57:10 -0500790 return Sliver.select_by_user(request.user)
791
Tony Mack04062832013-05-10 08:22:44 -0400792
Tony Mack1d6b85f2013-05-07 18:49:14 -0400793 def get_formsets(self, request, obj=None):
794 # make some fields read only if we are updating an existing record
795 if obj == None:
796 #self.readonly_fields = ('ip', 'instance_name')
797 self.readonly_fields = ()
798 else:
Tony Mack1e889462013-05-10 21:34:54 -0400799 self.readonly_fields = ()
800 #self.readonly_fields = ('ip', 'instance_name', 'slice', 'image', 'key')
Tony Mack1d6b85f2013-05-07 18:49:14 -0400801
802 for inline in self.get_inline_instances(request, obj):
803 # hide MyInline in the add view
804 if obj is None:
805 continue
Tony Mack53106f32013-04-27 16:43:01 -0400806
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500807 #def save_model(self, request, obj, form, change):
808 # # update openstack connection to use this site/tenant
809 # auth = request.session.get('auth', {})
810 # auth['tenant'] = obj.slice.name
811 # obj.os_manager = OpenStackManager(auth=auth, caller=request.user)
812 # obj.creator = request.user
813 # obj.save()
Tony Mack53106f32013-04-27 16:43:01 -0400814
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500815 #def delete_model(self, request, obj):
816 # # update openstack connection to use this site/tenant
817 # auth = request.session.get('auth', {})
818 # auth['tenant'] = obj.slice.name
819 # obj.os_manager = OpenStackManager(auth=auth, caller=request.user)
820 # obj.delete()
Tony Mackcdec0902013-04-15 00:38:49 -0400821
Siobhan Tully53437282013-04-26 19:30:27 -0400822class UserCreationForm(forms.ModelForm):
823 """A form for creating new users. Includes all the required
824 fields, plus a repeated password."""
825 password1 = forms.CharField(label='Password', widget=forms.PasswordInput)
826 password2 = forms.CharField(label='Password confirmation', widget=forms.PasswordInput)
827
828 class Meta:
Siobhan Tully30fd4292013-05-10 08:59:56 -0400829 model = User
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400830 fields = ('email', 'firstname', 'lastname', 'phone', 'public_key')
Siobhan Tully53437282013-04-26 19:30:27 -0400831
832 def clean_password2(self):
833 # Check that the two password entries match
834 password1 = self.cleaned_data.get("password1")
835 password2 = self.cleaned_data.get("password2")
836 if password1 and password2 and password1 != password2:
837 raise forms.ValidationError("Passwords don't match")
838 return password2
839
840 def save(self, commit=True):
841 # Save the provided password in hashed format
842 user = super(UserCreationForm, self).save(commit=False)
Tony Mackf9f4afb2013-05-01 21:02:12 -0400843 user.password = self.cleaned_data["password1"]
844 #user.set_password(self.cleaned_data["password1"])
Siobhan Tully53437282013-04-26 19:30:27 -0400845 if commit:
846 user.save()
847 return user
848
Siobhan Tully567e3e62013-06-21 18:03:16 -0400849
Siobhan Tully53437282013-04-26 19:30:27 -0400850class UserChangeForm(forms.ModelForm):
851 """A form for updating users. Includes all the fields on
852 the user, but replaces the password field with admin's
853 password hash display field.
854 """
Siobhan Tully63b7ba42014-01-12 10:35:11 -0500855 password = ReadOnlyPasswordHashField(label='Password',
856 help_text= '<a href=\"password/\">Change Password</a>.')
Siobhan Tully53437282013-04-26 19:30:27 -0400857
858 class Meta:
Siobhan Tully30fd4292013-05-10 08:59:56 -0400859 model = User
Siobhan Tully53437282013-04-26 19:30:27 -0400860
861 def clean_password(self):
862 # Regardless of what the user provides, return the initial value.
863 # This is done here, rather than on the field, because the
864 # field does not have access to the initial value
865 return self.initial["password"]
866
Tony Mack2bd5b412013-06-11 21:05:06 -0400867class UserAdmin(UserAdmin):
Siobhan Tully53437282013-04-26 19:30:27 -0400868 class Meta:
869 app_label = "core"
870
871 # The forms to add and change user instances
872 form = UserChangeForm
873 add_form = UserCreationForm
874
875 # The fields to be used in displaying the User model.
876 # These override the definitions on the base UserAdmin
877 # that reference specific fields on auth.User.
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500878 list_display = ('email', 'firstname', 'lastname', 'site', 'last_login')
Siobhan Tullyce652d02013-10-08 21:52:35 -0400879 #list_display = ('email', 'username','firstname', 'lastname', 'is_admin', 'last_login')
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500880 list_filter = ('site',)
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400881 inlines = [SlicePrivilegeInline,SitePrivilegeInline,DeploymentPrivilegeInline]
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500882
883 fieldListLoginDetails = ['email','site','password','is_readonly','is_amin','public_key']
884 fieldListContactInfo = ['firstname','lastname','phone','timezone']
885
Siobhan Tully53437282013-04-26 19:30:27 -0400886 fieldsets = (
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500887 ('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 -0400888 ('Contact Information', {'fields': ('firstname','lastname','phone', 'timezone'), 'classes':['suit-tab suit-tab-contact']}),
Siobhan Tully53437282013-04-26 19:30:27 -0400889 #('Important dates', {'fields': ('last_login',)}),
890 )
891 add_fieldsets = (
892 (None, {
893 'classes': ('wide',),
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500894 'fields': ('email', 'firstname', 'lastname', 'is_readonly', 'phone', 'public_key','password1', 'password2')}
Siobhan Tully53437282013-04-26 19:30:27 -0400895 ),
896 )
897 search_fields = ('email',)
898 ordering = ('email',)
899 filter_horizontal = ()
900
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500901 user_readonly_fields = fieldListLoginDetails
902 user_readonly_inlines = [SlicePrivilegeROInline,SitePrivilegeROInline,DeploymentPrivilegeROInline]
903
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400904 suit_form_tabs =(('general','Login Details'),('contact','Contact Information'),('sliceprivileges','Slice Privileges'),('siteprivileges','Site Privileges'),('deploymentprivileges','Deployment Privileges'))
905
Tony Mackc2835a92013-05-28 09:18:49 -0400906 def formfield_for_foreignkey(self, db_field, request, **kwargs):
907 if db_field.name == 'site':
Tony Mack5b061472014-02-04 07:57:10 -0500908 kwargs['queryset'] = Site.select_by_user(request.user)
Tony Mackc2835a92013-05-28 09:18:49 -0400909
910 return super(UserAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)
911
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500912 def has_add_permission(self, request, obj=None):
913 return (not self.__user_is_readonly(request))
914
915 def has_delete_permission(self, request, obj=None):
916 return (not self.__user_is_readonly(request))
917
918 def get_actions(self,request):
919 actions = super(UserAdmin,self).get_actions(request)
920
921 if self.__user_is_readonly(request):
922 if 'delete_selected' in actions:
923 del actions['delete_selected']
924
925 return actions
926
927 def change_view(self,request,object_id, extra_context=None):
928
929 if self.__user_is_readonly(request):
930 self.readonly_fields=self.user_readonly_fields
931 self.inlines = self.user_readonly_inlines
932 try:
933 return super(UserAdmin, self).change_view(request, object_id, extra_context=extra_context)
934 except PermissionDenied:
935 pass
936 if request.method == 'POST':
937 raise PermissionDenied
938 request.readonly = True
939 return super(UserAdmin, self).change_view(request, object_id, extra_context=extra_context)
940
941 def __user_is_readonly(self, request):
942 #groups = [x.name for x in request.user.groups.all() ]
943 #return "readonly" in groups
944 return request.user.isReadOnlyUser()
945
Tony Mack5b061472014-02-04 07:57:10 -0500946 def queryset(self, request):
947 return User.select_by_user(request.user)
948
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500949
950
951class ServiceResourceROInline(ReadOnlyTabularInline):
952 model = ServiceResource
953 extra = 0
954 fields = ['serviceClass', 'name', 'maxUnitsDeployment', 'maxUnitsNode', 'maxDuration', 'bucketInRate', 'bucketMaxSize', 'cost', 'calendarReservable']
955
Scott Baker0165fac2014-01-13 11:49:26 -0800956class ServiceResourceInline(PlStackTabularInline):
Scott Baker3de3e372013-05-10 16:50:44 -0700957 model = ServiceResource
958 extra = 0
959
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500960class ServiceClassAdmin(PlanetStackBaseAdmin):
Scott Baker3de3e372013-05-10 16:50:44 -0700961 list_display = ('name', 'commitment', 'membershipFee')
962 inlines = [ServiceResourceInline]
963
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500964 user_readonly_fields = ['name', 'commitment', 'membershipFee']
965 user_readonly_inlines = []
966
967class ReservedResourceROInline(ReadOnlyTabularInline):
968 model = ReservedResource
969 extra = 0
970 fields = ['sliver', 'resource','quantity','reservationSet']
971 suit_classes = 'suit-tab suit-tab-reservedresources'
972
Scott Baker0165fac2014-01-13 11:49:26 -0800973class ReservedResourceInline(PlStackTabularInline):
Scott Baker133c9212013-05-17 09:09:11 -0700974 model = ReservedResource
975 extra = 0
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400976 suit_classes = 'suit-tab suit-tab-reservedresources'
Scott Baker133c9212013-05-17 09:09:11 -0700977
978 def formfield_for_foreignkey(self, db_field, request=None, **kwargs):
979 field = super(ReservedResourceInline, self).formfield_for_foreignkey(db_field, request, **kwargs)
980
981 if db_field.name == 'resource':
982 # restrict resources to those that the slice's service class allows
983 if request._slice is not None:
984 field.queryset = field.queryset.filter(serviceClass = request._slice.serviceClass, calendarReservable=True)
985 if len(field.queryset) > 0:
986 field.initial = field.queryset.all()[0]
987 else:
988 field.queryset = field.queryset.none()
989 elif db_field.name == 'sliver':
990 # restrict slivers to those that belong to the slice
991 if request._slice is not None:
992 field.queryset = field.queryset.filter(slice = request._slice)
993 else:
994 field.queryset = field.queryset.none()
995
996 return field
997
Tony Mack5b061472014-02-04 07:57:10 -0500998 def queryset(self, request):
999 return ReservedResource.select_by_user(request.user)
1000
Scott Baker133c9212013-05-17 09:09:11 -07001001class ReservationChangeForm(forms.ModelForm):
1002 class Meta:
1003 model = Reservation
Siobhan Tullybfd11dc2013-09-03 12:59:24 -04001004 widgets = {
1005 'slice' : LinkedSelect
1006 }
Scott Baker133c9212013-05-17 09:09:11 -07001007
1008class ReservationAddForm(forms.ModelForm):
1009 slice = forms.ModelChoiceField(queryset=Slice.objects.all(), widget=forms.Select(attrs={"onChange":"document.getElementById('id_refresh').value=1; submit()"}))
1010 refresh = forms.CharField(widget=forms.HiddenInput())
1011
1012 class Media:
1013 css = {'all': ('planetstack.css',)} # .field-refresh { display: none; }
1014
1015 def clean_slice(self):
1016 slice = self.cleaned_data.get("slice")
1017 x = ServiceResource.objects.filter(serviceClass = slice.serviceClass, calendarReservable=True)
1018 if len(x) == 0:
1019 raise forms.ValidationError("The slice you selected does not have a service class that allows reservations")
1020 return slice
1021
1022 class Meta:
1023 model = Reservation
Siobhan Tullybfd11dc2013-09-03 12:59:24 -04001024 widgets = {
1025 'slice' : LinkedSelect
1026 }
1027
Scott Baker133c9212013-05-17 09:09:11 -07001028
1029class ReservationAddRefreshForm(ReservationAddForm):
1030 """ This form is displayed when the Reservation Form receives an update
1031 from the Slice dropdown onChange handler. It doesn't validate the
1032 data and doesn't save the data. This will cause the form to be
1033 redrawn.
1034 """
1035
Scott Baker8737e5f2013-05-17 09:35:32 -07001036 """ don't validate anything other than slice """
1037 dont_validate_fields = ("startTime", "duration")
1038
Scott Baker133c9212013-05-17 09:09:11 -07001039 def full_clean(self):
1040 result = super(ReservationAddForm, self).full_clean()
Scott Baker8737e5f2013-05-17 09:35:32 -07001041
1042 for fieldname in self.dont_validate_fields:
1043 if fieldname in self._errors:
1044 del self._errors[fieldname]
1045
Scott Baker133c9212013-05-17 09:09:11 -07001046 return result
1047
1048 """ don't save anything """
1049 def is_valid(self):
1050 return False
1051
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001052class ReservationAdmin(PlanetStackBaseAdmin):
1053 fieldList = ['slice', 'startTime', 'duration']
1054 fieldsets = [('Reservation Details', {'fields': fieldList, 'classes': ['suit-tab suit-tab-general']})]
Scott Baker133c9212013-05-17 09:09:11 -07001055 list_display = ('startTime', 'duration')
Scott Baker133c9212013-05-17 09:09:11 -07001056 form = ReservationAddForm
1057
Siobhan Tullybfd11dc2013-09-03 12:59:24 -04001058 suit_form_tabs = (('general','Reservation Details'), ('reservedresources','Reserved Resources'))
1059
1060 inlines = [ReservedResourceInline]
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001061 user_readonly_inlines = [ReservedResourceROInline]
1062 user_readonly_fields = fieldList
Siobhan Tullybfd11dc2013-09-03 12:59:24 -04001063
Scott Baker133c9212013-05-17 09:09:11 -07001064 def add_view(self, request, form_url='', extra_context=None):
Scott Bakeracd45142013-05-19 16:19:16 -07001065 timezone.activate(request.user.timezone)
Scott Baker133c9212013-05-17 09:09:11 -07001066 request._refresh = False
1067 request._slice = None
1068 if request.method == 'POST':
Scott Baker8737e5f2013-05-17 09:35:32 -07001069 # "refresh" will be set to "1" if the form was submitted due to
1070 # a change in the Slice dropdown.
Scott Baker133c9212013-05-17 09:09:11 -07001071 if request.POST.get("refresh","1") == "1":
1072 request._refresh = True
1073 request.POST["refresh"] = "0"
Scott Baker8737e5f2013-05-17 09:35:32 -07001074
1075 # Keep track of the slice that was selected, so the
1076 # reservedResource inline can filter items for the slice.
Scott Baker133c9212013-05-17 09:09:11 -07001077 request._slice = request.POST.get("slice",None)
1078 if (request._slice is not None):
1079 request._slice = Slice.objects.get(id=request._slice)
1080
1081 result = super(ReservationAdmin, self).add_view(request, form_url, extra_context)
1082 return result
1083
Scott Bakeracd45142013-05-19 16:19:16 -07001084 def changelist_view(self, request, extra_context = None):
1085 timezone.activate(request.user.timezone)
1086 return super(ReservationAdmin, self).changelist_view(request, extra_context)
1087
Scott Baker133c9212013-05-17 09:09:11 -07001088 def get_form(self, request, obj=None, **kwargs):
Siobhan Tullyd3515752013-06-21 16:34:53 -04001089 request._obj_ = obj
1090 if obj is not None:
1091 # For changes, set request._slice to the slice already set in the
1092 # object.
1093 request._slice = obj.slice
1094 self.form = ReservationChangeForm
1095 else:
1096 if getattr(request, "_refresh", False):
1097 self.form = ReservationAddRefreshForm
1098 else:
1099 self.form = ReservationAddForm
1100 return super(ReservationAdmin, self).get_form(request, obj, **kwargs)
1101
Scott Baker133c9212013-05-17 09:09:11 -07001102 def get_readonly_fields(self, request, obj=None):
Siobhan Tullyd3515752013-06-21 16:34:53 -04001103 if (obj is not None):
1104 # Prevent slice from being changed after the reservation has been
1105 # created.
1106 return ['slice']
1107 else:
Scott Baker133c9212013-05-17 09:09:11 -07001108 return []
Scott Baker3de3e372013-05-10 16:50:44 -07001109
Tony Mack5b061472014-02-04 07:57:10 -05001110 def queryset(self, request):
1111 return Reservation.select_by_user(request.user)
1112
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001113class NetworkParameterTypeAdmin(PlanetStackBaseAdmin):
Scott Baker74d8e622013-07-29 16:04:22 -07001114 list_display = ("name", )
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001115 user_readonly_fields = ['name']
1116 user_readonly_inlines = []
Scott Baker74d8e622013-07-29 16:04:22 -07001117
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001118class RouterAdmin(PlanetStackBaseAdmin):
Scott Baker74d8e622013-07-29 16:04:22 -07001119 list_display = ("name", )
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001120 user_readonly_fields = ['name']
1121 user_readonly_inlines = []
1122
1123class RouterROInline(ReadOnlyTabularInline):
1124 model = Router.networks.through
1125 extra = 0
1126 verbose_name_plural = "Routers"
1127 verbose_name = "Router"
1128 suit_classes = 'suit-tab suit-tab-routers'
1129
1130 fields = ['name', 'owner', 'permittedNetworks', 'networks']
Scott Baker74d8e622013-07-29 16:04:22 -07001131
Scott Baker0165fac2014-01-13 11:49:26 -08001132class RouterInline(PlStackTabularInline):
Scott Baker74d8e622013-07-29 16:04:22 -07001133 model = Router.networks.through
1134 extra = 0
1135 verbose_name_plural = "Routers"
1136 verbose_name = "Router"
Siobhan Tully2d95e482013-09-06 10:56:06 -04001137 suit_classes = 'suit-tab suit-tab-routers'
Scott Baker74d8e622013-07-29 16:04:22 -07001138
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001139class NetworkParameterROInline(ReadOnlyTabularInline):
1140 model = NetworkParameter
1141 extra = 1
1142 verbose_name_plural = "Parameters"
1143 verbose_name = "Parameter"
1144 suit_classes = 'suit-tab suit-tab-netparams'
1145 fields = ['parameter', 'value', 'content_type', 'object_id', 'content_object']
1146
Scott Baker74d8e622013-07-29 16:04:22 -07001147class NetworkParameterInline(generic.GenericTabularInline):
Scott Baker74d8e622013-07-29 16:04:22 -07001148 model = NetworkParameter
1149 extra = 1
1150 verbose_name_plural = "Parameters"
1151 verbose_name = "Parameter"
Siobhan Tully2d95e482013-09-06 10:56:06 -04001152 suit_classes = 'suit-tab suit-tab-netparams'
Scott Baker74d8e622013-07-29 16:04:22 -07001153
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001154class NetworkSliversROInline(ReadOnlyTabularInline):
1155 fields = ['network', 'sliver', 'ip', 'port_id']
1156 model = NetworkSliver
1157 extra = 0
1158 verbose_name_plural = "Slivers"
1159 verbose_name = "Sliver"
1160 suit_classes = 'suit-tab suit-tab-networkslivers'
1161
Scott Baker0165fac2014-01-13 11:49:26 -08001162class NetworkSliversInline(PlStackTabularInline):
Scott Baker74d8e622013-07-29 16:04:22 -07001163 readonly_fields = ("ip", )
1164 model = NetworkSliver
Scott Baker874936e2014-01-13 18:15:34 -08001165 selflink_fieldname = "sliver"
Scott Baker74d8e622013-07-29 16:04:22 -07001166 extra = 0
1167 verbose_name_plural = "Slivers"
1168 verbose_name = "Sliver"
Siobhan Tully2d95e482013-09-06 10:56:06 -04001169 suit_classes = 'suit-tab suit-tab-networkslivers'
Scott Baker74d8e622013-07-29 16:04:22 -07001170
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001171class NetworkSlicesROInline(ReadOnlyTabularInline):
1172 model = NetworkSlice
1173 extra = 0
1174 verbose_name_plural = "Slices"
1175 verbose_name = "Slice"
1176 suit_classes = 'suit-tab suit-tab-networkslices'
1177 fields = ['network','slice']
1178
Scott Baker0165fac2014-01-13 11:49:26 -08001179class NetworkSlicesInline(PlStackTabularInline):
Scott Bakerd7d2a392013-08-06 08:57:30 -07001180 model = NetworkSlice
Scott Baker874936e2014-01-13 18:15:34 -08001181 selflink_fieldname = "slice"
Scott Bakerd7d2a392013-08-06 08:57:30 -07001182 extra = 0
1183 verbose_name_plural = "Slices"
1184 verbose_name = "Slice"
Siobhan Tully2d95e482013-09-06 10:56:06 -04001185 suit_classes = 'suit-tab suit-tab-networkslices'
Scott Bakerd7d2a392013-08-06 08:57:30 -07001186
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001187class NetworkAdmin(PlanetStackBaseAdmin):
Scott Baker74d8e622013-07-29 16:04:22 -07001188 list_display = ("name", "subnet", "ports", "labels")
1189 readonly_fields = ("subnet", )
Siobhan Tully2d95e482013-09-06 10:56:06 -04001190
Scott Bakerd7d2a392013-08-06 08:57:30 -07001191 inlines = [NetworkParameterInline, NetworkSliversInline, NetworkSlicesInline, RouterInline]
Scott Baker74d8e622013-07-29 16:04:22 -07001192
Siobhan Tully2d95e482013-09-06 10:56:06 -04001193 fieldsets = [
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001194 (None, {'fields': ['name','template','ports','labels','owner','guaranteedBandwidth', 'permitAllSlices','permittedSlices','network_id','router_id','subnet_id','subnet'], 'classes':['suit-tab suit-tab-general']}),]
1195
1196 user_readonly_fields = ['name','template','ports','labels','owner','guaranteedBandwidth', 'permitAllSlices','permittedSlices','network_id','router_id','subnet_id','subnet']
1197 user_readonly_inlines = [NetworkParameterROInline, NetworkSliversROInline, NetworkSlicesROInline, RouterROInline]
Siobhan Tully2d95e482013-09-06 10:56:06 -04001198
1199 suit_form_tabs =(
1200 ('general','Network Details'),
1201 ('netparams', 'Parameters'),
1202 ('networkslivers','Slivers'),
1203 ('networkslices','Slices'),
1204 ('routers','Routers'),
1205 )
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001206class NetworkTemplateAdmin(PlanetStackBaseAdmin):
Scott Baker74d8e622013-07-29 16:04:22 -07001207 list_display = ("name", "guaranteedBandwidth", "visibility")
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001208 user_readonly_fields = ["name", "guaranteedBandwidth", "visibility"]
1209 user_readonly_inlines = []
Scott Baker74d8e622013-07-29 16:04:22 -07001210
Tony Mack31c2b8f2013-04-26 20:01:42 -04001211# register a signal that caches the user's credentials when they log in
1212def cache_credentials(sender, user, request, **kwds):
1213 auth = {'username': request.POST['username'],
1214 'password': request.POST['password']}
1215 request.session['auth'] = auth
1216user_logged_in.connect(cache_credentials)
1217
Scott Baker15cddfa2013-12-09 13:45:19 -08001218def dollar_field(fieldName, short_description):
1219 def newFunc(self, obj):
1220 try:
1221 x= "$ %0.2f" % float(getattr(obj, fieldName, 0.0))
1222 except:
1223 x=getattr(obj, fieldName, 0.0)
1224 return x
1225 newFunc.short_description = short_description
1226 return newFunc
1227
1228def right_dollar_field(fieldName, short_description):
1229 def newFunc(self, obj):
1230 try:
1231 #x= '<div align=right style="width:6em">$ %0.2f</div>' % float(getattr(obj, fieldName, 0.0))
1232 x= '<div align=right>$ %0.2f</div>' % float(getattr(obj, fieldName, 0.0))
1233 except:
1234 x=getattr(obj, fieldName, 0.0)
1235 return x
1236 newFunc.short_description = short_description
1237 newFunc.allow_tags = True
1238 return newFunc
Scott Baker43105042013-12-06 23:23:36 -08001239
Scott Baker0165fac2014-01-13 11:49:26 -08001240class InvoiceChargeInline(PlStackTabularInline):
Scott Baker43105042013-12-06 23:23:36 -08001241 model = Charge
Scott Baker15cddfa2013-12-09 13:45:19 -08001242 extra = 0
Scott Baker43105042013-12-06 23:23:36 -08001243 verbose_name_plural = "Charges"
1244 verbose_name = "Charge"
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001245 exclude = ['account']
Scott Baker9cb88a22013-12-09 18:56:00 -08001246 fields = ["date", "kind", "state", "object", "coreHours", "dollar_amount", "slice"]
1247 readonly_fields = ["date", "kind", "state", "object", "coreHours", "dollar_amount", "slice"]
1248 can_delete = False
1249 max_num = 0
1250
1251 dollar_amount = right_dollar_field("amount", "Amount")
Scott Baker43105042013-12-06 23:23:36 -08001252
1253class InvoiceAdmin(admin.ModelAdmin):
1254 list_display = ("date", "account")
1255
1256 inlines = [InvoiceChargeInline]
1257
Scott Baker9cb88a22013-12-09 18:56:00 -08001258 fields = ["date", "account", "dollar_amount"]
1259 readonly_fields = ["date", "account", "dollar_amount"]
1260
1261 dollar_amount = dollar_field("amount", "Amount")
Scott Baker43105042013-12-06 23:23:36 -08001262
Scott Baker0165fac2014-01-13 11:49:26 -08001263class InvoiceInline(PlStackTabularInline):
Scott Baker15cddfa2013-12-09 13:45:19 -08001264 model = Invoice
1265 extra = 0
1266 verbose_name_plural = "Invoices"
1267 verbose_name = "Invoice"
Scott Baker0165fac2014-01-13 11:49:26 -08001268 fields = ["date", "dollar_amount"]
1269 readonly_fields = ["date", "dollar_amount"]
Scott Baker15cddfa2013-12-09 13:45:19 -08001270 suit_classes = 'suit-tab suit-tab-accountinvoice'
1271 can_delete=False
1272 max_num=0
1273
1274 dollar_amount = right_dollar_field("amount", "Amount")
1275
Scott Baker0165fac2014-01-13 11:49:26 -08001276class PendingChargeInline(PlStackTabularInline):
Scott Baker43105042013-12-06 23:23:36 -08001277 model = Charge
Scott Baker15cddfa2013-12-09 13:45:19 -08001278 extra = 0
Scott Baker43105042013-12-06 23:23:36 -08001279 verbose_name_plural = "Charges"
1280 verbose_name = "Charge"
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001281 exclude = ["invoice"]
Scott Baker15cddfa2013-12-09 13:45:19 -08001282 fields = ["date", "kind", "state", "object", "coreHours", "dollar_amount", "slice"]
1283 readonly_fields = ["date", "kind", "state", "object", "coreHours", "dollar_amount", "slice"]
Scott Baker43105042013-12-06 23:23:36 -08001284 suit_classes = 'suit-tab suit-tab-accountpendingcharges'
Scott Baker15cddfa2013-12-09 13:45:19 -08001285 can_delete=False
1286 max_num=0
Scott Baker43105042013-12-06 23:23:36 -08001287
1288 def queryset(self, request):
1289 qs = super(PendingChargeInline, self).queryset(request)
1290 qs = qs.filter(state="pending")
1291 return qs
1292
Scott Baker15cddfa2013-12-09 13:45:19 -08001293 dollar_amount = right_dollar_field("amount", "Amount")
1294
Scott Baker0165fac2014-01-13 11:49:26 -08001295class PaymentInline(PlStackTabularInline):
Scott Baker43105042013-12-06 23:23:36 -08001296 model=Payment
1297 extra = 1
1298 verbose_name_plural = "Payments"
1299 verbose_name = "Payment"
Scott Baker15cddfa2013-12-09 13:45:19 -08001300 fields = ["date", "dollar_amount"]
1301 readonly_fields = ["date", "dollar_amount"]
Scott Baker43105042013-12-06 23:23:36 -08001302 suit_classes = 'suit-tab suit-tab-accountpayments'
Scott Baker15cddfa2013-12-09 13:45:19 -08001303 can_delete=False
1304 max_num=0
1305
1306 dollar_amount = right_dollar_field("amount", "Amount")
1307
Scott Baker43105042013-12-06 23:23:36 -08001308class AccountAdmin(admin.ModelAdmin):
1309 list_display = ("site", "balance_due")
1310
1311 inlines = [InvoiceInline, PaymentInline, PendingChargeInline]
1312
1313 fieldsets = [
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001314 (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 -08001315
Scott Baker15cddfa2013-12-09 13:45:19 -08001316 readonly_fields = ['site', 'dollar_balance_due', 'dollar_total_invoices', 'dollar_total_payments']
Scott Baker43105042013-12-06 23:23:36 -08001317
1318 suit_form_tabs =(
1319 ('general','Account Details'),
1320 ('accountinvoice', 'Invoices'),
1321 ('accountpayments', 'Payments'),
1322 ('accountpendingcharges','Pending Charges'),
1323 )
1324
Scott Baker15cddfa2013-12-09 13:45:19 -08001325 dollar_balance_due = dollar_field("balance_due", "Balance Due")
1326 dollar_total_invoices = dollar_field("total_invoices", "Total Invoices")
1327 dollar_total_payments = dollar_field("total_payments", "Total Payments")
1328
Siobhan Tullyce652d02013-10-08 21:52:35 -04001329
Siobhan Tully53437282013-04-26 19:30:27 -04001330# Now register the new UserAdmin...
Siobhan Tully30fd4292013-05-10 08:59:56 -04001331admin.site.register(User, UserAdmin)
Siobhan Tully53437282013-04-26 19:30:27 -04001332# ... and, since we're not using Django's builtin permissions,
1333# unregister the Group model from admin.
Siobhan Tullyce652d02013-10-08 21:52:35 -04001334#admin.site.unregister(Group)
Siobhan Tully53437282013-04-26 19:30:27 -04001335
Siobhan Tullybf1153a2013-05-27 20:53:48 -04001336#Do not show django evolution in the admin interface
1337from django_evolution.models import Version, Evolution
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001338#admin.site.unregister(Version)
1339#admin.site.unregister(Evolution)
Siobhan Tullybf1153a2013-05-27 20:53:48 -04001340
1341
1342# When debugging it is often easier to see all the classes, but for regular use
1343# only the top-levels should be displayed
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001344showAll = False
Scott Baker43105042013-12-06 23:23:36 -08001345
Siobhan Tullybf1153a2013-05-27 20:53:48 -04001346admin.site.register(Deployment, DeploymentAdmin)
Siobhan Tully4bc09f22013-04-10 21:15:21 -04001347admin.site.register(Site, SiteAdmin)
Siobhan Tully4bc09f22013-04-10 21:15:21 -04001348admin.site.register(Slice, SliceAdmin)
Siobhan Tullyce652d02013-10-08 21:52:35 -04001349admin.site.register(Service, ServiceAdmin)
smbakera3cf70c2013-06-27 02:01:41 -07001350admin.site.register(Reservation, ReservationAdmin)
Scott Baker74d8e622013-07-29 16:04:22 -07001351admin.site.register(Network, NetworkAdmin)
1352admin.site.register(Router, RouterAdmin)
Scott Baker74d8e622013-07-29 16:04:22 -07001353admin.site.register(NetworkTemplate, NetworkTemplateAdmin)
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001354admin.site.register(Account, AccountAdmin)
1355admin.site.register(Invoice, InvoiceAdmin)
Siobhan Tullybf1153a2013-05-27 20:53:48 -04001356
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001357if True:
1358 admin.site.register(NetworkParameterType, NetworkParameterTypeAdmin)
1359 admin.site.register(ServiceClass, ServiceClassAdmin)
Siobhan Tullybfd11dc2013-09-03 12:59:24 -04001360 #admin.site.register(PlanetStack)
Siobhan Tullyd3515752013-06-21 16:34:53 -04001361 admin.site.register(Tag, TagAdmin)
Siobhan Tullyce652d02013-10-08 21:52:35 -04001362 admin.site.register(DeploymentRole)
1363 admin.site.register(SiteRole)
1364 admin.site.register(SliceRole)
1365 admin.site.register(PlanetStackRole)
Siobhan Tullybf1153a2013-05-27 20:53:48 -04001366 admin.site.register(Node, NodeAdmin)
Siobhan Tullybfd11dc2013-09-03 12:59:24 -04001367 #admin.site.register(SlicePrivilege, SlicePrivilegeAdmin)
1368 #admin.site.register(SitePrivilege, SitePrivilegeAdmin)
Siobhan Tullybf1153a2013-05-27 20:53:48 -04001369 admin.site.register(Sliver, SliverAdmin)
Siobhan Tullybf1153a2013-05-27 20:53:48 -04001370 admin.site.register(Image, ImageAdmin)
Tony Mack7130ac32013-03-22 21:58:00 -04001371