blob: f054e3f6fa550fc1fc74353ef8bf56137fb7ea47 [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):
Siobhan Tullycf04fb62014-01-11 11:25:57 -050046 if self.__user_is_readonly(request):
Scott Bakeraf73e102014-04-22 22:40:07 -070047 if not hasattr(self, "readonly_save"):
48 # save the original readonly fields
49 self.readonly_save = self.readonly_fields
50 self.inlines_save = self.inlines
51 self.readonly_fields=self.user_readonly_fields
52 self.inlines = self.user_readonly_inlines
53 else:
54 if hasattr(self, "readonly_save"):
55 # restore the original readonly fields
56 self.readonly_fields = self.readonly_save
57 self.inlines = self.inlines_save
Siobhan Tullycf04fb62014-01-11 11:25:57 -050058
59 try:
60 return super(ReadOnlyAwareAdmin, self).change_view(request, object_id, extra_context=extra_context)
61 except PermissionDenied:
62 pass
63 if request.method == 'POST':
64 raise PermissionDenied
65 request.readonly = True
66 return super(ReadOnlyAwareAdmin, self).change_view(request, object_id, extra_context=extra_context)
67
68
69 def __user_is_readonly(self, request):
70 return request.user.isReadOnlyUser()
71
Siobhan Tullyce652d02013-10-08 21:52:35 -040072class SingletonAdmin (admin.ModelAdmin):
73 def has_add_permission(self, request):
74 num_objects = self.model.objects.count()
75 if num_objects >= 1:
76 return False
77 else:
78 return True
79
80
Siobhan Tullyd3515752013-06-21 16:34:53 -040081class PlStackTabularInline(admin.TabularInline):
Scott Baker86568322014-01-12 16:53:31 -080082 def __init__(self, *args, **kwargs):
83 super(PlStackTabularInline, self).__init__(*args, **kwargs)
84
85 # InlineModelAdmin as no get_fields() method, so in order to add
86 # the selflink field, we override __init__ to modify self.fields and
87 # self.readonly_fields.
88
Scott Bakere2bbf7e2014-01-13 12:09:31 -080089 self.setup_selflink()
90
Scott Baker874936e2014-01-13 18:15:34 -080091 def get_change_url(self, model, id):
92 """ Get the URL to a change form in the admin for this model """
93 reverse_path = "admin:%s_change" % (model._meta.db_table)
Scott Bakere2bbf7e2014-01-13 12:09:31 -080094 try:
Scott Baker874936e2014-01-13 18:15:34 -080095 url = reverse(reverse_path, args=(id,))
Scott Bakere2bbf7e2014-01-13 12:09:31 -080096 except NoReverseMatch:
Scott Baker874936e2014-01-13 18:15:34 -080097 return None
98
99 return url
100
101 def setup_selflink(self):
102 if hasattr(self, "selflink_fieldname"):
103 """ self.selflink_model can be defined to punch through a relation
104 to its target object. For example, in SliceNetworkInline, set
105 selflink_model = "network", and the URL will lead to the Network
106 object instead of trying to bring up a change view of the
107 SliceNetwork object.
108 """
109 self.selflink_model = getattr(self.model,self.selflink_fieldname).field.rel.to
110 else:
111 self.selflink_model = self.model
112
113 url = self.get_change_url(self.selflink_model, 0)
114
115 # We don't have an admin for this object, so don't create the
116 # selflink.
117 if (url == None):
Scott Bakere2bbf7e2014-01-13 12:09:31 -0800118 return
119
Scott Baker874936e2014-01-13 18:15:34 -0800120 # Since we need to add "selflink" to the field list, we need to create
121 # self.fields if it is None.
Scott Baker0165fac2014-01-13 11:49:26 -0800122 if (self.fields is None):
123 self.fields = []
124 for f in self.model._meta.fields:
125 if f.editable and f.name != "id":
126 self.fields.append(f.name)
Scott Baker86568322014-01-12 16:53:31 -0800127
Scott Baker874936e2014-01-13 18:15:34 -0800128 self.fields = tuple(self.fields) + ("selflink", )
Scott Baker86568322014-01-12 16:53:31 -0800129
Scott Baker874936e2014-01-13 18:15:34 -0800130 if self.readonly_fields is None:
131 self.readonly_fields = ()
Scott Baker86568322014-01-12 16:53:31 -0800132
Scott Baker874936e2014-01-13 18:15:34 -0800133 self.readonly_fields = tuple(self.readonly_fields) + ("selflink", )
Scott Baker86568322014-01-12 16:53:31 -0800134
135 def selflink(self, obj):
Scott Baker874936e2014-01-13 18:15:34 -0800136 if hasattr(self, "selflink_fieldname"):
137 obj = getattr(obj, self.selflink_fieldname)
138
Scott Baker86568322014-01-12 16:53:31 -0800139 if obj.id:
Scott Baker874936e2014-01-13 18:15:34 -0800140 url = self.get_change_url(self.selflink_model, obj.id)
141 return "<a href='%s'>Details</a>" % str(url)
Scott Baker86568322014-01-12 16:53:31 -0800142 else:
Scott Bakere2bbf7e2014-01-13 12:09:31 -0800143 return "Not present"
Scott Baker86568322014-01-12 16:53:31 -0800144
145 selflink.allow_tags = True
146 selflink.short_description = "Details"
Siobhan Tullyd3515752013-06-21 16:34:53 -0400147
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500148class ReadOnlyTabularInline(PlStackTabularInline):
149 can_delete = False
150
151 def get_readonly_fields(self, request, obj=None):
152 return self.fields
153
154 def has_add_permission(self, request):
155 return False
156
157class ReservationROInline(ReadOnlyTabularInline):
158 model = Reservation
159 extra = 0
160 suit_classes = 'suit-tab suit-tab-reservations'
161 fields = ['startTime','slice','duration']
162
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400163class ReservationInline(PlStackTabularInline):
164 model = Reservation
165 extra = 0
166 suit_classes = 'suit-tab suit-tab-reservations'
Tony Mack5b061472014-02-04 07:57:10 -0500167
168 def queryset(self, request):
169 return Reservation.select_by_user(request.user)
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400170
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500171class TagROInline(generic.GenericTabularInline):
172 model = Tag
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400173 extra = 0
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500174 suit_classes = 'suit-tab suit-tab-tags'
175 can_delete = False
176 fields = ['service', 'name', 'value']
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400177
178 def get_readonly_fields(self, request, obj=None):
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500179 return self.fields
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400180
181 def has_add_permission(self, request):
182 return False
183
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500184
Siobhan Tullyde5450d2013-06-21 11:35:33 -0400185class TagInline(generic.GenericTabularInline):
186 model = Tag
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400187 extra = 0
188 suit_classes = 'suit-tab suit-tab-tags'
Tony Mack5b061472014-02-04 07:57:10 -0500189 fields = ['service', 'name', 'value']
190
191 def queryset(self, request):
192 return Tag.select_by_user(request.user)
Siobhan Tullyde5450d2013-06-21 11:35:33 -0400193
Scott Baker74d8e622013-07-29 16:04:22 -0700194class NetworkLookerUpper:
Siobhan Tully2c780ad2013-09-06 11:22:40 -0400195 """ This is a callable that looks up a network name in a sliver and returns
196 the ip address for that network.
197 """
198
199 def __init__(self, name):
200 self.short_description = name
201 self.__name__ = name
202 self.network_name = name
203
204 def __call__(self, obj):
205 if obj is not None:
206 for nbs in obj.networksliver_set.all():
207 if (nbs.network.name == self.network_name):
208 return nbs.ip
Scott Baker74d8e622013-07-29 16:04:22 -0700209 return ""
210
211 def __str__(self):
212 return self.network_name
213
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500214class SliverROInline(ReadOnlyTabularInline):
215 model = Sliver
216 fields = ['ip', 'instance_name', 'slice', 'numberCores', 'image', 'node', 'deploymentNetwork']
217 suit_classes = 'suit-tab suit-tab-slivers'
218
Siobhan Tullyd3515752013-06-21 16:34:53 -0400219class SliverInline(PlStackTabularInline):
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400220 model = Sliver
Tony Mackb0d97422013-06-10 09:57:45 -0400221 fields = ['ip', 'instance_name', 'slice', 'numberCores', 'image', 'node', 'deploymentNetwork']
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400222 extra = 0
Tony Mack3777b012013-05-07 21:38:06 -0400223 readonly_fields = ['ip', 'instance_name']
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400224 suit_classes = 'suit-tab suit-tab-slivers'
Scott Baker74d8e622013-07-29 16:04:22 -0700225
Tony Mack5b061472014-02-04 07:57:10 -0500226 def queryset(self, request):
227 return Sliver.select_by_user(request.user)
228
Siobhan Tully2d95e482013-09-06 10:56:06 -0400229# Note this is breaking in the admin.py when trying to use an inline to add a node/image
230# def _declared_fieldsets(self):
231# # Return None so django will call get_fieldsets and we can insert our
232# # dynamic fields
233# return None
234#
235# def get_readonly_fields(self, request, obj=None):
236# readonly_fields = super(SliverInline, self).get_readonly_fields(request, obj)
237#
238# # Lookup the networks that are bound to the slivers, and add those
239# # network names to the list of readonly fields.
240#
241# for sliver in obj.slivers.all():
242# for nbs in sliver.networksliver_set.all():
243# if nbs.ip:
244# network_name = nbs.network.name
245# if network_name not in [str(x) for x in readonly_fields]:
246# readonly_fields.append(NetworkLookerUpper(network_name))
247#
248# return readonly_fields
249#
250# def get_fieldsets(self, request, obj=None):
251# form = self.get_formset(request, obj).form
252# # fields = the read/write files + the read-only fields
253# fields = self.fields
254# for fieldName in self.get_readonly_fields(request,obj):
255# if not fieldName in fields:
256# fields.append(fieldName)
257#
258# return [(None, {'fields': fields})]
Scott Baker74d8e622013-07-29 16:04:22 -0700259
Tony Mackc2835a92013-05-28 09:18:49 -0400260
Siobhan Tully567e3e62013-06-21 18:03:16 -0400261
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500262class SiteROInline(ReadOnlyTabularInline):
263 model = Site
264 extra = 0
265 fields = ['name', 'login_base', 'site_url', 'enabled']
266 suit_classes = 'suit-tab suit-tab-sites'
267
Siobhan Tullyd3515752013-06-21 16:34:53 -0400268class SiteInline(PlStackTabularInline):
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400269 model = Site
270 extra = 0
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400271 suit_classes = 'suit-tab suit-tab-sites'
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400272
Tony Mack5b061472014-02-04 07:57:10 -0500273 def queryset(self, request):
274 return Site.select_by_user(request.user)
275
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500276class UserROInline(ReadOnlyTabularInline):
277 model = User
278 fields = ['email', 'firstname', 'lastname']
279 extra = 0
280 suit_classes = 'suit-tab suit-tab-users'
281
Siobhan Tullyd3515752013-06-21 16:34:53 -0400282class UserInline(PlStackTabularInline):
Siobhan Tully30fd4292013-05-10 08:59:56 -0400283 model = User
Siobhan Tully47ae1b52013-05-10 15:53:14 -0400284 fields = ['email', 'firstname', 'lastname']
Siobhan Tully30fd4292013-05-10 08:59:56 -0400285 extra = 0
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400286 suit_classes = 'suit-tab suit-tab-users'
Siobhan Tully30fd4292013-05-10 08:59:56 -0400287
Tony Mack5b061472014-02-04 07:57:10 -0500288 def queryset(self, request):
289 return User.select_by_user(request.user)
290
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500291class SliceROInline(ReadOnlyTabularInline):
292 model = Slice
293 suit_classes = 'suit-tab suit-tab-slices'
294 fields = ['name','site', 'serviceClass', 'service']
295
Siobhan Tullyd3515752013-06-21 16:34:53 -0400296class SliceInline(PlStackTabularInline):
Tony Mack00d361f2013-04-28 10:28:42 -0400297 model = Slice
Siobhan Tullyce652d02013-10-08 21:52:35 -0400298 fields = ['name','site', 'serviceClass', 'service']
Tony Mack00d361f2013-04-28 10:28:42 -0400299 extra = 0
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400300 suit_classes = 'suit-tab suit-tab-slices'
301
Tony Mack5b061472014-02-04 07:57:10 -0500302 def queryset(self, request):
303 return Slice.select_by_user(request.user)
304
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500305class NodeROInline(ReadOnlyTabularInline):
306 model = Node
307 extra = 0
308 suit_classes = 'suit-tab suit-tab-nodes'
309 fields = ['name','deployment']
Tony Mack00d361f2013-04-28 10:28:42 -0400310
Siobhan Tullyd3515752013-06-21 16:34:53 -0400311class NodeInline(PlStackTabularInline):
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400312 model = Node
313 extra = 0
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400314 suit_classes = 'suit-tab suit-tab-nodes'
Tony Mack5b061472014-02-04 07:57:10 -0500315 fields = ['name','deployment']
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400316
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500317class DeploymentPrivilegeROInline(ReadOnlyTabularInline):
318 model = DeploymentPrivilege
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400319 extra = 0
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500320 suit_classes = 'suit-tab suit-tab-deploymentprivileges'
321 fields = ['user','role']
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400322
323class DeploymentPrivilegeInline(PlStackTabularInline):
324 model = DeploymentPrivilege
325 extra = 0
326 suit_classes = 'suit-tab suit-tab-deploymentprivileges'
Tony Mack5b061472014-02-04 07:57:10 -0500327 fields = ['user','role']
328
329 def queryset(self, request):
330 return DeploymentPrivilege.select_by_user(request.user)
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400331
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500332#CLEANUP DOUBLE SitePrivilegeInline
333class SitePrivilegeROInline(ReadOnlyTabularInline):
334 model = SitePrivilege
335 extra = 0
336 suit_classes = 'suit-tab suit-tab-siteprivileges'
337 fields = ['user','site', 'role']
338
Siobhan Tullyd3515752013-06-21 16:34:53 -0400339class SitePrivilegeInline(PlStackTabularInline):
Siobhan Tullyaa1bcd52013-05-10 12:43:09 -0400340 model = SitePrivilege
341 extra = 0
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400342 suit_classes = 'suit-tab suit-tab-siteprivileges'
Tony Mack5b061472014-02-04 07:57:10 -0500343 fields = ['user','site', 'role']
Siobhan Tullyaa1bcd52013-05-10 12:43:09 -0400344
Tony Mackc2835a92013-05-28 09:18:49 -0400345 def formfield_for_foreignkey(self, db_field, request, **kwargs):
346 if db_field.name == 'site':
Tony Mack5b061472014-02-04 07:57:10 -0500347 kwargs['queryset'] = Site.select_by_user(request.user)
Tony Mackc2835a92013-05-28 09:18:49 -0400348
349 if db_field.name == 'user':
Tony Mack5b061472014-02-04 07:57:10 -0500350 kwargs['queryset'] = User.select_by_user(request.user)
Tony Mackc2835a92013-05-28 09:18:49 -0400351 return super(SitePrivilegeInline, self).formfield_for_foreignkey(db_field, request, **kwargs)
352
Tony Mack5b061472014-02-04 07:57:10 -0500353 def queryset(self, request):
354 return SitePrivilege.select_by_user(request.user)
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400355
Tony Macke4be32f2014-03-11 20:45:25 -0400356class SiteDeploymentROInline(ReadOnlyTabularInline):
357 model = SiteDeployments
358 #model = Site.deployments.through
359 extra = 0
360 suit_classes = 'suit-tab suit-tab-sitedeployments'
361 fields = ['deployment','site']
362
363class SiteDeploymentInline(PlStackTabularInline):
364 model = SiteDeployments
365 #model = Site.deployments.through
366 extra = 0
367 suit_classes = 'suit-tab suit-tab-deployments'
368 fields = ['deployment','site']
369
370 def formfield_for_foreignkey(self, db_field, request, **kwargs):
371 if db_field.name == 'site':
372 kwargs['queryset'] = Site.select_by_user(request.user)
373
374 if db_field.name == 'deployment':
375 kwargs['queryset'] = Deployment.select_by_user(request.user)
376 return super(SiteDeploymentInline, self).formfield_for_foreignkey(db_field, request, **kwargs)
377
378 def queryset(self, request):
379 return SiteDeployments.select_by_user(request.user)
380
381
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500382class SlicePrivilegeROInline(ReadOnlyTabularInline):
383 model = SlicePrivilege
384 extra = 0
385 suit_classes = 'suit-tab suit-tab-sliceprivileges'
386 fields = ['user', 'slice', 'role']
387
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400388class SlicePrivilegeInline(PlStackTabularInline):
389 model = SlicePrivilege
390 suit_classes = 'suit-tab suit-tab-sliceprivileges'
391 extra = 0
392 fields = ('user', 'slice','role')
Siobhan Tullyaa1bcd52013-05-10 12:43:09 -0400393
Tony Mackc2835a92013-05-28 09:18:49 -0400394 def formfield_for_foreignkey(self, db_field, request, **kwargs):
395 if db_field.name == 'slice':
Tony Mack5b061472014-02-04 07:57:10 -0500396 kwargs['queryset'] = Slice.select_by_user(request.user)
Tony Mackc2835a92013-05-28 09:18:49 -0400397 if db_field.name == 'user':
Tony Mack5b061472014-02-04 07:57:10 -0500398 kwargs['queryset'] = User.select_by_user(request.user)
Tony Mackc2835a92013-05-28 09:18:49 -0400399
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400400 return super(SlicePrivilegeInline, self).formfield_for_foreignkey(db_field, request, **kwargs)
Tony Mackc2835a92013-05-28 09:18:49 -0400401
Tony Mack5b061472014-02-04 07:57:10 -0500402 def queryset(self, request):
403 return SlicePrivilege.select_by_user(request.user)
404
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500405class SliceNetworkROInline(ReadOnlyTabularInline):
406 model = Network.slices.through
407 extra = 0
408 verbose_name = "Network Connection"
409 verbose_name_plural = "Network Connections"
410 suit_classes = 'suit-tab suit-tab-slicenetworks'
411 fields = ['network']
412
Scott Bakera0015eb2013-08-14 17:28:14 -0700413class SliceNetworkInline(PlStackTabularInline):
Scott Baker74d8e622013-07-29 16:04:22 -0700414 model = Network.slices.through
Scott Baker874936e2014-01-13 18:15:34 -0800415 selflink_fieldname = "network"
Scott Baker74d8e622013-07-29 16:04:22 -0700416 extra = 0
417 verbose_name = "Network Connection"
418 verbose_name_plural = "Network Connections"
Siobhan Tully2d95e482013-09-06 10:56:06 -0400419 suit_classes = 'suit-tab suit-tab-slicenetworks'
Scott Baker74d8e622013-07-29 16:04:22 -0700420
Tony Mack5e71a662013-05-03 23:30:41 -0400421class PlainTextWidget(forms.HiddenInput):
422 input_type = 'hidden'
423
424 def render(self, name, value, attrs=None):
425 if value is None:
426 value = ''
Tony Mack1d6b85f2013-05-07 18:49:14 -0400427 return mark_safe(str(value) + super(PlainTextWidget, self).render(name, value, attrs))
Tony Mack9bcbe4f2013-04-29 08:13:27 -0400428
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500429class PlanetStackBaseAdmin(ReadOnlyAwareAdmin):
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400430 save_on_top = False
Tony Mack332ee1d2014-02-04 15:33:45 -0500431
432 def save_model(self, request, obj, form, change):
Tony Mack3d042792014-03-17 19:18:37 -0400433 obj.caller = request.user
Tony Mack332ee1d2014-02-04 15:33:45 -0500434 # update openstack connection to use this site/tenant
435 obj.save_by_user(request.user)
436
437 def delete_model(self, request, obj):
438 obj.delete_by_user(request.user)
439
440 def save_formset(self, request, form, formset, change):
441 instances = formset.save(commit=False)
442 for instance in instances:
443 instance.save_by_user(request.user)
444 formset.save_m2m()
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400445
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400446class SliceRoleAdmin(PlanetStackBaseAdmin):
447 model = SliceRole
448 pass
449
450class SiteRoleAdmin(PlanetStackBaseAdmin):
451 model = SiteRole
452 pass
453
Siobhan Tullybf1153a2013-05-27 20:53:48 -0400454class DeploymentAdminForm(forms.ModelForm):
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400455 sites = forms.ModelMultipleChoiceField(
456 queryset=Site.objects.all(),
457 required=False,
458 widget=FilteredSelectMultiple(
459 verbose_name=('Sites'), is_stacked=False
460 )
461 )
462 class Meta:
Siobhan Tullybf1153a2013-05-27 20:53:48 -0400463 model = Deployment
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400464
Siobhan Tully320b4622014-01-17 15:11:14 -0500465 def __init__(self, *args, **kwargs):
466 super(DeploymentAdminForm, self).__init__(*args, **kwargs)
467
468 if self.instance and self.instance.pk:
Tony Mack0cd67e82014-04-02 16:02:45 -0400469 self.fields['sites'].initial = self.instance.sitedeployments_set.all()
Siobhan Tully320b4622014-01-17 15:11:14 -0500470
471 def save(self, commit=True):
472 deployment = super(DeploymentAdminForm, self).save(commit=False)
473
474 if commit:
475 deployment.save()
476
477 if deployment.pk:
478 deployment.sites = self.cleaned_data['sites']
479 self.save_m2m()
480
481 return deployment
482
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500483class SiteAssocInline(PlStackTabularInline):
484 model = Site.deployments.through
485 extra = 0
486 suit_classes = 'suit-tab suit-tab-sites'
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400487
Siobhan Tullybf1153a2013-05-27 20:53:48 -0400488class DeploymentAdmin(PlanetStackBaseAdmin):
489 form = DeploymentAdminForm
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500490 model = Deployment
491 fieldList = ['name','sites']
492 fieldsets = [(None, {'fields': fieldList, 'classes':['suit-tab suit-tab-sites']})]
Siobhan Tully2d95e482013-09-06 10:56:06 -0400493 inlines = [DeploymentPrivilegeInline,NodeInline,TagInline]
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500494
495 user_readonly_inlines = [DeploymentPrivilegeROInline,NodeROInline,TagROInline]
496 user_readonly_fields = ['name']
497
498 suit_form_tabs =(('sites','Deployment Details'),('nodes','Nodes'),('deploymentprivileges','Privileges'),('tags','Tags'))
499
500class ServiceAttrAsTabROInline(ReadOnlyTabularInline):
501 model = ServiceAttribute
502 fields = ['name','value']
503 extra = 0
504 suit_classes = 'suit-tab suit-tab-serviceattrs'
Tony Mack5cd13202013-05-01 21:48:38 -0400505
Siobhan Tullyce652d02013-10-08 21:52:35 -0400506class ServiceAttrAsTabInline(PlStackTabularInline):
507 model = ServiceAttribute
508 fields = ['name','value']
509 extra = 0
510 suit_classes = 'suit-tab suit-tab-serviceattrs'
511
Siobhan Tullyce652d02013-10-08 21:52:35 -0400512class ServiceAdmin(PlanetStackBaseAdmin):
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500513 list_display = ("name","description","versionNumber","enabled","published")
514 fieldList = ["name","description","versionNumber","enabled","published"]
515 fieldsets = [(None, {'fields': fieldList, 'classes':['suit-tab suit-tab-general']})]
516 inlines = [ServiceAttrAsTabInline,SliceInline]
517
518 user_readonly_fields = fieldList
519 user_readonly_inlines = [ServiceAttrAsTabROInline,SliceROInline]
520
521 suit_form_tabs =(('general', 'Service Details'),
522 ('slices','Slices'),
523 ('serviceattrs','Additional Attributes'),
524 )
Siobhan Tullyce652d02013-10-08 21:52:35 -0400525
Tony Mack0553f282013-06-10 22:54:50 -0400526class SiteAdmin(PlanetStackBaseAdmin):
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500527 fieldList = ['name', 'site_url', 'enabled', 'is_public', 'login_base', 'accountLink','location']
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400528 fieldsets = [
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500529 (None, {'fields': fieldList, 'classes':['suit-tab suit-tab-general']}),
Tony Macke4be32f2014-03-11 20:45:25 -0400530 #('Deployment Networks', {'fields': ['deployments'], 'classes':['suit-tab suit-tab-deployments']}),
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400531 ]
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400532 suit_form_tabs =(('general', 'Site Details'),
533 ('users','Users'),
Siobhan Tully2d95e482013-09-06 10:56:06 -0400534 ('siteprivileges','Privileges'),
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400535 ('deployments','Deployments'),
536 ('slices','Slices'),
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500537 ('nodes','Nodes'),
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400538 ('tags','Tags'),
539 )
Scott Baker545db2a2013-12-09 18:44:43 -0800540 readonly_fields = ['accountLink']
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500541
542 user_readonly_fields = ['name', 'deployments','site_url', 'enabled', 'is_public', 'login_base', 'accountLink']
Tony Macke4be32f2014-03-11 20:45:25 -0400543 user_readonly_inlines = [SliceROInline,UserROInline,TagROInline, NodeROInline, SitePrivilegeROInline,SiteDeploymentROInline]
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500544
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400545 list_display = ('name', 'login_base','site_url', 'enabled')
546 filter_horizontal = ('deployments',)
Tony Macke4be32f2014-03-11 20:45:25 -0400547 inlines = [SliceInline,UserInline,TagInline, NodeInline, SitePrivilegeInline, SiteDeploymentInline]
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400548 search_fields = ['name']
549
Tony Mack04062832013-05-10 08:22:44 -0400550 def queryset(self, request):
Tony Mack5b061472014-02-04 07:57:10 -0500551 #print dir(UserInline)
552 return Site.select_by_user(request.user)
Tony Mack04062832013-05-10 08:22:44 -0400553
Tony Mack5cd13202013-05-01 21:48:38 -0400554 def get_formsets(self, request, obj=None):
555 for inline in self.get_inline_instances(request, obj):
556 # hide MyInline in the add view
557 if obj is None:
558 continue
Tony Mack2bd5b412013-06-11 21:05:06 -0400559 if isinstance(inline, SliceInline):
560 inline.model.caller = request.user
561 yield inline.get_formset(request, obj)
562
563 def get_formsets(self, request, obj=None):
564 for inline in self.get_inline_instances(request, obj):
565 # hide MyInline in the add view
566 if obj is None:
567 continue
568 if isinstance(inline, SliverInline):
569 inline.model.caller = request.user
Tony Mack5cd13202013-05-01 21:48:38 -0400570 yield inline.get_formset(request, obj)
571
Scott Baker545db2a2013-12-09 18:44:43 -0800572 def accountLink(self, obj):
573 link_obj = obj.accounts.all()
574 if link_obj:
575 reverse_path = "admin:core_account_change"
576 url = reverse(reverse_path, args =(link_obj[0].id,))
577 return "<a href='%s'>%s</a>" % (url, "view billing details")
578 else:
579 return "no billing data for this site"
580 accountLink.allow_tags = True
581 accountLink.short_description = "Billing"
582
Tony Mack332ee1d2014-02-04 15:33:45 -0500583 def save_model(self, request, obj, form, change):
584 # update openstack connection to use this site/tenant
585 obj.save_by_user(request.user)
586
587 def delete_model(self, request, obj):
588 obj.delete_by_user(request.user)
589
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500590
Tony Mack9bcbe4f2013-04-29 08:13:27 -0400591class SitePrivilegeAdmin(PlanetStackBaseAdmin):
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500592 fieldList = ['user', 'site', 'role']
Tony Mack00d361f2013-04-28 10:28:42 -0400593 fieldsets = [
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500594 (None, {'fields': fieldList, 'classes':['collapse']})
Tony Mack00d361f2013-04-28 10:28:42 -0400595 ]
596 list_display = ('user', 'site', 'role')
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500597 user_readonly_fields = fieldList
598 user_readonly_inlines = []
Tony Mack00d361f2013-04-28 10:28:42 -0400599
Tony Mackc2835a92013-05-28 09:18:49 -0400600 def formfield_for_foreignkey(self, db_field, request, **kwargs):
601 if db_field.name == 'site':
602 if not request.user.is_admin:
603 # only show sites where user is an admin or pi
604 sites = set()
605 for site_privilege in SitePrivilege.objects.filer(user=request.user):
606 if site_privilege.role.role_type in ['admin', 'pi']:
607 sites.add(site_privilege.site)
608 kwargs['queryset'] = Site.objects.filter(site__in=list(sites))
609
610 if db_field.name == 'user':
611 if not request.user.is_admin:
612 # only show users from sites where caller has admin or pi role
613 roles = Role.objects.filter(role_type__in=['admin', 'pi'])
614 site_privileges = SitePrivilege.objects.filter(user=request.user).filter(role__in=roles)
615 sites = [site_privilege.site for site_privilege in site_privileges]
616 site_privileges = SitePrivilege.objects.filter(site__in=sites)
617 emails = [site_privilege.user.email for site_privilege in site_privileges]
618 users = User.objects.filter(email__in=emails)
619 kwargs['queryset'] = users
620
621 return super(SitePrivilegeAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)
622
Tony Mack04062832013-05-10 08:22:44 -0400623 def queryset(self, request):
624 # admins can see all privileges. Users can only see privileges at sites
Tony Mackc2835a92013-05-28 09:18:49 -0400625 # where they have the admin role or pi role.
Tony Mack04062832013-05-10 08:22:44 -0400626 qs = super(SitePrivilegeAdmin, self).queryset(request)
Tony Mack5b061472014-02-04 07:57:10 -0500627 #if not request.user.is_admin:
628 # roles = Role.objects.filter(role_type__in=['admin', 'pi'])
629 # site_privileges = SitePrivilege.objects.filter(user=request.user).filter(role__in=roles)
630 # login_bases = [site_privilege.site.login_base for site_privilege in site_privileges]
631 # sites = Site.objects.filter(login_base__in=login_bases)
632 # qs = qs.filter(site__in=sites)
Tony Mack04062832013-05-10 08:22:44 -0400633 return qs
634
Siobhan Tullyce652d02013-10-08 21:52:35 -0400635class SliceForm(forms.ModelForm):
636 class Meta:
637 model = Slice
638 widgets = {
639 'service': LinkedSelect
640 }
641
Tony Mack2bd5b412013-06-11 21:05:06 -0400642class SliceAdmin(PlanetStackBaseAdmin):
Siobhan Tullyce652d02013-10-08 21:52:35 -0400643 form = SliceForm
Tony Mack29bf5e82014-04-29 21:40:24 -0400644 fieldList = ['name', 'site', 'serviceClass', 'enabled','description', 'service', 'slice_url', 'max_slivers']
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500645 fieldsets = [('Slice Details', {'fields': fieldList, 'classes':['suit-tab suit-tab-general']}),]
Tony Mack29bf5e82014-04-29 21:40:24 -0400646 list_display = ('name', 'site','serviceClass', 'slice_url', 'max_slivers')
Siobhan Tully2d95e482013-09-06 10:56:06 -0400647 inlines = [SlicePrivilegeInline,SliverInline, TagInline, ReservationInline,SliceNetworkInline]
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400648
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500649 user_readonly_fields = fieldList
650 user_readonly_inlines = [SlicePrivilegeROInline,SliverROInline,TagROInline, ReservationROInline, SliceNetworkROInline]
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400651
652 suit_form_tabs =(('general', 'Slice Details'),
Siobhan Tully2d95e482013-09-06 10:56:06 -0400653 ('slicenetworks','Networks'),
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400654 ('sliceprivileges','Privileges'),
655 ('slivers','Slivers'),
656 ('tags','Tags'),
657 ('reservations','Reservations'),
658 )
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400659
Tony Mackc2835a92013-05-28 09:18:49 -0400660 def formfield_for_foreignkey(self, db_field, request, **kwargs):
661 if db_field.name == 'site':
Tony Mack5b061472014-02-04 07:57:10 -0500662 kwargs['queryset'] = Site.select_by_user(request.user)
663
Tony Mackc2835a92013-05-28 09:18:49 -0400664 return super(SliceAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)
665
Tony Mack04062832013-05-10 08:22:44 -0400666 def queryset(self, request):
667 # admins can see all keys. Users can only see slices they belong to.
Tony Mack5b061472014-02-04 07:57:10 -0500668 return Slice.select_by_user(request.user)
Tony Mack04062832013-05-10 08:22:44 -0400669
Tony Mack79748612013-05-01 14:52:03 -0400670 def get_formsets(self, request, obj=None):
671 for inline in self.get_inline_instances(request, obj):
672 # hide MyInline in the add view
673 if obj is None:
674 continue
Tony Mack2bd5b412013-06-11 21:05:06 -0400675 if isinstance(inline, SliverInline):
676 inline.model.caller = request.user
Tony Mack79748612013-05-01 14:52:03 -0400677 yield inline.get_formset(request, obj)
678
Tony Mack2bd5b412013-06-11 21:05:06 -0400679
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400680class SlicePrivilegeAdmin(PlanetStackBaseAdmin):
Tony Mack00d361f2013-04-28 10:28:42 -0400681 fieldsets = [
682 (None, {'fields': ['user', 'slice', 'role']})
683 ]
684 list_display = ('user', 'slice', 'role')
Tony Mack00d361f2013-04-28 10:28:42 -0400685
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500686 user_readonly_fields = ['user', 'slice', 'role']
687 user_readonly_inlines = []
688
Tony Mackc2835a92013-05-28 09:18:49 -0400689 def formfield_for_foreignkey(self, db_field, request, **kwargs):
690 if db_field.name == 'slice':
Tony Mack5b061472014-02-04 07:57:10 -0500691 kwargs['queryset'] = Slice.select_by_user(request.user)
Tony Mackc2835a92013-05-28 09:18:49 -0400692
693 if db_field.name == 'user':
Tony Mack5b061472014-02-04 07:57:10 -0500694 kwargs['queryset'] = User.select_by_user(request.user)
Tony Mackc2835a92013-05-28 09:18:49 -0400695
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400696 return super(SlicePrivilegeAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)
Tony Mackc2835a92013-05-28 09:18:49 -0400697
Tony Mack04062832013-05-10 08:22:44 -0400698 def queryset(self, request):
699 # admins can see all memberships. Users can only see memberships of
700 # slices where they have the admin role.
Tony Mack5b061472014-02-04 07:57:10 -0500701 return SlicePrivilege.select_by_user(request.user)
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400702
Tony Mack9bcbe4f2013-04-29 08:13:27 -0400703 def save_model(self, request, obj, form, change):
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.save()
709
710 def delete_model(self, request, obj):
Tony Mack951dab42013-05-02 19:51:45 -0400711 # update openstack connection to use this site/tenant
712 auth = request.session.get('auth', {})
713 auth['tenant'] = obj.slice.name
714 obj.os_manager = OpenStackManager(auth=auth, caller=request.user)
Tony Mack9bcbe4f2013-04-29 08:13:27 -0400715 obj.delete()
716
Siobhan Tully567e3e62013-06-21 18:03:16 -0400717
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400718class ImageAdmin(PlanetStackBaseAdmin):
719
720 fieldsets = [('Image Details',
Scott Baker00b00b32014-05-07 08:47:54 -0700721 {'fields': ['name', 'disk_format', 'container_format'],
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400722 'classes': ['suit-tab suit-tab-general']})
723 ]
724
725 suit_form_tabs =(('general','Image Details'),('slivers','Slivers'))
726
727 inlines = [SliverInline]
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500728
Tony Mack32e1ce32014-05-07 13:29:41 -0400729 user_readonly_fields = ['name', 'disk_format', 'container_format']
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500730 user_readonly_inlines = [SliverROInline]
731
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400732class NodeForm(forms.ModelForm):
733 class Meta:
734 widgets = {
735 'site': LinkedSelect,
736 'deployment': LinkedSelect
737 }
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400738
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500739class NodeAdmin(PlanetStackBaseAdmin):
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400740 form = NodeForm
Siobhan Tullybf1153a2013-05-27 20:53:48 -0400741 list_display = ('name', 'site', 'deployment')
742 list_filter = ('deployment',)
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500743
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400744 inlines = [TagInline,SliverInline]
745 fieldsets = [('Node Details', {'fields': ['name','site','deployment'], 'classes':['suit-tab suit-tab-details']})]
746
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500747 user_readonly_fields = ['name','site','deployment']
748 user_readonly_inlines = [TagInline,SliverInline]
749
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400750 suit_form_tabs =(('details','Node Details'),('slivers','Slivers'),('tags','Tags'))
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400751
Siobhan Tully567e3e62013-06-21 18:03:16 -0400752
Tony Mackd90cdbf2013-04-16 22:48:40 -0400753class SliverForm(forms.ModelForm):
754 class Meta:
Tony Mack1d6b85f2013-05-07 18:49:14 -0400755 model = Sliver
Tony Mackd90cdbf2013-04-16 22:48:40 -0400756 ip = forms.CharField(widget=PlainTextWidget)
Tony Mack18261812013-05-02 16:39:20 -0400757 instance_name = forms.CharField(widget=PlainTextWidget)
Tony Mackd90cdbf2013-04-16 22:48:40 -0400758 widgets = {
759 'ip': PlainTextWidget(),
Tony Mack18261812013-05-02 16:39:20 -0400760 'instance_name': PlainTextWidget(),
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400761 'slice': LinkedSelect,
762 'deploymentNetwork': LinkedSelect,
763 'node': LinkedSelect,
764 'image': LinkedSelect
Siobhan Tully53437282013-04-26 19:30:27 -0400765 }
Tony Mackd90cdbf2013-04-16 22:48:40 -0400766
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500767class TagAdmin(PlanetStackBaseAdmin):
Siobhan Tullyce652d02013-10-08 21:52:35 -0400768 list_display = ['service', 'name', 'value', 'content_type', 'content_object',]
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500769 user_readonly_fields = ['service', 'name', 'value', 'content_type', 'content_object',]
770 user_readonly_inlines = []
Siobhan Tullyd3515752013-06-21 16:34:53 -0400771
Tony Mack9bcbe4f2013-04-29 08:13:27 -0400772class SliverAdmin(PlanetStackBaseAdmin):
Tony Mackd90cdbf2013-04-16 22:48:40 -0400773 form = SliverForm
Tony Mackcdec0902013-04-15 00:38:49 -0400774 fieldsets = [
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400775 ('Sliver Details', {'fields': ['slice', 'deploymentNetwork', 'node', 'ip', 'instance_name', 'numberCores', 'image', ], 'classes': ['suit-tab suit-tab-general'], })
Tony Mackcdec0902013-04-15 00:38:49 -0400776 ]
Siobhan Tully5d7dc8d2013-07-02 13:17:33 -0400777 list_display = ['ip', 'instance_name', 'slice', 'numberCores', 'image', 'node', 'deploymentNetwork']
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400778
779 suit_form_tabs =(('general', 'Sliver Details'),
780 ('tags','Tags'),
781 )
782
Siobhan Tullyde5450d2013-06-21 11:35:33 -0400783 inlines = [TagInline]
Tony Mack53106f32013-04-27 16:43:01 -0400784
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500785 user_readonly_fields = ['slice', 'deploymentNetwork', 'node', 'ip', 'instance_name', 'numberCores', 'image']
786 user_readonly_inlines = [TagROInline]
787
Tony Mackc2835a92013-05-28 09:18:49 -0400788 def formfield_for_foreignkey(self, db_field, request, **kwargs):
789 if db_field.name == 'slice':
Tony Mack5b061472014-02-04 07:57:10 -0500790 kwargs['queryset'] = Slice.select_by_user(request.user)
Tony Mackc2835a92013-05-28 09:18:49 -0400791
792 return super(SliverAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)
793
Tony Mack04062832013-05-10 08:22:44 -0400794 def queryset(self, request):
795 # admins can see all slivers. Users can only see slivers of
796 # the slices they belong to.
Tony Mack5b061472014-02-04 07:57:10 -0500797 return Sliver.select_by_user(request.user)
798
Tony Mack04062832013-05-10 08:22:44 -0400799
Tony Mack1d6b85f2013-05-07 18:49:14 -0400800 def get_formsets(self, request, obj=None):
801 # make some fields read only if we are updating an existing record
802 if obj == None:
803 #self.readonly_fields = ('ip', 'instance_name')
804 self.readonly_fields = ()
805 else:
Tony Mack1e889462013-05-10 21:34:54 -0400806 self.readonly_fields = ()
807 #self.readonly_fields = ('ip', 'instance_name', 'slice', 'image', 'key')
Tony Mack1d6b85f2013-05-07 18:49:14 -0400808
809 for inline in self.get_inline_instances(request, obj):
810 # hide MyInline in the add view
811 if obj is None:
812 continue
Scott Baker526b71e2014-05-13 13:18:01 -0700813 if isinstance(inline, SliverInline):
814 inline.model.caller = request.user
815 yield inline.get_formset(request, obj)
Tony Mack53106f32013-04-27 16:43:01 -0400816
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500817 #def save_model(self, request, obj, form, change):
818 # # update openstack connection to use this site/tenant
819 # auth = request.session.get('auth', {})
820 # auth['tenant'] = obj.slice.name
821 # obj.os_manager = OpenStackManager(auth=auth, caller=request.user)
822 # obj.creator = request.user
823 # obj.save()
Tony Mack53106f32013-04-27 16:43:01 -0400824
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500825 #def delete_model(self, request, obj):
826 # # update openstack connection to use this site/tenant
827 # auth = request.session.get('auth', {})
828 # auth['tenant'] = obj.slice.name
829 # obj.os_manager = OpenStackManager(auth=auth, caller=request.user)
830 # obj.delete()
Tony Mackcdec0902013-04-15 00:38:49 -0400831
Siobhan Tully53437282013-04-26 19:30:27 -0400832class UserCreationForm(forms.ModelForm):
833 """A form for creating new users. Includes all the required
834 fields, plus a repeated password."""
835 password1 = forms.CharField(label='Password', widget=forms.PasswordInput)
836 password2 = forms.CharField(label='Password confirmation', widget=forms.PasswordInput)
837
838 class Meta:
Siobhan Tully30fd4292013-05-10 08:59:56 -0400839 model = User
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400840 fields = ('email', 'firstname', 'lastname', 'phone', 'public_key')
Siobhan Tully53437282013-04-26 19:30:27 -0400841
842 def clean_password2(self):
843 # Check that the two password entries match
844 password1 = self.cleaned_data.get("password1")
845 password2 = self.cleaned_data.get("password2")
846 if password1 and password2 and password1 != password2:
847 raise forms.ValidationError("Passwords don't match")
848 return password2
849
850 def save(self, commit=True):
851 # Save the provided password in hashed format
852 user = super(UserCreationForm, self).save(commit=False)
Tony Mackf9f4afb2013-05-01 21:02:12 -0400853 user.password = self.cleaned_data["password1"]
854 #user.set_password(self.cleaned_data["password1"])
Siobhan Tully53437282013-04-26 19:30:27 -0400855 if commit:
856 user.save()
857 return user
858
Siobhan Tully567e3e62013-06-21 18:03:16 -0400859
Siobhan Tully53437282013-04-26 19:30:27 -0400860class UserChangeForm(forms.ModelForm):
861 """A form for updating users. Includes all the fields on
862 the user, but replaces the password field with admin's
863 password hash display field.
864 """
Siobhan Tully63b7ba42014-01-12 10:35:11 -0500865 password = ReadOnlyPasswordHashField(label='Password',
866 help_text= '<a href=\"password/\">Change Password</a>.')
Siobhan Tully53437282013-04-26 19:30:27 -0400867
868 class Meta:
Siobhan Tully30fd4292013-05-10 08:59:56 -0400869 model = User
Siobhan Tully53437282013-04-26 19:30:27 -0400870
871 def clean_password(self):
872 # Regardless of what the user provides, return the initial value.
873 # This is done here, rather than on the field, because the
874 # field does not have access to the initial value
875 return self.initial["password"]
876
Scott Baker2c3cb642014-05-19 17:55:56 -0700877class UserDashboardViewInline(PlStackTabularInline):
878 model = UserDashboardView
879 extra = 0
880 suit_classes = 'suit-tab suit-tab-dashboards'
881 fields = ['user', 'dashboardView', 'order']
882
Tony Mack2bd5b412013-06-11 21:05:06 -0400883class UserAdmin(UserAdmin):
Siobhan Tully53437282013-04-26 19:30:27 -0400884 class Meta:
885 app_label = "core"
886
887 # The forms to add and change user instances
888 form = UserChangeForm
889 add_form = UserCreationForm
890
891 # The fields to be used in displaying the User model.
892 # These override the definitions on the base UserAdmin
893 # that reference specific fields on auth.User.
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500894 list_display = ('email', 'firstname', 'lastname', 'site', 'last_login')
Siobhan Tullyce652d02013-10-08 21:52:35 -0400895 #list_display = ('email', 'username','firstname', 'lastname', 'is_admin', 'last_login')
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500896 list_filter = ('site',)
Scott Baker2c3cb642014-05-19 17:55:56 -0700897 inlines = [SlicePrivilegeInline,SitePrivilegeInline,DeploymentPrivilegeInline,UserDashboardViewInline]
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500898
899 fieldListLoginDetails = ['email','site','password','is_readonly','is_amin','public_key']
900 fieldListContactInfo = ['firstname','lastname','phone','timezone']
901
Siobhan Tully53437282013-04-26 19:30:27 -0400902 fieldsets = (
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500903 ('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 -0400904 ('Contact Information', {'fields': ('firstname','lastname','phone', 'timezone'), 'classes':['suit-tab suit-tab-contact']}),
Scott Baker2c3cb642014-05-19 17:55:56 -0700905 #('Dashboard Views', {'fields': ('dashboards',), 'classes':['suit-tab suit-tab-dashboards']}),
Siobhan Tully53437282013-04-26 19:30:27 -0400906 #('Important dates', {'fields': ('last_login',)}),
907 )
908 add_fieldsets = (
909 (None, {
910 'classes': ('wide',),
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500911 'fields': ('email', 'firstname', 'lastname', 'is_readonly', 'phone', 'public_key','password1', 'password2')}
Siobhan Tully53437282013-04-26 19:30:27 -0400912 ),
913 )
914 search_fields = ('email',)
915 ordering = ('email',)
916 filter_horizontal = ()
917
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500918 user_readonly_fields = fieldListLoginDetails
919 user_readonly_inlines = [SlicePrivilegeROInline,SitePrivilegeROInline,DeploymentPrivilegeROInline]
920
Scott Baker2c3cb642014-05-19 17:55:56 -0700921 suit_form_tabs =(('general','Login Details'),
922 ('contact','Contact Information'),
923 ('sliceprivileges','Slice Privileges'),
924 ('siteprivileges','Site Privileges'),
925 ('deploymentprivileges','Deployment Privileges'),
926 ('dashboards','Dashboard Views'))
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400927
Tony Mackc2835a92013-05-28 09:18:49 -0400928 def formfield_for_foreignkey(self, db_field, request, **kwargs):
929 if db_field.name == 'site':
Tony Mack5b061472014-02-04 07:57:10 -0500930 kwargs['queryset'] = Site.select_by_user(request.user)
Tony Mackc2835a92013-05-28 09:18:49 -0400931
932 return super(UserAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)
933
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500934 def has_add_permission(self, request, obj=None):
935 return (not self.__user_is_readonly(request))
936
937 def has_delete_permission(self, request, obj=None):
938 return (not self.__user_is_readonly(request))
939
940 def get_actions(self,request):
941 actions = super(UserAdmin,self).get_actions(request)
942
943 if self.__user_is_readonly(request):
944 if 'delete_selected' in actions:
945 del actions['delete_selected']
946
947 return actions
948
949 def change_view(self,request,object_id, extra_context=None):
950
951 if self.__user_is_readonly(request):
952 self.readonly_fields=self.user_readonly_fields
953 self.inlines = self.user_readonly_inlines
954 try:
955 return super(UserAdmin, self).change_view(request, object_id, extra_context=extra_context)
956 except PermissionDenied:
957 pass
958 if request.method == 'POST':
959 raise PermissionDenied
960 request.readonly = True
961 return super(UserAdmin, self).change_view(request, object_id, extra_context=extra_context)
962
963 def __user_is_readonly(self, request):
964 #groups = [x.name for x in request.user.groups.all() ]
965 #return "readonly" in groups
966 return request.user.isReadOnlyUser()
967
Tony Mack5b061472014-02-04 07:57:10 -0500968 def queryset(self, request):
969 return User.select_by_user(request.user)
970
Scott Baker2c3cb642014-05-19 17:55:56 -0700971class DashboardViewAdmin(PlanetStackBaseAdmin):
972 fieldsets = [('Dashboard View Details',
973 {'fields': ['name', 'url'],
974 'classes': ['suit-tab suit-tab-general']})
975 ]
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500976
Scott Baker2c3cb642014-05-19 17:55:56 -0700977 suit_form_tabs =(('general','Dashboard View Details'),)
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500978
979class ServiceResourceROInline(ReadOnlyTabularInline):
980 model = ServiceResource
981 extra = 0
982 fields = ['serviceClass', 'name', 'maxUnitsDeployment', 'maxUnitsNode', 'maxDuration', 'bucketInRate', 'bucketMaxSize', 'cost', 'calendarReservable']
983
Scott Baker0165fac2014-01-13 11:49:26 -0800984class ServiceResourceInline(PlStackTabularInline):
Scott Baker3de3e372013-05-10 16:50:44 -0700985 model = ServiceResource
986 extra = 0
987
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500988class ServiceClassAdmin(PlanetStackBaseAdmin):
Scott Baker3de3e372013-05-10 16:50:44 -0700989 list_display = ('name', 'commitment', 'membershipFee')
990 inlines = [ServiceResourceInline]
991
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500992 user_readonly_fields = ['name', 'commitment', 'membershipFee']
993 user_readonly_inlines = []
994
995class ReservedResourceROInline(ReadOnlyTabularInline):
996 model = ReservedResource
997 extra = 0
998 fields = ['sliver', 'resource','quantity','reservationSet']
999 suit_classes = 'suit-tab suit-tab-reservedresources'
1000
Scott Baker0165fac2014-01-13 11:49:26 -08001001class ReservedResourceInline(PlStackTabularInline):
Scott Baker133c9212013-05-17 09:09:11 -07001002 model = ReservedResource
1003 extra = 0
Siobhan Tullybfd11dc2013-09-03 12:59:24 -04001004 suit_classes = 'suit-tab suit-tab-reservedresources'
Scott Baker133c9212013-05-17 09:09:11 -07001005
1006 def formfield_for_foreignkey(self, db_field, request=None, **kwargs):
1007 field = super(ReservedResourceInline, self).formfield_for_foreignkey(db_field, request, **kwargs)
1008
1009 if db_field.name == 'resource':
1010 # restrict resources to those that the slice's service class allows
1011 if request._slice is not None:
1012 field.queryset = field.queryset.filter(serviceClass = request._slice.serviceClass, calendarReservable=True)
1013 if len(field.queryset) > 0:
1014 field.initial = field.queryset.all()[0]
1015 else:
1016 field.queryset = field.queryset.none()
1017 elif db_field.name == 'sliver':
1018 # restrict slivers to those that belong to the slice
1019 if request._slice is not None:
1020 field.queryset = field.queryset.filter(slice = request._slice)
1021 else:
1022 field.queryset = field.queryset.none()
1023
1024 return field
1025
Tony Mack5b061472014-02-04 07:57:10 -05001026 def queryset(self, request):
1027 return ReservedResource.select_by_user(request.user)
1028
Scott Baker133c9212013-05-17 09:09:11 -07001029class ReservationChangeForm(forms.ModelForm):
1030 class Meta:
1031 model = Reservation
Siobhan Tullybfd11dc2013-09-03 12:59:24 -04001032 widgets = {
1033 'slice' : LinkedSelect
1034 }
Scott Baker133c9212013-05-17 09:09:11 -07001035
1036class ReservationAddForm(forms.ModelForm):
1037 slice = forms.ModelChoiceField(queryset=Slice.objects.all(), widget=forms.Select(attrs={"onChange":"document.getElementById('id_refresh').value=1; submit()"}))
1038 refresh = forms.CharField(widget=forms.HiddenInput())
1039
1040 class Media:
1041 css = {'all': ('planetstack.css',)} # .field-refresh { display: none; }
1042
1043 def clean_slice(self):
1044 slice = self.cleaned_data.get("slice")
1045 x = ServiceResource.objects.filter(serviceClass = slice.serviceClass, calendarReservable=True)
1046 if len(x) == 0:
1047 raise forms.ValidationError("The slice you selected does not have a service class that allows reservations")
1048 return slice
1049
1050 class Meta:
1051 model = Reservation
Siobhan Tullybfd11dc2013-09-03 12:59:24 -04001052 widgets = {
1053 'slice' : LinkedSelect
1054 }
1055
Scott Baker133c9212013-05-17 09:09:11 -07001056
1057class ReservationAddRefreshForm(ReservationAddForm):
1058 """ This form is displayed when the Reservation Form receives an update
1059 from the Slice dropdown onChange handler. It doesn't validate the
1060 data and doesn't save the data. This will cause the form to be
1061 redrawn.
1062 """
1063
Scott Baker8737e5f2013-05-17 09:35:32 -07001064 """ don't validate anything other than slice """
1065 dont_validate_fields = ("startTime", "duration")
1066
Scott Baker133c9212013-05-17 09:09:11 -07001067 def full_clean(self):
1068 result = super(ReservationAddForm, self).full_clean()
Scott Baker8737e5f2013-05-17 09:35:32 -07001069
1070 for fieldname in self.dont_validate_fields:
1071 if fieldname in self._errors:
1072 del self._errors[fieldname]
1073
Scott Baker133c9212013-05-17 09:09:11 -07001074 return result
1075
1076 """ don't save anything """
1077 def is_valid(self):
1078 return False
1079
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001080class ReservationAdmin(PlanetStackBaseAdmin):
1081 fieldList = ['slice', 'startTime', 'duration']
1082 fieldsets = [('Reservation Details', {'fields': fieldList, 'classes': ['suit-tab suit-tab-general']})]
Scott Baker133c9212013-05-17 09:09:11 -07001083 list_display = ('startTime', 'duration')
Scott Baker133c9212013-05-17 09:09:11 -07001084 form = ReservationAddForm
1085
Siobhan Tullybfd11dc2013-09-03 12:59:24 -04001086 suit_form_tabs = (('general','Reservation Details'), ('reservedresources','Reserved Resources'))
1087
1088 inlines = [ReservedResourceInline]
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001089 user_readonly_inlines = [ReservedResourceROInline]
1090 user_readonly_fields = fieldList
Siobhan Tullybfd11dc2013-09-03 12:59:24 -04001091
Scott Baker133c9212013-05-17 09:09:11 -07001092 def add_view(self, request, form_url='', extra_context=None):
Scott Bakeracd45142013-05-19 16:19:16 -07001093 timezone.activate(request.user.timezone)
Scott Baker133c9212013-05-17 09:09:11 -07001094 request._refresh = False
1095 request._slice = None
1096 if request.method == 'POST':
Scott Baker8737e5f2013-05-17 09:35:32 -07001097 # "refresh" will be set to "1" if the form was submitted due to
1098 # a change in the Slice dropdown.
Scott Baker133c9212013-05-17 09:09:11 -07001099 if request.POST.get("refresh","1") == "1":
1100 request._refresh = True
1101 request.POST["refresh"] = "0"
Scott Baker8737e5f2013-05-17 09:35:32 -07001102
1103 # Keep track of the slice that was selected, so the
1104 # reservedResource inline can filter items for the slice.
Scott Baker133c9212013-05-17 09:09:11 -07001105 request._slice = request.POST.get("slice",None)
1106 if (request._slice is not None):
1107 request._slice = Slice.objects.get(id=request._slice)
1108
1109 result = super(ReservationAdmin, self).add_view(request, form_url, extra_context)
1110 return result
1111
Scott Bakeracd45142013-05-19 16:19:16 -07001112 def changelist_view(self, request, extra_context = None):
1113 timezone.activate(request.user.timezone)
1114 return super(ReservationAdmin, self).changelist_view(request, extra_context)
1115
Scott Baker133c9212013-05-17 09:09:11 -07001116 def get_form(self, request, obj=None, **kwargs):
Siobhan Tullyd3515752013-06-21 16:34:53 -04001117 request._obj_ = obj
1118 if obj is not None:
1119 # For changes, set request._slice to the slice already set in the
1120 # object.
1121 request._slice = obj.slice
1122 self.form = ReservationChangeForm
1123 else:
1124 if getattr(request, "_refresh", False):
1125 self.form = ReservationAddRefreshForm
1126 else:
1127 self.form = ReservationAddForm
1128 return super(ReservationAdmin, self).get_form(request, obj, **kwargs)
1129
Scott Baker133c9212013-05-17 09:09:11 -07001130 def get_readonly_fields(self, request, obj=None):
Siobhan Tullyd3515752013-06-21 16:34:53 -04001131 if (obj is not None):
1132 # Prevent slice from being changed after the reservation has been
1133 # created.
1134 return ['slice']
1135 else:
Scott Baker133c9212013-05-17 09:09:11 -07001136 return []
Scott Baker3de3e372013-05-10 16:50:44 -07001137
Tony Mack5b061472014-02-04 07:57:10 -05001138 def queryset(self, request):
1139 return Reservation.select_by_user(request.user)
1140
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001141class NetworkParameterTypeAdmin(PlanetStackBaseAdmin):
Scott Baker74d8e622013-07-29 16:04:22 -07001142 list_display = ("name", )
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001143 user_readonly_fields = ['name']
1144 user_readonly_inlines = []
Scott Baker74d8e622013-07-29 16:04:22 -07001145
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001146class RouterAdmin(PlanetStackBaseAdmin):
Scott Baker74d8e622013-07-29 16:04:22 -07001147 list_display = ("name", )
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001148 user_readonly_fields = ['name']
1149 user_readonly_inlines = []
1150
1151class RouterROInline(ReadOnlyTabularInline):
1152 model = Router.networks.through
1153 extra = 0
1154 verbose_name_plural = "Routers"
1155 verbose_name = "Router"
1156 suit_classes = 'suit-tab suit-tab-routers'
1157
1158 fields = ['name', 'owner', 'permittedNetworks', 'networks']
Scott Baker74d8e622013-07-29 16:04:22 -07001159
Scott Baker0165fac2014-01-13 11:49:26 -08001160class RouterInline(PlStackTabularInline):
Scott Baker74d8e622013-07-29 16:04:22 -07001161 model = Router.networks.through
1162 extra = 0
1163 verbose_name_plural = "Routers"
1164 verbose_name = "Router"
Siobhan Tully2d95e482013-09-06 10:56:06 -04001165 suit_classes = 'suit-tab suit-tab-routers'
Scott Baker74d8e622013-07-29 16:04:22 -07001166
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001167class NetworkParameterROInline(ReadOnlyTabularInline):
1168 model = NetworkParameter
1169 extra = 1
1170 verbose_name_plural = "Parameters"
1171 verbose_name = "Parameter"
1172 suit_classes = 'suit-tab suit-tab-netparams'
1173 fields = ['parameter', 'value', 'content_type', 'object_id', 'content_object']
1174
Scott Baker74d8e622013-07-29 16:04:22 -07001175class NetworkParameterInline(generic.GenericTabularInline):
Scott Baker74d8e622013-07-29 16:04:22 -07001176 model = NetworkParameter
1177 extra = 1
1178 verbose_name_plural = "Parameters"
1179 verbose_name = "Parameter"
Siobhan Tully2d95e482013-09-06 10:56:06 -04001180 suit_classes = 'suit-tab suit-tab-netparams'
Scott Baker74d8e622013-07-29 16:04:22 -07001181
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001182class NetworkSliversROInline(ReadOnlyTabularInline):
1183 fields = ['network', 'sliver', 'ip', 'port_id']
1184 model = NetworkSliver
1185 extra = 0
1186 verbose_name_plural = "Slivers"
1187 verbose_name = "Sliver"
1188 suit_classes = 'suit-tab suit-tab-networkslivers'
1189
Scott Baker0165fac2014-01-13 11:49:26 -08001190class NetworkSliversInline(PlStackTabularInline):
Scott Baker74d8e622013-07-29 16:04:22 -07001191 readonly_fields = ("ip", )
1192 model = NetworkSliver
Scott Baker874936e2014-01-13 18:15:34 -08001193 selflink_fieldname = "sliver"
Scott Baker74d8e622013-07-29 16:04:22 -07001194 extra = 0
1195 verbose_name_plural = "Slivers"
1196 verbose_name = "Sliver"
Siobhan Tully2d95e482013-09-06 10:56:06 -04001197 suit_classes = 'suit-tab suit-tab-networkslivers'
Scott Baker74d8e622013-07-29 16:04:22 -07001198
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001199class NetworkSlicesROInline(ReadOnlyTabularInline):
1200 model = NetworkSlice
1201 extra = 0
1202 verbose_name_plural = "Slices"
1203 verbose_name = "Slice"
1204 suit_classes = 'suit-tab suit-tab-networkslices'
1205 fields = ['network','slice']
1206
Scott Baker0165fac2014-01-13 11:49:26 -08001207class NetworkSlicesInline(PlStackTabularInline):
Scott Bakerd7d2a392013-08-06 08:57:30 -07001208 model = NetworkSlice
Scott Baker874936e2014-01-13 18:15:34 -08001209 selflink_fieldname = "slice"
Scott Bakerd7d2a392013-08-06 08:57:30 -07001210 extra = 0
1211 verbose_name_plural = "Slices"
1212 verbose_name = "Slice"
Siobhan Tully2d95e482013-09-06 10:56:06 -04001213 suit_classes = 'suit-tab suit-tab-networkslices'
Scott Bakerd7d2a392013-08-06 08:57:30 -07001214
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001215class NetworkAdmin(PlanetStackBaseAdmin):
Scott Baker74d8e622013-07-29 16:04:22 -07001216 list_display = ("name", "subnet", "ports", "labels")
1217 readonly_fields = ("subnet", )
Siobhan Tully2d95e482013-09-06 10:56:06 -04001218
Scott Bakerd7d2a392013-08-06 08:57:30 -07001219 inlines = [NetworkParameterInline, NetworkSliversInline, NetworkSlicesInline, RouterInline]
Scott Baker74d8e622013-07-29 16:04:22 -07001220
Siobhan Tully2d95e482013-09-06 10:56:06 -04001221 fieldsets = [
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001222 (None, {'fields': ['name','template','ports','labels','owner','guaranteedBandwidth', 'permitAllSlices','permittedSlices','network_id','router_id','subnet_id','subnet'], 'classes':['suit-tab suit-tab-general']}),]
1223
1224 user_readonly_fields = ['name','template','ports','labels','owner','guaranteedBandwidth', 'permitAllSlices','permittedSlices','network_id','router_id','subnet_id','subnet']
1225 user_readonly_inlines = [NetworkParameterROInline, NetworkSliversROInline, NetworkSlicesROInline, RouterROInline]
Siobhan Tully2d95e482013-09-06 10:56:06 -04001226
1227 suit_form_tabs =(
1228 ('general','Network Details'),
1229 ('netparams', 'Parameters'),
1230 ('networkslivers','Slivers'),
1231 ('networkslices','Slices'),
1232 ('routers','Routers'),
1233 )
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001234class NetworkTemplateAdmin(PlanetStackBaseAdmin):
Scott Baker74d8e622013-07-29 16:04:22 -07001235 list_display = ("name", "guaranteedBandwidth", "visibility")
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001236 user_readonly_fields = ["name", "guaranteedBandwidth", "visibility"]
1237 user_readonly_inlines = []
Scott Baker74d8e622013-07-29 16:04:22 -07001238
Tony Mack31c2b8f2013-04-26 20:01:42 -04001239# register a signal that caches the user's credentials when they log in
1240def cache_credentials(sender, user, request, **kwds):
1241 auth = {'username': request.POST['username'],
1242 'password': request.POST['password']}
1243 request.session['auth'] = auth
1244user_logged_in.connect(cache_credentials)
1245
Scott Baker15cddfa2013-12-09 13:45:19 -08001246def dollar_field(fieldName, short_description):
1247 def newFunc(self, obj):
1248 try:
1249 x= "$ %0.2f" % float(getattr(obj, fieldName, 0.0))
1250 except:
1251 x=getattr(obj, fieldName, 0.0)
1252 return x
1253 newFunc.short_description = short_description
1254 return newFunc
1255
1256def right_dollar_field(fieldName, short_description):
1257 def newFunc(self, obj):
1258 try:
1259 #x= '<div align=right style="width:6em">$ %0.2f</div>' % float(getattr(obj, fieldName, 0.0))
1260 x= '<div align=right>$ %0.2f</div>' % float(getattr(obj, fieldName, 0.0))
1261 except:
1262 x=getattr(obj, fieldName, 0.0)
1263 return x
1264 newFunc.short_description = short_description
1265 newFunc.allow_tags = True
1266 return newFunc
Scott Baker43105042013-12-06 23:23:36 -08001267
Scott Baker0165fac2014-01-13 11:49:26 -08001268class InvoiceChargeInline(PlStackTabularInline):
Scott Baker43105042013-12-06 23:23:36 -08001269 model = Charge
Scott Baker15cddfa2013-12-09 13:45:19 -08001270 extra = 0
Scott Baker43105042013-12-06 23:23:36 -08001271 verbose_name_plural = "Charges"
1272 verbose_name = "Charge"
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001273 exclude = ['account']
Scott Baker9cb88a22013-12-09 18:56:00 -08001274 fields = ["date", "kind", "state", "object", "coreHours", "dollar_amount", "slice"]
1275 readonly_fields = ["date", "kind", "state", "object", "coreHours", "dollar_amount", "slice"]
1276 can_delete = False
1277 max_num = 0
1278
1279 dollar_amount = right_dollar_field("amount", "Amount")
Scott Baker43105042013-12-06 23:23:36 -08001280
1281class InvoiceAdmin(admin.ModelAdmin):
1282 list_display = ("date", "account")
1283
1284 inlines = [InvoiceChargeInline]
1285
Scott Baker9cb88a22013-12-09 18:56:00 -08001286 fields = ["date", "account", "dollar_amount"]
1287 readonly_fields = ["date", "account", "dollar_amount"]
1288
1289 dollar_amount = dollar_field("amount", "Amount")
Scott Baker43105042013-12-06 23:23:36 -08001290
Scott Baker0165fac2014-01-13 11:49:26 -08001291class InvoiceInline(PlStackTabularInline):
Scott Baker15cddfa2013-12-09 13:45:19 -08001292 model = Invoice
1293 extra = 0
1294 verbose_name_plural = "Invoices"
1295 verbose_name = "Invoice"
Scott Baker0165fac2014-01-13 11:49:26 -08001296 fields = ["date", "dollar_amount"]
1297 readonly_fields = ["date", "dollar_amount"]
Scott Baker15cddfa2013-12-09 13:45:19 -08001298 suit_classes = 'suit-tab suit-tab-accountinvoice'
1299 can_delete=False
1300 max_num=0
1301
1302 dollar_amount = right_dollar_field("amount", "Amount")
1303
Scott Baker0165fac2014-01-13 11:49:26 -08001304class PendingChargeInline(PlStackTabularInline):
Scott Baker43105042013-12-06 23:23:36 -08001305 model = Charge
Scott Baker15cddfa2013-12-09 13:45:19 -08001306 extra = 0
Scott Baker43105042013-12-06 23:23:36 -08001307 verbose_name_plural = "Charges"
1308 verbose_name = "Charge"
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001309 exclude = ["invoice"]
Scott Baker15cddfa2013-12-09 13:45:19 -08001310 fields = ["date", "kind", "state", "object", "coreHours", "dollar_amount", "slice"]
1311 readonly_fields = ["date", "kind", "state", "object", "coreHours", "dollar_amount", "slice"]
Scott Baker43105042013-12-06 23:23:36 -08001312 suit_classes = 'suit-tab suit-tab-accountpendingcharges'
Scott Baker15cddfa2013-12-09 13:45:19 -08001313 can_delete=False
1314 max_num=0
Scott Baker43105042013-12-06 23:23:36 -08001315
1316 def queryset(self, request):
1317 qs = super(PendingChargeInline, self).queryset(request)
1318 qs = qs.filter(state="pending")
1319 return qs
1320
Scott Baker15cddfa2013-12-09 13:45:19 -08001321 dollar_amount = right_dollar_field("amount", "Amount")
1322
Scott Baker0165fac2014-01-13 11:49:26 -08001323class PaymentInline(PlStackTabularInline):
Scott Baker43105042013-12-06 23:23:36 -08001324 model=Payment
1325 extra = 1
1326 verbose_name_plural = "Payments"
1327 verbose_name = "Payment"
Scott Baker15cddfa2013-12-09 13:45:19 -08001328 fields = ["date", "dollar_amount"]
1329 readonly_fields = ["date", "dollar_amount"]
Scott Baker43105042013-12-06 23:23:36 -08001330 suit_classes = 'suit-tab suit-tab-accountpayments'
Scott Baker15cddfa2013-12-09 13:45:19 -08001331 can_delete=False
1332 max_num=0
1333
1334 dollar_amount = right_dollar_field("amount", "Amount")
1335
Scott Baker43105042013-12-06 23:23:36 -08001336class AccountAdmin(admin.ModelAdmin):
1337 list_display = ("site", "balance_due")
1338
1339 inlines = [InvoiceInline, PaymentInline, PendingChargeInline]
1340
1341 fieldsets = [
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001342 (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 -08001343
Scott Baker15cddfa2013-12-09 13:45:19 -08001344 readonly_fields = ['site', 'dollar_balance_due', 'dollar_total_invoices', 'dollar_total_payments']
Scott Baker43105042013-12-06 23:23:36 -08001345
1346 suit_form_tabs =(
1347 ('general','Account Details'),
1348 ('accountinvoice', 'Invoices'),
1349 ('accountpayments', 'Payments'),
1350 ('accountpendingcharges','Pending Charges'),
1351 )
1352
Scott Baker15cddfa2013-12-09 13:45:19 -08001353 dollar_balance_due = dollar_field("balance_due", "Balance Due")
1354 dollar_total_invoices = dollar_field("total_invoices", "Total Invoices")
1355 dollar_total_payments = dollar_field("total_payments", "Total Payments")
1356
Siobhan Tullyce652d02013-10-08 21:52:35 -04001357
Siobhan Tully53437282013-04-26 19:30:27 -04001358# Now register the new UserAdmin...
Siobhan Tully30fd4292013-05-10 08:59:56 -04001359admin.site.register(User, UserAdmin)
Siobhan Tully53437282013-04-26 19:30:27 -04001360# ... and, since we're not using Django's builtin permissions,
1361# unregister the Group model from admin.
Siobhan Tullyce652d02013-10-08 21:52:35 -04001362#admin.site.unregister(Group)
Siobhan Tully53437282013-04-26 19:30:27 -04001363
Siobhan Tullybf1153a2013-05-27 20:53:48 -04001364#Do not show django evolution in the admin interface
1365from django_evolution.models import Version, Evolution
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001366#admin.site.unregister(Version)
1367#admin.site.unregister(Evolution)
Siobhan Tullybf1153a2013-05-27 20:53:48 -04001368
1369
1370# When debugging it is often easier to see all the classes, but for regular use
1371# only the top-levels should be displayed
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001372showAll = False
Scott Baker43105042013-12-06 23:23:36 -08001373
Siobhan Tullybf1153a2013-05-27 20:53:48 -04001374admin.site.register(Deployment, DeploymentAdmin)
Siobhan Tully4bc09f22013-04-10 21:15:21 -04001375admin.site.register(Site, SiteAdmin)
Siobhan Tully4bc09f22013-04-10 21:15:21 -04001376admin.site.register(Slice, SliceAdmin)
Siobhan Tullyce652d02013-10-08 21:52:35 -04001377admin.site.register(Service, ServiceAdmin)
smbakera3cf70c2013-06-27 02:01:41 -07001378admin.site.register(Reservation, ReservationAdmin)
Scott Baker74d8e622013-07-29 16:04:22 -07001379admin.site.register(Network, NetworkAdmin)
1380admin.site.register(Router, RouterAdmin)
Scott Baker74d8e622013-07-29 16:04:22 -07001381admin.site.register(NetworkTemplate, NetworkTemplateAdmin)
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001382admin.site.register(Account, AccountAdmin)
1383admin.site.register(Invoice, InvoiceAdmin)
Siobhan Tullybf1153a2013-05-27 20:53:48 -04001384
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001385if True:
1386 admin.site.register(NetworkParameterType, NetworkParameterTypeAdmin)
1387 admin.site.register(ServiceClass, ServiceClassAdmin)
Siobhan Tullybfd11dc2013-09-03 12:59:24 -04001388 #admin.site.register(PlanetStack)
Siobhan Tullyd3515752013-06-21 16:34:53 -04001389 admin.site.register(Tag, TagAdmin)
Siobhan Tullyce652d02013-10-08 21:52:35 -04001390 admin.site.register(DeploymentRole)
1391 admin.site.register(SiteRole)
1392 admin.site.register(SliceRole)
1393 admin.site.register(PlanetStackRole)
Siobhan Tullybf1153a2013-05-27 20:53:48 -04001394 admin.site.register(Node, NodeAdmin)
Siobhan Tullybfd11dc2013-09-03 12:59:24 -04001395 #admin.site.register(SlicePrivilege, SlicePrivilegeAdmin)
1396 #admin.site.register(SitePrivilege, SitePrivilegeAdmin)
Siobhan Tullybf1153a2013-05-27 20:53:48 -04001397 admin.site.register(Sliver, SliverAdmin)
Siobhan Tullybf1153a2013-05-27 20:53:48 -04001398 admin.site.register(Image, ImageAdmin)
Scott Baker2c3cb642014-05-19 17:55:56 -07001399 admin.site.register(DashboardView, DashboardViewAdmin)
Tony Mack7130ac32013-03-22 21:58:00 -04001400