blob: 5aeb784ae532c8ddb56b665c920a70401a134f7c [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:
Scott Bakerc9b14f72014-05-22 13:44:20 -0700469 self.fields['sites'].initial = [x.site for x in 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:
Scott Bakerc9b14f72014-05-22 13:44:20 -0700478 # save_m2m() doesn't seem to work with 'through' relations. So we
479 # create/destroy the through models ourselves. There has to be
480 # a better way...
481
482 sites = self.cleaned_data['sites']
483
484 existing_sites = []
485 for sdp in list(deployment.sitedeployments_set.all()):
486 if sdp.site not in sites:
487 #print "deleting site", sdp.site
488 sdp.delete()
489 else:
490 existing_sites.append(sdp.site)
491
492 for site in sites:
493 if site not in existing_sites:
494 #print "adding site", site
495 sdp = SiteDeployments(site=site, deployment=deployment)
496 sdp.save()
497
Siobhan Tully320b4622014-01-17 15:11:14 -0500498 self.save_m2m()
499
500 return deployment
501
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500502class SiteAssocInline(PlStackTabularInline):
503 model = Site.deployments.through
504 extra = 0
505 suit_classes = 'suit-tab suit-tab-sites'
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400506
Siobhan Tullybf1153a2013-05-27 20:53:48 -0400507class DeploymentAdmin(PlanetStackBaseAdmin):
508 form = DeploymentAdminForm
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500509 model = Deployment
510 fieldList = ['name','sites']
511 fieldsets = [(None, {'fields': fieldList, 'classes':['suit-tab suit-tab-sites']})]
Siobhan Tully2d95e482013-09-06 10:56:06 -0400512 inlines = [DeploymentPrivilegeInline,NodeInline,TagInline]
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500513
514 user_readonly_inlines = [DeploymentPrivilegeROInline,NodeROInline,TagROInline]
515 user_readonly_fields = ['name']
516
517 suit_form_tabs =(('sites','Deployment Details'),('nodes','Nodes'),('deploymentprivileges','Privileges'),('tags','Tags'))
518
519class ServiceAttrAsTabROInline(ReadOnlyTabularInline):
520 model = ServiceAttribute
521 fields = ['name','value']
522 extra = 0
523 suit_classes = 'suit-tab suit-tab-serviceattrs'
Tony Mack5cd13202013-05-01 21:48:38 -0400524
Siobhan Tullyce652d02013-10-08 21:52:35 -0400525class ServiceAttrAsTabInline(PlStackTabularInline):
526 model = ServiceAttribute
527 fields = ['name','value']
528 extra = 0
529 suit_classes = 'suit-tab suit-tab-serviceattrs'
530
Siobhan Tullyce652d02013-10-08 21:52:35 -0400531class ServiceAdmin(PlanetStackBaseAdmin):
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500532 list_display = ("name","description","versionNumber","enabled","published")
533 fieldList = ["name","description","versionNumber","enabled","published"]
534 fieldsets = [(None, {'fields': fieldList, 'classes':['suit-tab suit-tab-general']})]
535 inlines = [ServiceAttrAsTabInline,SliceInline]
536
537 user_readonly_fields = fieldList
538 user_readonly_inlines = [ServiceAttrAsTabROInline,SliceROInline]
539
540 suit_form_tabs =(('general', 'Service Details'),
541 ('slices','Slices'),
542 ('serviceattrs','Additional Attributes'),
543 )
Siobhan Tullyce652d02013-10-08 21:52:35 -0400544
Tony Mack0553f282013-06-10 22:54:50 -0400545class SiteAdmin(PlanetStackBaseAdmin):
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500546 fieldList = ['name', 'site_url', 'enabled', 'is_public', 'login_base', 'accountLink','location']
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400547 fieldsets = [
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500548 (None, {'fields': fieldList, 'classes':['suit-tab suit-tab-general']}),
Tony Macke4be32f2014-03-11 20:45:25 -0400549 #('Deployment Networks', {'fields': ['deployments'], 'classes':['suit-tab suit-tab-deployments']}),
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400550 ]
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400551 suit_form_tabs =(('general', 'Site Details'),
552 ('users','Users'),
Siobhan Tully2d95e482013-09-06 10:56:06 -0400553 ('siteprivileges','Privileges'),
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400554 ('deployments','Deployments'),
555 ('slices','Slices'),
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500556 ('nodes','Nodes'),
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400557 ('tags','Tags'),
558 )
Scott Baker545db2a2013-12-09 18:44:43 -0800559 readonly_fields = ['accountLink']
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500560
561 user_readonly_fields = ['name', 'deployments','site_url', 'enabled', 'is_public', 'login_base', 'accountLink']
Tony Macke4be32f2014-03-11 20:45:25 -0400562 user_readonly_inlines = [SliceROInline,UserROInline,TagROInline, NodeROInline, SitePrivilegeROInline,SiteDeploymentROInline]
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500563
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400564 list_display = ('name', 'login_base','site_url', 'enabled')
565 filter_horizontal = ('deployments',)
Tony Macke4be32f2014-03-11 20:45:25 -0400566 inlines = [SliceInline,UserInline,TagInline, NodeInline, SitePrivilegeInline, SiteDeploymentInline]
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400567 search_fields = ['name']
568
Tony Mack04062832013-05-10 08:22:44 -0400569 def queryset(self, request):
Tony Mack5b061472014-02-04 07:57:10 -0500570 #print dir(UserInline)
571 return Site.select_by_user(request.user)
Tony Mack04062832013-05-10 08:22:44 -0400572
Tony Mack5cd13202013-05-01 21:48:38 -0400573 def get_formsets(self, request, obj=None):
574 for inline in self.get_inline_instances(request, obj):
575 # hide MyInline in the add view
576 if obj is None:
577 continue
Tony Mack2bd5b412013-06-11 21:05:06 -0400578 if isinstance(inline, SliceInline):
579 inline.model.caller = request.user
580 yield inline.get_formset(request, obj)
581
582 def get_formsets(self, request, obj=None):
583 for inline in self.get_inline_instances(request, obj):
584 # hide MyInline in the add view
585 if obj is None:
586 continue
587 if isinstance(inline, SliverInline):
588 inline.model.caller = request.user
Tony Mack5cd13202013-05-01 21:48:38 -0400589 yield inline.get_formset(request, obj)
590
Scott Baker545db2a2013-12-09 18:44:43 -0800591 def accountLink(self, obj):
592 link_obj = obj.accounts.all()
593 if link_obj:
594 reverse_path = "admin:core_account_change"
595 url = reverse(reverse_path, args =(link_obj[0].id,))
596 return "<a href='%s'>%s</a>" % (url, "view billing details")
597 else:
598 return "no billing data for this site"
599 accountLink.allow_tags = True
600 accountLink.short_description = "Billing"
601
Tony Mack332ee1d2014-02-04 15:33:45 -0500602 def save_model(self, request, obj, form, change):
603 # update openstack connection to use this site/tenant
604 obj.save_by_user(request.user)
605
606 def delete_model(self, request, obj):
607 obj.delete_by_user(request.user)
608
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500609
Tony Mack9bcbe4f2013-04-29 08:13:27 -0400610class SitePrivilegeAdmin(PlanetStackBaseAdmin):
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500611 fieldList = ['user', 'site', 'role']
Tony Mack00d361f2013-04-28 10:28:42 -0400612 fieldsets = [
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500613 (None, {'fields': fieldList, 'classes':['collapse']})
Tony Mack00d361f2013-04-28 10:28:42 -0400614 ]
615 list_display = ('user', 'site', 'role')
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500616 user_readonly_fields = fieldList
617 user_readonly_inlines = []
Tony Mack00d361f2013-04-28 10:28:42 -0400618
Tony Mackc2835a92013-05-28 09:18:49 -0400619 def formfield_for_foreignkey(self, db_field, request, **kwargs):
620 if db_field.name == 'site':
621 if not request.user.is_admin:
622 # only show sites where user is an admin or pi
623 sites = set()
624 for site_privilege in SitePrivilege.objects.filer(user=request.user):
625 if site_privilege.role.role_type in ['admin', 'pi']:
626 sites.add(site_privilege.site)
627 kwargs['queryset'] = Site.objects.filter(site__in=list(sites))
628
629 if db_field.name == 'user':
630 if not request.user.is_admin:
631 # only show users from sites where caller has admin or pi role
632 roles = Role.objects.filter(role_type__in=['admin', 'pi'])
633 site_privileges = SitePrivilege.objects.filter(user=request.user).filter(role__in=roles)
634 sites = [site_privilege.site for site_privilege in site_privileges]
635 site_privileges = SitePrivilege.objects.filter(site__in=sites)
636 emails = [site_privilege.user.email for site_privilege in site_privileges]
637 users = User.objects.filter(email__in=emails)
638 kwargs['queryset'] = users
639
640 return super(SitePrivilegeAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)
641
Tony Mack04062832013-05-10 08:22:44 -0400642 def queryset(self, request):
643 # admins can see all privileges. Users can only see privileges at sites
Tony Mackc2835a92013-05-28 09:18:49 -0400644 # where they have the admin role or pi role.
Tony Mack04062832013-05-10 08:22:44 -0400645 qs = super(SitePrivilegeAdmin, self).queryset(request)
Tony Mack5b061472014-02-04 07:57:10 -0500646 #if not request.user.is_admin:
647 # roles = Role.objects.filter(role_type__in=['admin', 'pi'])
648 # site_privileges = SitePrivilege.objects.filter(user=request.user).filter(role__in=roles)
649 # login_bases = [site_privilege.site.login_base for site_privilege in site_privileges]
650 # sites = Site.objects.filter(login_base__in=login_bases)
651 # qs = qs.filter(site__in=sites)
Tony Mack04062832013-05-10 08:22:44 -0400652 return qs
653
Siobhan Tullyce652d02013-10-08 21:52:35 -0400654class SliceForm(forms.ModelForm):
655 class Meta:
656 model = Slice
657 widgets = {
658 'service': LinkedSelect
659 }
660
Tony Mack2bd5b412013-06-11 21:05:06 -0400661class SliceAdmin(PlanetStackBaseAdmin):
Siobhan Tullyce652d02013-10-08 21:52:35 -0400662 form = SliceForm
Tony Mack29bf5e82014-04-29 21:40:24 -0400663 fieldList = ['name', 'site', 'serviceClass', 'enabled','description', 'service', 'slice_url', 'max_slivers']
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500664 fieldsets = [('Slice Details', {'fields': fieldList, 'classes':['suit-tab suit-tab-general']}),]
Tony Mack29bf5e82014-04-29 21:40:24 -0400665 list_display = ('name', 'site','serviceClass', 'slice_url', 'max_slivers')
Siobhan Tully2d95e482013-09-06 10:56:06 -0400666 inlines = [SlicePrivilegeInline,SliverInline, TagInline, ReservationInline,SliceNetworkInline]
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400667
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500668 user_readonly_fields = fieldList
669 user_readonly_inlines = [SlicePrivilegeROInline,SliverROInline,TagROInline, ReservationROInline, SliceNetworkROInline]
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400670
671 suit_form_tabs =(('general', 'Slice Details'),
Siobhan Tully2d95e482013-09-06 10:56:06 -0400672 ('slicenetworks','Networks'),
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400673 ('sliceprivileges','Privileges'),
674 ('slivers','Slivers'),
675 ('tags','Tags'),
676 ('reservations','Reservations'),
677 )
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400678
Tony Mackc2835a92013-05-28 09:18:49 -0400679 def formfield_for_foreignkey(self, db_field, request, **kwargs):
680 if db_field.name == 'site':
Tony Mack5b061472014-02-04 07:57:10 -0500681 kwargs['queryset'] = Site.select_by_user(request.user)
682
Tony Mackc2835a92013-05-28 09:18:49 -0400683 return super(SliceAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)
684
Tony Mack04062832013-05-10 08:22:44 -0400685 def queryset(self, request):
686 # admins can see all keys. Users can only see slices they belong to.
Tony Mack5b061472014-02-04 07:57:10 -0500687 return Slice.select_by_user(request.user)
Tony Mack04062832013-05-10 08:22:44 -0400688
Tony Mack79748612013-05-01 14:52:03 -0400689 def get_formsets(self, request, obj=None):
690 for inline in self.get_inline_instances(request, obj):
691 # hide MyInline in the add view
692 if obj is None:
693 continue
Tony Mack2bd5b412013-06-11 21:05:06 -0400694 if isinstance(inline, SliverInline):
695 inline.model.caller = request.user
Tony Mack79748612013-05-01 14:52:03 -0400696 yield inline.get_formset(request, obj)
697
Tony Mack2bd5b412013-06-11 21:05:06 -0400698
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400699class SlicePrivilegeAdmin(PlanetStackBaseAdmin):
Tony Mack00d361f2013-04-28 10:28:42 -0400700 fieldsets = [
701 (None, {'fields': ['user', 'slice', 'role']})
702 ]
703 list_display = ('user', 'slice', 'role')
Tony Mack00d361f2013-04-28 10:28:42 -0400704
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500705 user_readonly_fields = ['user', 'slice', 'role']
706 user_readonly_inlines = []
707
Tony Mackc2835a92013-05-28 09:18:49 -0400708 def formfield_for_foreignkey(self, db_field, request, **kwargs):
709 if db_field.name == 'slice':
Tony Mack5b061472014-02-04 07:57:10 -0500710 kwargs['queryset'] = Slice.select_by_user(request.user)
Tony Mackc2835a92013-05-28 09:18:49 -0400711
712 if db_field.name == 'user':
Tony Mack5b061472014-02-04 07:57:10 -0500713 kwargs['queryset'] = User.select_by_user(request.user)
Tony Mackc2835a92013-05-28 09:18:49 -0400714
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400715 return super(SlicePrivilegeAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)
Tony Mackc2835a92013-05-28 09:18:49 -0400716
Tony Mack04062832013-05-10 08:22:44 -0400717 def queryset(self, request):
718 # admins can see all memberships. Users can only see memberships of
719 # slices where they have the admin role.
Tony Mack5b061472014-02-04 07:57:10 -0500720 return SlicePrivilege.select_by_user(request.user)
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400721
Tony Mack9bcbe4f2013-04-29 08:13:27 -0400722 def save_model(self, request, obj, form, change):
Tony Mack951dab42013-05-02 19:51:45 -0400723 # update openstack connection to use this site/tenant
724 auth = request.session.get('auth', {})
725 auth['tenant'] = obj.slice.name
726 obj.os_manager = OpenStackManager(auth=auth, caller=request.user)
Tony Mack9bcbe4f2013-04-29 08:13:27 -0400727 obj.save()
728
729 def delete_model(self, request, obj):
Tony Mack951dab42013-05-02 19:51:45 -0400730 # update openstack connection to use this site/tenant
731 auth = request.session.get('auth', {})
732 auth['tenant'] = obj.slice.name
733 obj.os_manager = OpenStackManager(auth=auth, caller=request.user)
Tony Mack9bcbe4f2013-04-29 08:13:27 -0400734 obj.delete()
735
Siobhan Tully567e3e62013-06-21 18:03:16 -0400736
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400737class ImageAdmin(PlanetStackBaseAdmin):
738
739 fieldsets = [('Image Details',
Scott Baker00b00b32014-05-07 08:47:54 -0700740 {'fields': ['name', 'disk_format', 'container_format'],
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400741 'classes': ['suit-tab suit-tab-general']})
742 ]
743
744 suit_form_tabs =(('general','Image Details'),('slivers','Slivers'))
745
746 inlines = [SliverInline]
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500747
Tony Mack32e1ce32014-05-07 13:29:41 -0400748 user_readonly_fields = ['name', 'disk_format', 'container_format']
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500749 user_readonly_inlines = [SliverROInline]
750
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400751class NodeForm(forms.ModelForm):
752 class Meta:
753 widgets = {
754 'site': LinkedSelect,
755 'deployment': LinkedSelect
756 }
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400757
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500758class NodeAdmin(PlanetStackBaseAdmin):
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400759 form = NodeForm
Siobhan Tullybf1153a2013-05-27 20:53:48 -0400760 list_display = ('name', 'site', 'deployment')
761 list_filter = ('deployment',)
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500762
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400763 inlines = [TagInline,SliverInline]
764 fieldsets = [('Node Details', {'fields': ['name','site','deployment'], 'classes':['suit-tab suit-tab-details']})]
765
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500766 user_readonly_fields = ['name','site','deployment']
767 user_readonly_inlines = [TagInline,SliverInline]
768
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400769 suit_form_tabs =(('details','Node Details'),('slivers','Slivers'),('tags','Tags'))
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400770
Siobhan Tully567e3e62013-06-21 18:03:16 -0400771
Tony Mackd90cdbf2013-04-16 22:48:40 -0400772class SliverForm(forms.ModelForm):
773 class Meta:
Tony Mack1d6b85f2013-05-07 18:49:14 -0400774 model = Sliver
Tony Mackd90cdbf2013-04-16 22:48:40 -0400775 ip = forms.CharField(widget=PlainTextWidget)
Tony Mack18261812013-05-02 16:39:20 -0400776 instance_name = forms.CharField(widget=PlainTextWidget)
Tony Mackd90cdbf2013-04-16 22:48:40 -0400777 widgets = {
778 'ip': PlainTextWidget(),
Tony Mack18261812013-05-02 16:39:20 -0400779 'instance_name': PlainTextWidget(),
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400780 'slice': LinkedSelect,
781 'deploymentNetwork': LinkedSelect,
782 'node': LinkedSelect,
783 'image': LinkedSelect
Siobhan Tully53437282013-04-26 19:30:27 -0400784 }
Tony Mackd90cdbf2013-04-16 22:48:40 -0400785
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500786class TagAdmin(PlanetStackBaseAdmin):
Siobhan Tullyce652d02013-10-08 21:52:35 -0400787 list_display = ['service', 'name', 'value', 'content_type', 'content_object',]
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500788 user_readonly_fields = ['service', 'name', 'value', 'content_type', 'content_object',]
789 user_readonly_inlines = []
Siobhan Tullyd3515752013-06-21 16:34:53 -0400790
Tony Mack9bcbe4f2013-04-29 08:13:27 -0400791class SliverAdmin(PlanetStackBaseAdmin):
Tony Mackd90cdbf2013-04-16 22:48:40 -0400792 form = SliverForm
Tony Mackcdec0902013-04-15 00:38:49 -0400793 fieldsets = [
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400794 ('Sliver Details', {'fields': ['slice', 'deploymentNetwork', 'node', 'ip', 'instance_name', 'numberCores', 'image', ], 'classes': ['suit-tab suit-tab-general'], })
Tony Mackcdec0902013-04-15 00:38:49 -0400795 ]
Siobhan Tully5d7dc8d2013-07-02 13:17:33 -0400796 list_display = ['ip', 'instance_name', 'slice', 'numberCores', 'image', 'node', 'deploymentNetwork']
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400797
798 suit_form_tabs =(('general', 'Sliver Details'),
799 ('tags','Tags'),
800 )
801
Siobhan Tullyde5450d2013-06-21 11:35:33 -0400802 inlines = [TagInline]
Tony Mack53106f32013-04-27 16:43:01 -0400803
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500804 user_readonly_fields = ['slice', 'deploymentNetwork', 'node', 'ip', 'instance_name', 'numberCores', 'image']
805 user_readonly_inlines = [TagROInline]
806
Tony Mackc2835a92013-05-28 09:18:49 -0400807 def formfield_for_foreignkey(self, db_field, request, **kwargs):
808 if db_field.name == 'slice':
Tony Mack5b061472014-02-04 07:57:10 -0500809 kwargs['queryset'] = Slice.select_by_user(request.user)
Tony Mackc2835a92013-05-28 09:18:49 -0400810
811 return super(SliverAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)
812
Tony Mack04062832013-05-10 08:22:44 -0400813 def queryset(self, request):
814 # admins can see all slivers. Users can only see slivers of
815 # the slices they belong to.
Tony Mack5b061472014-02-04 07:57:10 -0500816 return Sliver.select_by_user(request.user)
817
Tony Mack04062832013-05-10 08:22:44 -0400818
Tony Mack1d6b85f2013-05-07 18:49:14 -0400819 def get_formsets(self, request, obj=None):
820 # make some fields read only if we are updating an existing record
821 if obj == None:
822 #self.readonly_fields = ('ip', 'instance_name')
823 self.readonly_fields = ()
824 else:
Tony Mack1e889462013-05-10 21:34:54 -0400825 self.readonly_fields = ()
826 #self.readonly_fields = ('ip', 'instance_name', 'slice', 'image', 'key')
Tony Mack1d6b85f2013-05-07 18:49:14 -0400827
828 for inline in self.get_inline_instances(request, obj):
829 # hide MyInline in the add view
830 if obj is None:
831 continue
Scott Baker526b71e2014-05-13 13:18:01 -0700832 if isinstance(inline, SliverInline):
833 inline.model.caller = request.user
834 yield inline.get_formset(request, obj)
Tony Mack53106f32013-04-27 16:43:01 -0400835
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500836 #def save_model(self, request, obj, form, change):
837 # # update openstack connection to use this site/tenant
838 # auth = request.session.get('auth', {})
839 # auth['tenant'] = obj.slice.name
840 # obj.os_manager = OpenStackManager(auth=auth, caller=request.user)
841 # obj.creator = request.user
842 # obj.save()
Tony Mack53106f32013-04-27 16:43:01 -0400843
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500844 #def delete_model(self, request, obj):
845 # # update openstack connection to use this site/tenant
846 # auth = request.session.get('auth', {})
847 # auth['tenant'] = obj.slice.name
848 # obj.os_manager = OpenStackManager(auth=auth, caller=request.user)
849 # obj.delete()
Tony Mackcdec0902013-04-15 00:38:49 -0400850
Siobhan Tully53437282013-04-26 19:30:27 -0400851class UserCreationForm(forms.ModelForm):
852 """A form for creating new users. Includes all the required
853 fields, plus a repeated password."""
854 password1 = forms.CharField(label='Password', widget=forms.PasswordInput)
855 password2 = forms.CharField(label='Password confirmation', widget=forms.PasswordInput)
856
857 class Meta:
Siobhan Tully30fd4292013-05-10 08:59:56 -0400858 model = User
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400859 fields = ('email', 'firstname', 'lastname', 'phone', 'public_key')
Siobhan Tully53437282013-04-26 19:30:27 -0400860
861 def clean_password2(self):
862 # Check that the two password entries match
863 password1 = self.cleaned_data.get("password1")
864 password2 = self.cleaned_data.get("password2")
865 if password1 and password2 and password1 != password2:
866 raise forms.ValidationError("Passwords don't match")
867 return password2
868
869 def save(self, commit=True):
870 # Save the provided password in hashed format
871 user = super(UserCreationForm, self).save(commit=False)
Tony Mackf9f4afb2013-05-01 21:02:12 -0400872 user.password = self.cleaned_data["password1"]
873 #user.set_password(self.cleaned_data["password1"])
Siobhan Tully53437282013-04-26 19:30:27 -0400874 if commit:
875 user.save()
876 return user
877
Siobhan Tully567e3e62013-06-21 18:03:16 -0400878
Siobhan Tully53437282013-04-26 19:30:27 -0400879class UserChangeForm(forms.ModelForm):
880 """A form for updating users. Includes all the fields on
881 the user, but replaces the password field with admin's
882 password hash display field.
883 """
Siobhan Tully63b7ba42014-01-12 10:35:11 -0500884 password = ReadOnlyPasswordHashField(label='Password',
885 help_text= '<a href=\"password/\">Change Password</a>.')
Siobhan Tully53437282013-04-26 19:30:27 -0400886
887 class Meta:
Siobhan Tully30fd4292013-05-10 08:59:56 -0400888 model = User
Siobhan Tully53437282013-04-26 19:30:27 -0400889
890 def clean_password(self):
891 # Regardless of what the user provides, return the initial value.
892 # This is done here, rather than on the field, because the
893 # field does not have access to the initial value
894 return self.initial["password"]
895
Scott Baker2c3cb642014-05-19 17:55:56 -0700896class UserDashboardViewInline(PlStackTabularInline):
897 model = UserDashboardView
898 extra = 0
899 suit_classes = 'suit-tab suit-tab-dashboards'
900 fields = ['user', 'dashboardView', 'order']
901
Scott Bakered31f672014-05-21 18:14:03 -0700902class UserDashboardViewROInline(ReadOnlyTabularInline):
903 model = UserDashboardView
904 extra = 0
905 suit_classes = 'suit-tab suit-tab-dashboards'
906 fields = ['user', 'dashboardView', 'order']
907
Tony Mack2bd5b412013-06-11 21:05:06 -0400908class UserAdmin(UserAdmin):
Siobhan Tully53437282013-04-26 19:30:27 -0400909 class Meta:
910 app_label = "core"
911
912 # The forms to add and change user instances
913 form = UserChangeForm
914 add_form = UserCreationForm
915
916 # The fields to be used in displaying the User model.
917 # These override the definitions on the base UserAdmin
918 # that reference specific fields on auth.User.
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500919 list_display = ('email', 'firstname', 'lastname', 'site', 'last_login')
Siobhan Tullyce652d02013-10-08 21:52:35 -0400920 #list_display = ('email', 'username','firstname', 'lastname', 'is_admin', 'last_login')
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500921 list_filter = ('site',)
Scott Baker2c3cb642014-05-19 17:55:56 -0700922 inlines = [SlicePrivilegeInline,SitePrivilegeInline,DeploymentPrivilegeInline,UserDashboardViewInline]
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500923
924 fieldListLoginDetails = ['email','site','password','is_readonly','is_amin','public_key']
925 fieldListContactInfo = ['firstname','lastname','phone','timezone']
926
Siobhan Tully53437282013-04-26 19:30:27 -0400927 fieldsets = (
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500928 ('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 -0400929 ('Contact Information', {'fields': ('firstname','lastname','phone', 'timezone'), 'classes':['suit-tab suit-tab-contact']}),
Scott Baker2c3cb642014-05-19 17:55:56 -0700930 #('Dashboard Views', {'fields': ('dashboards',), 'classes':['suit-tab suit-tab-dashboards']}),
Siobhan Tully53437282013-04-26 19:30:27 -0400931 #('Important dates', {'fields': ('last_login',)}),
932 )
933 add_fieldsets = (
934 (None, {
935 'classes': ('wide',),
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500936 'fields': ('email', 'firstname', 'lastname', 'is_readonly', 'phone', 'public_key','password1', 'password2')}
Siobhan Tully53437282013-04-26 19:30:27 -0400937 ),
938 )
939 search_fields = ('email',)
940 ordering = ('email',)
941 filter_horizontal = ()
942
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500943 user_readonly_fields = fieldListLoginDetails
Scott Bakered31f672014-05-21 18:14:03 -0700944 user_readonly_inlines = [SlicePrivilegeROInline,SitePrivilegeROInline,DeploymentPrivilegeROInline,UserDashboardViewROInline]
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500945
Scott Baker2c3cb642014-05-19 17:55:56 -0700946 suit_form_tabs =(('general','Login Details'),
947 ('contact','Contact Information'),
948 ('sliceprivileges','Slice Privileges'),
949 ('siteprivileges','Site Privileges'),
950 ('deploymentprivileges','Deployment Privileges'),
951 ('dashboards','Dashboard Views'))
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400952
Tony Mackc2835a92013-05-28 09:18:49 -0400953 def formfield_for_foreignkey(self, db_field, request, **kwargs):
954 if db_field.name == 'site':
Tony Mack5b061472014-02-04 07:57:10 -0500955 kwargs['queryset'] = Site.select_by_user(request.user)
Tony Mackc2835a92013-05-28 09:18:49 -0400956
957 return super(UserAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)
958
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500959 def has_add_permission(self, request, obj=None):
960 return (not self.__user_is_readonly(request))
961
962 def has_delete_permission(self, request, obj=None):
963 return (not self.__user_is_readonly(request))
964
965 def get_actions(self,request):
966 actions = super(UserAdmin,self).get_actions(request)
967
968 if self.__user_is_readonly(request):
969 if 'delete_selected' in actions:
970 del actions['delete_selected']
971
972 return actions
973
974 def change_view(self,request,object_id, extra_context=None):
975
976 if self.__user_is_readonly(request):
977 self.readonly_fields=self.user_readonly_fields
978 self.inlines = self.user_readonly_inlines
979 try:
980 return super(UserAdmin, self).change_view(request, object_id, extra_context=extra_context)
981 except PermissionDenied:
982 pass
983 if request.method == 'POST':
984 raise PermissionDenied
985 request.readonly = True
986 return super(UserAdmin, self).change_view(request, object_id, extra_context=extra_context)
987
988 def __user_is_readonly(self, request):
989 #groups = [x.name for x in request.user.groups.all() ]
990 #return "readonly" in groups
991 return request.user.isReadOnlyUser()
992
Tony Mack5b061472014-02-04 07:57:10 -0500993 def queryset(self, request):
994 return User.select_by_user(request.user)
995
Scott Baker2c3cb642014-05-19 17:55:56 -0700996class DashboardViewAdmin(PlanetStackBaseAdmin):
997 fieldsets = [('Dashboard View Details',
998 {'fields': ['name', 'url'],
999 'classes': ['suit-tab suit-tab-general']})
1000 ]
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001001
Scott Baker2c3cb642014-05-19 17:55:56 -07001002 suit_form_tabs =(('general','Dashboard View Details'),)
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001003
1004class ServiceResourceROInline(ReadOnlyTabularInline):
1005 model = ServiceResource
1006 extra = 0
1007 fields = ['serviceClass', 'name', 'maxUnitsDeployment', 'maxUnitsNode', 'maxDuration', 'bucketInRate', 'bucketMaxSize', 'cost', 'calendarReservable']
1008
Scott Baker0165fac2014-01-13 11:49:26 -08001009class ServiceResourceInline(PlStackTabularInline):
Scott Baker3de3e372013-05-10 16:50:44 -07001010 model = ServiceResource
1011 extra = 0
1012
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001013class ServiceClassAdmin(PlanetStackBaseAdmin):
Scott Baker3de3e372013-05-10 16:50:44 -07001014 list_display = ('name', 'commitment', 'membershipFee')
1015 inlines = [ServiceResourceInline]
1016
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001017 user_readonly_fields = ['name', 'commitment', 'membershipFee']
1018 user_readonly_inlines = []
1019
1020class ReservedResourceROInline(ReadOnlyTabularInline):
1021 model = ReservedResource
1022 extra = 0
1023 fields = ['sliver', 'resource','quantity','reservationSet']
1024 suit_classes = 'suit-tab suit-tab-reservedresources'
1025
Scott Baker0165fac2014-01-13 11:49:26 -08001026class ReservedResourceInline(PlStackTabularInline):
Scott Baker133c9212013-05-17 09:09:11 -07001027 model = ReservedResource
1028 extra = 0
Siobhan Tullybfd11dc2013-09-03 12:59:24 -04001029 suit_classes = 'suit-tab suit-tab-reservedresources'
Scott Baker133c9212013-05-17 09:09:11 -07001030
1031 def formfield_for_foreignkey(self, db_field, request=None, **kwargs):
1032 field = super(ReservedResourceInline, self).formfield_for_foreignkey(db_field, request, **kwargs)
1033
1034 if db_field.name == 'resource':
1035 # restrict resources to those that the slice's service class allows
1036 if request._slice is not None:
1037 field.queryset = field.queryset.filter(serviceClass = request._slice.serviceClass, calendarReservable=True)
1038 if len(field.queryset) > 0:
1039 field.initial = field.queryset.all()[0]
1040 else:
1041 field.queryset = field.queryset.none()
1042 elif db_field.name == 'sliver':
1043 # restrict slivers to those that belong to the slice
1044 if request._slice is not None:
1045 field.queryset = field.queryset.filter(slice = request._slice)
1046 else:
1047 field.queryset = field.queryset.none()
1048
1049 return field
1050
Tony Mack5b061472014-02-04 07:57:10 -05001051 def queryset(self, request):
1052 return ReservedResource.select_by_user(request.user)
1053
Scott Baker133c9212013-05-17 09:09:11 -07001054class ReservationChangeForm(forms.ModelForm):
1055 class Meta:
1056 model = Reservation
Siobhan Tullybfd11dc2013-09-03 12:59:24 -04001057 widgets = {
1058 'slice' : LinkedSelect
1059 }
Scott Baker133c9212013-05-17 09:09:11 -07001060
1061class ReservationAddForm(forms.ModelForm):
1062 slice = forms.ModelChoiceField(queryset=Slice.objects.all(), widget=forms.Select(attrs={"onChange":"document.getElementById('id_refresh').value=1; submit()"}))
1063 refresh = forms.CharField(widget=forms.HiddenInput())
1064
1065 class Media:
1066 css = {'all': ('planetstack.css',)} # .field-refresh { display: none; }
1067
1068 def clean_slice(self):
1069 slice = self.cleaned_data.get("slice")
1070 x = ServiceResource.objects.filter(serviceClass = slice.serviceClass, calendarReservable=True)
1071 if len(x) == 0:
1072 raise forms.ValidationError("The slice you selected does not have a service class that allows reservations")
1073 return slice
1074
1075 class Meta:
1076 model = Reservation
Siobhan Tullybfd11dc2013-09-03 12:59:24 -04001077 widgets = {
1078 'slice' : LinkedSelect
1079 }
1080
Scott Baker133c9212013-05-17 09:09:11 -07001081
1082class ReservationAddRefreshForm(ReservationAddForm):
1083 """ This form is displayed when the Reservation Form receives an update
1084 from the Slice dropdown onChange handler. It doesn't validate the
1085 data and doesn't save the data. This will cause the form to be
1086 redrawn.
1087 """
1088
Scott Baker8737e5f2013-05-17 09:35:32 -07001089 """ don't validate anything other than slice """
1090 dont_validate_fields = ("startTime", "duration")
1091
Scott Baker133c9212013-05-17 09:09:11 -07001092 def full_clean(self):
1093 result = super(ReservationAddForm, self).full_clean()
Scott Baker8737e5f2013-05-17 09:35:32 -07001094
1095 for fieldname in self.dont_validate_fields:
1096 if fieldname in self._errors:
1097 del self._errors[fieldname]
1098
Scott Baker133c9212013-05-17 09:09:11 -07001099 return result
1100
1101 """ don't save anything """
1102 def is_valid(self):
1103 return False
1104
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001105class ReservationAdmin(PlanetStackBaseAdmin):
1106 fieldList = ['slice', 'startTime', 'duration']
1107 fieldsets = [('Reservation Details', {'fields': fieldList, 'classes': ['suit-tab suit-tab-general']})]
Scott Baker133c9212013-05-17 09:09:11 -07001108 list_display = ('startTime', 'duration')
Scott Baker133c9212013-05-17 09:09:11 -07001109 form = ReservationAddForm
1110
Siobhan Tullybfd11dc2013-09-03 12:59:24 -04001111 suit_form_tabs = (('general','Reservation Details'), ('reservedresources','Reserved Resources'))
1112
1113 inlines = [ReservedResourceInline]
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001114 user_readonly_inlines = [ReservedResourceROInline]
1115 user_readonly_fields = fieldList
Siobhan Tullybfd11dc2013-09-03 12:59:24 -04001116
Scott Baker133c9212013-05-17 09:09:11 -07001117 def add_view(self, request, form_url='', extra_context=None):
Scott Bakeracd45142013-05-19 16:19:16 -07001118 timezone.activate(request.user.timezone)
Scott Baker133c9212013-05-17 09:09:11 -07001119 request._refresh = False
1120 request._slice = None
1121 if request.method == 'POST':
Scott Baker8737e5f2013-05-17 09:35:32 -07001122 # "refresh" will be set to "1" if the form was submitted due to
1123 # a change in the Slice dropdown.
Scott Baker133c9212013-05-17 09:09:11 -07001124 if request.POST.get("refresh","1") == "1":
1125 request._refresh = True
1126 request.POST["refresh"] = "0"
Scott Baker8737e5f2013-05-17 09:35:32 -07001127
1128 # Keep track of the slice that was selected, so the
1129 # reservedResource inline can filter items for the slice.
Scott Baker133c9212013-05-17 09:09:11 -07001130 request._slice = request.POST.get("slice",None)
1131 if (request._slice is not None):
1132 request._slice = Slice.objects.get(id=request._slice)
1133
1134 result = super(ReservationAdmin, self).add_view(request, form_url, extra_context)
1135 return result
1136
Scott Bakeracd45142013-05-19 16:19:16 -07001137 def changelist_view(self, request, extra_context = None):
1138 timezone.activate(request.user.timezone)
1139 return super(ReservationAdmin, self).changelist_view(request, extra_context)
1140
Scott Baker133c9212013-05-17 09:09:11 -07001141 def get_form(self, request, obj=None, **kwargs):
Siobhan Tullyd3515752013-06-21 16:34:53 -04001142 request._obj_ = obj
1143 if obj is not None:
1144 # For changes, set request._slice to the slice already set in the
1145 # object.
1146 request._slice = obj.slice
1147 self.form = ReservationChangeForm
1148 else:
1149 if getattr(request, "_refresh", False):
1150 self.form = ReservationAddRefreshForm
1151 else:
1152 self.form = ReservationAddForm
1153 return super(ReservationAdmin, self).get_form(request, obj, **kwargs)
1154
Scott Baker133c9212013-05-17 09:09:11 -07001155 def get_readonly_fields(self, request, obj=None):
Siobhan Tullyd3515752013-06-21 16:34:53 -04001156 if (obj is not None):
1157 # Prevent slice from being changed after the reservation has been
1158 # created.
1159 return ['slice']
1160 else:
Scott Baker133c9212013-05-17 09:09:11 -07001161 return []
Scott Baker3de3e372013-05-10 16:50:44 -07001162
Tony Mack5b061472014-02-04 07:57:10 -05001163 def queryset(self, request):
1164 return Reservation.select_by_user(request.user)
1165
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001166class NetworkParameterTypeAdmin(PlanetStackBaseAdmin):
Scott Baker74d8e622013-07-29 16:04:22 -07001167 list_display = ("name", )
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001168 user_readonly_fields = ['name']
1169 user_readonly_inlines = []
Scott Baker74d8e622013-07-29 16:04:22 -07001170
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001171class RouterAdmin(PlanetStackBaseAdmin):
Scott Baker74d8e622013-07-29 16:04:22 -07001172 list_display = ("name", )
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001173 user_readonly_fields = ['name']
1174 user_readonly_inlines = []
1175
1176class RouterROInline(ReadOnlyTabularInline):
1177 model = Router.networks.through
1178 extra = 0
1179 verbose_name_plural = "Routers"
1180 verbose_name = "Router"
1181 suit_classes = 'suit-tab suit-tab-routers'
1182
1183 fields = ['name', 'owner', 'permittedNetworks', 'networks']
Scott Baker74d8e622013-07-29 16:04:22 -07001184
Scott Baker0165fac2014-01-13 11:49:26 -08001185class RouterInline(PlStackTabularInline):
Scott Baker74d8e622013-07-29 16:04:22 -07001186 model = Router.networks.through
1187 extra = 0
1188 verbose_name_plural = "Routers"
1189 verbose_name = "Router"
Siobhan Tully2d95e482013-09-06 10:56:06 -04001190 suit_classes = 'suit-tab suit-tab-routers'
Scott Baker74d8e622013-07-29 16:04:22 -07001191
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001192class NetworkParameterROInline(ReadOnlyTabularInline):
1193 model = NetworkParameter
1194 extra = 1
1195 verbose_name_plural = "Parameters"
1196 verbose_name = "Parameter"
1197 suit_classes = 'suit-tab suit-tab-netparams'
1198 fields = ['parameter', 'value', 'content_type', 'object_id', 'content_object']
1199
Scott Baker74d8e622013-07-29 16:04:22 -07001200class NetworkParameterInline(generic.GenericTabularInline):
Scott Baker74d8e622013-07-29 16:04:22 -07001201 model = NetworkParameter
1202 extra = 1
1203 verbose_name_plural = "Parameters"
1204 verbose_name = "Parameter"
Siobhan Tully2d95e482013-09-06 10:56:06 -04001205 suit_classes = 'suit-tab suit-tab-netparams'
Scott Baker74d8e622013-07-29 16:04:22 -07001206
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001207class NetworkSliversROInline(ReadOnlyTabularInline):
1208 fields = ['network', 'sliver', 'ip', 'port_id']
1209 model = NetworkSliver
1210 extra = 0
1211 verbose_name_plural = "Slivers"
1212 verbose_name = "Sliver"
1213 suit_classes = 'suit-tab suit-tab-networkslivers'
1214
Scott Baker0165fac2014-01-13 11:49:26 -08001215class NetworkSliversInline(PlStackTabularInline):
Scott Baker74d8e622013-07-29 16:04:22 -07001216 readonly_fields = ("ip", )
1217 model = NetworkSliver
Scott Baker874936e2014-01-13 18:15:34 -08001218 selflink_fieldname = "sliver"
Scott Baker74d8e622013-07-29 16:04:22 -07001219 extra = 0
1220 verbose_name_plural = "Slivers"
1221 verbose_name = "Sliver"
Siobhan Tully2d95e482013-09-06 10:56:06 -04001222 suit_classes = 'suit-tab suit-tab-networkslivers'
Scott Baker74d8e622013-07-29 16:04:22 -07001223
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001224class NetworkSlicesROInline(ReadOnlyTabularInline):
1225 model = NetworkSlice
1226 extra = 0
1227 verbose_name_plural = "Slices"
1228 verbose_name = "Slice"
1229 suit_classes = 'suit-tab suit-tab-networkslices'
1230 fields = ['network','slice']
1231
Scott Baker0165fac2014-01-13 11:49:26 -08001232class NetworkSlicesInline(PlStackTabularInline):
Scott Bakerd7d2a392013-08-06 08:57:30 -07001233 model = NetworkSlice
Scott Baker874936e2014-01-13 18:15:34 -08001234 selflink_fieldname = "slice"
Scott Bakerd7d2a392013-08-06 08:57:30 -07001235 extra = 0
1236 verbose_name_plural = "Slices"
1237 verbose_name = "Slice"
Siobhan Tully2d95e482013-09-06 10:56:06 -04001238 suit_classes = 'suit-tab suit-tab-networkslices'
Scott Bakerd7d2a392013-08-06 08:57:30 -07001239
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001240class NetworkAdmin(PlanetStackBaseAdmin):
Scott Baker74d8e622013-07-29 16:04:22 -07001241 list_display = ("name", "subnet", "ports", "labels")
1242 readonly_fields = ("subnet", )
Siobhan Tully2d95e482013-09-06 10:56:06 -04001243
Scott Bakerd7d2a392013-08-06 08:57:30 -07001244 inlines = [NetworkParameterInline, NetworkSliversInline, NetworkSlicesInline, RouterInline]
Scott Baker74d8e622013-07-29 16:04:22 -07001245
Siobhan Tully2d95e482013-09-06 10:56:06 -04001246 fieldsets = [
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001247 (None, {'fields': ['name','template','ports','labels','owner','guaranteedBandwidth', 'permitAllSlices','permittedSlices','network_id','router_id','subnet_id','subnet'], 'classes':['suit-tab suit-tab-general']}),]
1248
1249 user_readonly_fields = ['name','template','ports','labels','owner','guaranteedBandwidth', 'permitAllSlices','permittedSlices','network_id','router_id','subnet_id','subnet']
1250 user_readonly_inlines = [NetworkParameterROInline, NetworkSliversROInline, NetworkSlicesROInline, RouterROInline]
Siobhan Tully2d95e482013-09-06 10:56:06 -04001251
1252 suit_form_tabs =(
1253 ('general','Network Details'),
1254 ('netparams', 'Parameters'),
1255 ('networkslivers','Slivers'),
1256 ('networkslices','Slices'),
1257 ('routers','Routers'),
1258 )
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001259class NetworkTemplateAdmin(PlanetStackBaseAdmin):
Scott Baker74d8e622013-07-29 16:04:22 -07001260 list_display = ("name", "guaranteedBandwidth", "visibility")
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001261 user_readonly_fields = ["name", "guaranteedBandwidth", "visibility"]
1262 user_readonly_inlines = []
Scott Baker74d8e622013-07-29 16:04:22 -07001263
Tony Mack31c2b8f2013-04-26 20:01:42 -04001264# register a signal that caches the user's credentials when they log in
1265def cache_credentials(sender, user, request, **kwds):
1266 auth = {'username': request.POST['username'],
1267 'password': request.POST['password']}
1268 request.session['auth'] = auth
1269user_logged_in.connect(cache_credentials)
1270
Scott Baker15cddfa2013-12-09 13:45:19 -08001271def dollar_field(fieldName, short_description):
1272 def newFunc(self, obj):
1273 try:
1274 x= "$ %0.2f" % float(getattr(obj, fieldName, 0.0))
1275 except:
1276 x=getattr(obj, fieldName, 0.0)
1277 return x
1278 newFunc.short_description = short_description
1279 return newFunc
1280
1281def right_dollar_field(fieldName, short_description):
1282 def newFunc(self, obj):
1283 try:
1284 #x= '<div align=right style="width:6em">$ %0.2f</div>' % float(getattr(obj, fieldName, 0.0))
1285 x= '<div align=right>$ %0.2f</div>' % float(getattr(obj, fieldName, 0.0))
1286 except:
1287 x=getattr(obj, fieldName, 0.0)
1288 return x
1289 newFunc.short_description = short_description
1290 newFunc.allow_tags = True
1291 return newFunc
Scott Baker43105042013-12-06 23:23:36 -08001292
Scott Baker0165fac2014-01-13 11:49:26 -08001293class InvoiceChargeInline(PlStackTabularInline):
Scott Baker43105042013-12-06 23:23:36 -08001294 model = Charge
Scott Baker15cddfa2013-12-09 13:45:19 -08001295 extra = 0
Scott Baker43105042013-12-06 23:23:36 -08001296 verbose_name_plural = "Charges"
1297 verbose_name = "Charge"
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001298 exclude = ['account']
Scott Baker9cb88a22013-12-09 18:56:00 -08001299 fields = ["date", "kind", "state", "object", "coreHours", "dollar_amount", "slice"]
1300 readonly_fields = ["date", "kind", "state", "object", "coreHours", "dollar_amount", "slice"]
1301 can_delete = False
1302 max_num = 0
1303
1304 dollar_amount = right_dollar_field("amount", "Amount")
Scott Baker43105042013-12-06 23:23:36 -08001305
1306class InvoiceAdmin(admin.ModelAdmin):
1307 list_display = ("date", "account")
1308
1309 inlines = [InvoiceChargeInline]
1310
Scott Baker9cb88a22013-12-09 18:56:00 -08001311 fields = ["date", "account", "dollar_amount"]
1312 readonly_fields = ["date", "account", "dollar_amount"]
1313
1314 dollar_amount = dollar_field("amount", "Amount")
Scott Baker43105042013-12-06 23:23:36 -08001315
Scott Baker0165fac2014-01-13 11:49:26 -08001316class InvoiceInline(PlStackTabularInline):
Scott Baker15cddfa2013-12-09 13:45:19 -08001317 model = Invoice
1318 extra = 0
1319 verbose_name_plural = "Invoices"
1320 verbose_name = "Invoice"
Scott Baker0165fac2014-01-13 11:49:26 -08001321 fields = ["date", "dollar_amount"]
1322 readonly_fields = ["date", "dollar_amount"]
Scott Baker15cddfa2013-12-09 13:45:19 -08001323 suit_classes = 'suit-tab suit-tab-accountinvoice'
1324 can_delete=False
1325 max_num=0
1326
1327 dollar_amount = right_dollar_field("amount", "Amount")
1328
Scott Baker0165fac2014-01-13 11:49:26 -08001329class PendingChargeInline(PlStackTabularInline):
Scott Baker43105042013-12-06 23:23:36 -08001330 model = Charge
Scott Baker15cddfa2013-12-09 13:45:19 -08001331 extra = 0
Scott Baker43105042013-12-06 23:23:36 -08001332 verbose_name_plural = "Charges"
1333 verbose_name = "Charge"
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001334 exclude = ["invoice"]
Scott Baker15cddfa2013-12-09 13:45:19 -08001335 fields = ["date", "kind", "state", "object", "coreHours", "dollar_amount", "slice"]
1336 readonly_fields = ["date", "kind", "state", "object", "coreHours", "dollar_amount", "slice"]
Scott Baker43105042013-12-06 23:23:36 -08001337 suit_classes = 'suit-tab suit-tab-accountpendingcharges'
Scott Baker15cddfa2013-12-09 13:45:19 -08001338 can_delete=False
1339 max_num=0
Scott Baker43105042013-12-06 23:23:36 -08001340
1341 def queryset(self, request):
1342 qs = super(PendingChargeInline, self).queryset(request)
1343 qs = qs.filter(state="pending")
1344 return qs
1345
Scott Baker15cddfa2013-12-09 13:45:19 -08001346 dollar_amount = right_dollar_field("amount", "Amount")
1347
Scott Baker0165fac2014-01-13 11:49:26 -08001348class PaymentInline(PlStackTabularInline):
Scott Baker43105042013-12-06 23:23:36 -08001349 model=Payment
1350 extra = 1
1351 verbose_name_plural = "Payments"
1352 verbose_name = "Payment"
Scott Baker15cddfa2013-12-09 13:45:19 -08001353 fields = ["date", "dollar_amount"]
1354 readonly_fields = ["date", "dollar_amount"]
Scott Baker43105042013-12-06 23:23:36 -08001355 suit_classes = 'suit-tab suit-tab-accountpayments'
Scott Baker15cddfa2013-12-09 13:45:19 -08001356 can_delete=False
1357 max_num=0
1358
1359 dollar_amount = right_dollar_field("amount", "Amount")
1360
Scott Baker43105042013-12-06 23:23:36 -08001361class AccountAdmin(admin.ModelAdmin):
1362 list_display = ("site", "balance_due")
1363
1364 inlines = [InvoiceInline, PaymentInline, PendingChargeInline]
1365
1366 fieldsets = [
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001367 (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 -08001368
Scott Baker15cddfa2013-12-09 13:45:19 -08001369 readonly_fields = ['site', 'dollar_balance_due', 'dollar_total_invoices', 'dollar_total_payments']
Scott Baker43105042013-12-06 23:23:36 -08001370
1371 suit_form_tabs =(
1372 ('general','Account Details'),
1373 ('accountinvoice', 'Invoices'),
1374 ('accountpayments', 'Payments'),
1375 ('accountpendingcharges','Pending Charges'),
1376 )
1377
Scott Baker15cddfa2013-12-09 13:45:19 -08001378 dollar_balance_due = dollar_field("balance_due", "Balance Due")
1379 dollar_total_invoices = dollar_field("total_invoices", "Total Invoices")
1380 dollar_total_payments = dollar_field("total_payments", "Total Payments")
1381
Siobhan Tullyce652d02013-10-08 21:52:35 -04001382
Siobhan Tully53437282013-04-26 19:30:27 -04001383# Now register the new UserAdmin...
Siobhan Tully30fd4292013-05-10 08:59:56 -04001384admin.site.register(User, UserAdmin)
Siobhan Tully53437282013-04-26 19:30:27 -04001385# ... and, since we're not using Django's builtin permissions,
1386# unregister the Group model from admin.
Siobhan Tullyce652d02013-10-08 21:52:35 -04001387#admin.site.unregister(Group)
Siobhan Tully53437282013-04-26 19:30:27 -04001388
Siobhan Tullybf1153a2013-05-27 20:53:48 -04001389#Do not show django evolution in the admin interface
1390from django_evolution.models import Version, Evolution
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001391#admin.site.unregister(Version)
1392#admin.site.unregister(Evolution)
Siobhan Tullybf1153a2013-05-27 20:53:48 -04001393
1394
1395# When debugging it is often easier to see all the classes, but for regular use
1396# only the top-levels should be displayed
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001397showAll = False
Scott Baker43105042013-12-06 23:23:36 -08001398
Siobhan Tullybf1153a2013-05-27 20:53:48 -04001399admin.site.register(Deployment, DeploymentAdmin)
Siobhan Tully4bc09f22013-04-10 21:15:21 -04001400admin.site.register(Site, SiteAdmin)
Siobhan Tully4bc09f22013-04-10 21:15:21 -04001401admin.site.register(Slice, SliceAdmin)
Siobhan Tullyce652d02013-10-08 21:52:35 -04001402admin.site.register(Service, ServiceAdmin)
smbakera3cf70c2013-06-27 02:01:41 -07001403admin.site.register(Reservation, ReservationAdmin)
Scott Baker74d8e622013-07-29 16:04:22 -07001404admin.site.register(Network, NetworkAdmin)
1405admin.site.register(Router, RouterAdmin)
Scott Baker74d8e622013-07-29 16:04:22 -07001406admin.site.register(NetworkTemplate, NetworkTemplateAdmin)
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001407admin.site.register(Account, AccountAdmin)
1408admin.site.register(Invoice, InvoiceAdmin)
Siobhan Tullybf1153a2013-05-27 20:53:48 -04001409
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001410if True:
1411 admin.site.register(NetworkParameterType, NetworkParameterTypeAdmin)
1412 admin.site.register(ServiceClass, ServiceClassAdmin)
Siobhan Tullybfd11dc2013-09-03 12:59:24 -04001413 #admin.site.register(PlanetStack)
Siobhan Tullyd3515752013-06-21 16:34:53 -04001414 admin.site.register(Tag, TagAdmin)
Siobhan Tullyce652d02013-10-08 21:52:35 -04001415 admin.site.register(DeploymentRole)
1416 admin.site.register(SiteRole)
1417 admin.site.register(SliceRole)
1418 admin.site.register(PlanetStackRole)
Siobhan Tullybf1153a2013-05-27 20:53:48 -04001419 admin.site.register(Node, NodeAdmin)
Siobhan Tullybfd11dc2013-09-03 12:59:24 -04001420 #admin.site.register(SlicePrivilege, SlicePrivilegeAdmin)
1421 #admin.site.register(SitePrivilege, SitePrivilegeAdmin)
Siobhan Tullybf1153a2013-05-27 20:53:48 -04001422 admin.site.register(Sliver, SliverAdmin)
Siobhan Tullybf1153a2013-05-27 20:53:48 -04001423 admin.site.register(Image, ImageAdmin)
Scott Baker2c3cb642014-05-19 17:55:56 -07001424 admin.site.register(DashboardView, DashboardViewAdmin)
Tony Mack7130ac32013-03-22 21:58:00 -04001425