blob: 196324e4386cacafe473d66732ba58d1f9a06bbc [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
Siobhan Tullycf04fb62014-01-11 11:25:57 -050068 def __user_is_readonly(self, request):
69 return request.user.isReadOnlyUser()
70
Siobhan Tullyce652d02013-10-08 21:52:35 -040071class SingletonAdmin (admin.ModelAdmin):
72 def has_add_permission(self, request):
73 num_objects = self.model.objects.count()
74 if num_objects >= 1:
75 return False
76 else:
77 return True
78
79
Siobhan Tullyd3515752013-06-21 16:34:53 -040080class PlStackTabularInline(admin.TabularInline):
Scott Baker86568322014-01-12 16:53:31 -080081 def __init__(self, *args, **kwargs):
82 super(PlStackTabularInline, self).__init__(*args, **kwargs)
83
84 # InlineModelAdmin as no get_fields() method, so in order to add
85 # the selflink field, we override __init__ to modify self.fields and
86 # self.readonly_fields.
87
Scott Bakere2bbf7e2014-01-13 12:09:31 -080088 self.setup_selflink()
89
Scott Baker874936e2014-01-13 18:15:34 -080090 def get_change_url(self, model, id):
91 """ Get the URL to a change form in the admin for this model """
92 reverse_path = "admin:%s_change" % (model._meta.db_table)
Scott Bakere2bbf7e2014-01-13 12:09:31 -080093 try:
Scott Baker874936e2014-01-13 18:15:34 -080094 url = reverse(reverse_path, args=(id,))
Scott Bakere2bbf7e2014-01-13 12:09:31 -080095 except NoReverseMatch:
Scott Baker874936e2014-01-13 18:15:34 -080096 return None
97
98 return url
99
100 def setup_selflink(self):
101 if hasattr(self, "selflink_fieldname"):
102 """ self.selflink_model can be defined to punch through a relation
103 to its target object. For example, in SliceNetworkInline, set
104 selflink_model = "network", and the URL will lead to the Network
105 object instead of trying to bring up a change view of the
106 SliceNetwork object.
107 """
108 self.selflink_model = getattr(self.model,self.selflink_fieldname).field.rel.to
109 else:
110 self.selflink_model = self.model
111
112 url = self.get_change_url(self.selflink_model, 0)
113
114 # We don't have an admin for this object, so don't create the
115 # selflink.
116 if (url == None):
Scott Bakere2bbf7e2014-01-13 12:09:31 -0800117 return
118
Scott Baker874936e2014-01-13 18:15:34 -0800119 # Since we need to add "selflink" to the field list, we need to create
120 # self.fields if it is None.
Scott Baker0165fac2014-01-13 11:49:26 -0800121 if (self.fields is None):
122 self.fields = []
123 for f in self.model._meta.fields:
124 if f.editable and f.name != "id":
125 self.fields.append(f.name)
Scott Baker86568322014-01-12 16:53:31 -0800126
Scott Baker874936e2014-01-13 18:15:34 -0800127 self.fields = tuple(self.fields) + ("selflink", )
Scott Baker86568322014-01-12 16:53:31 -0800128
Scott Baker874936e2014-01-13 18:15:34 -0800129 if self.readonly_fields is None:
130 self.readonly_fields = ()
Scott Baker86568322014-01-12 16:53:31 -0800131
Scott Baker874936e2014-01-13 18:15:34 -0800132 self.readonly_fields = tuple(self.readonly_fields) + ("selflink", )
Scott Baker86568322014-01-12 16:53:31 -0800133
134 def selflink(self, obj):
Scott Baker874936e2014-01-13 18:15:34 -0800135 if hasattr(self, "selflink_fieldname"):
136 obj = getattr(obj, self.selflink_fieldname)
137
Scott Baker86568322014-01-12 16:53:31 -0800138 if obj.id:
Scott Baker874936e2014-01-13 18:15:34 -0800139 url = self.get_change_url(self.selflink_model, obj.id)
140 return "<a href='%s'>Details</a>" % str(url)
Scott Baker86568322014-01-12 16:53:31 -0800141 else:
Scott Bakere2bbf7e2014-01-13 12:09:31 -0800142 return "Not present"
Scott Baker86568322014-01-12 16:53:31 -0800143
144 selflink.allow_tags = True
145 selflink.short_description = "Details"
Siobhan Tullyd3515752013-06-21 16:34:53 -0400146
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500147class ReadOnlyTabularInline(PlStackTabularInline):
148 can_delete = False
149
150 def get_readonly_fields(self, request, obj=None):
151 return self.fields
152
153 def has_add_permission(self, request):
154 return False
155
156class ReservationROInline(ReadOnlyTabularInline):
157 model = Reservation
158 extra = 0
159 suit_classes = 'suit-tab suit-tab-reservations'
160 fields = ['startTime','slice','duration']
161
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400162class ReservationInline(PlStackTabularInline):
163 model = Reservation
164 extra = 0
165 suit_classes = 'suit-tab suit-tab-reservations'
Tony Mack5b061472014-02-04 07:57:10 -0500166
167 def queryset(self, request):
168 return Reservation.select_by_user(request.user)
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400169
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500170class TagROInline(generic.GenericTabularInline):
171 model = Tag
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400172 extra = 0
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500173 suit_classes = 'suit-tab suit-tab-tags'
174 can_delete = False
175 fields = ['service', 'name', 'value']
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400176
177 def get_readonly_fields(self, request, obj=None):
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500178 return self.fields
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400179
180 def has_add_permission(self, request):
181 return False
182
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500183
Siobhan Tullyde5450d2013-06-21 11:35:33 -0400184class TagInline(generic.GenericTabularInline):
185 model = Tag
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400186 extra = 0
187 suit_classes = 'suit-tab suit-tab-tags'
Tony Mack5b061472014-02-04 07:57:10 -0500188 fields = ['service', 'name', 'value']
189
190 def queryset(self, request):
191 return Tag.select_by_user(request.user)
Siobhan Tullyde5450d2013-06-21 11:35:33 -0400192
Scott Baker74d8e622013-07-29 16:04:22 -0700193class NetworkLookerUpper:
Siobhan Tully2c780ad2013-09-06 11:22:40 -0400194 """ This is a callable that looks up a network name in a sliver and returns
195 the ip address for that network.
196 """
197
198 def __init__(self, name):
199 self.short_description = name
200 self.__name__ = name
201 self.network_name = name
202
203 def __call__(self, obj):
204 if obj is not None:
205 for nbs in obj.networksliver_set.all():
206 if (nbs.network.name == self.network_name):
207 return nbs.ip
Scott Baker74d8e622013-07-29 16:04:22 -0700208 return ""
209
210 def __str__(self):
211 return self.network_name
212
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500213class SliverROInline(ReadOnlyTabularInline):
214 model = Sliver
215 fields = ['ip', 'instance_name', 'slice', 'numberCores', 'image', 'node', 'deploymentNetwork']
216 suit_classes = 'suit-tab suit-tab-slivers'
217
Siobhan Tullyd3515752013-06-21 16:34:53 -0400218class SliverInline(PlStackTabularInline):
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400219 model = Sliver
Tony Mackb0d97422013-06-10 09:57:45 -0400220 fields = ['ip', 'instance_name', 'slice', 'numberCores', 'image', 'node', 'deploymentNetwork']
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400221 extra = 0
Tony Mack3777b012013-05-07 21:38:06 -0400222 readonly_fields = ['ip', 'instance_name']
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400223 suit_classes = 'suit-tab suit-tab-slivers'
Scott Baker74d8e622013-07-29 16:04:22 -0700224
Tony Mack5b061472014-02-04 07:57:10 -0500225 def queryset(self, request):
226 return Sliver.select_by_user(request.user)
227
Siobhan Tully2d95e482013-09-06 10:56:06 -0400228# Note this is breaking in the admin.py when trying to use an inline to add a node/image
229# def _declared_fieldsets(self):
230# # Return None so django will call get_fieldsets and we can insert our
231# # dynamic fields
232# return None
233#
234# def get_readonly_fields(self, request, obj=None):
235# readonly_fields = super(SliverInline, self).get_readonly_fields(request, obj)
236#
237# # Lookup the networks that are bound to the slivers, and add those
238# # network names to the list of readonly fields.
239#
240# for sliver in obj.slivers.all():
241# for nbs in sliver.networksliver_set.all():
242# if nbs.ip:
243# network_name = nbs.network.name
244# if network_name not in [str(x) for x in readonly_fields]:
245# readonly_fields.append(NetworkLookerUpper(network_name))
246#
247# return readonly_fields
248#
249# def get_fieldsets(self, request, obj=None):
250# form = self.get_formset(request, obj).form
251# # fields = the read/write files + the read-only fields
252# fields = self.fields
253# for fieldName in self.get_readonly_fields(request,obj):
254# if not fieldName in fields:
255# fields.append(fieldName)
256#
257# return [(None, {'fields': fields})]
Scott Baker74d8e622013-07-29 16:04:22 -0700258
Tony Mackc2835a92013-05-28 09:18:49 -0400259
Siobhan Tully567e3e62013-06-21 18:03:16 -0400260
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500261class SiteROInline(ReadOnlyTabularInline):
262 model = Site
263 extra = 0
264 fields = ['name', 'login_base', 'site_url', 'enabled']
265 suit_classes = 'suit-tab suit-tab-sites'
266
Siobhan Tullyd3515752013-06-21 16:34:53 -0400267class SiteInline(PlStackTabularInline):
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400268 model = Site
269 extra = 0
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400270 suit_classes = 'suit-tab suit-tab-sites'
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400271
Tony Mack5b061472014-02-04 07:57:10 -0500272 def queryset(self, request):
273 return Site.select_by_user(request.user)
274
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500275class UserROInline(ReadOnlyTabularInline):
276 model = User
277 fields = ['email', 'firstname', 'lastname']
278 extra = 0
279 suit_classes = 'suit-tab suit-tab-users'
280
Siobhan Tullyd3515752013-06-21 16:34:53 -0400281class UserInline(PlStackTabularInline):
Siobhan Tully30fd4292013-05-10 08:59:56 -0400282 model = User
Siobhan Tully47ae1b52013-05-10 15:53:14 -0400283 fields = ['email', 'firstname', 'lastname']
Siobhan Tully30fd4292013-05-10 08:59:56 -0400284 extra = 0
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400285 suit_classes = 'suit-tab suit-tab-users'
Siobhan Tully30fd4292013-05-10 08:59:56 -0400286
Tony Mack5b061472014-02-04 07:57:10 -0500287 def queryset(self, request):
288 return User.select_by_user(request.user)
289
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500290class SliceROInline(ReadOnlyTabularInline):
291 model = Slice
292 suit_classes = 'suit-tab suit-tab-slices'
293 fields = ['name','site', 'serviceClass', 'service']
294
Siobhan Tullyd3515752013-06-21 16:34:53 -0400295class SliceInline(PlStackTabularInline):
Tony Mack00d361f2013-04-28 10:28:42 -0400296 model = Slice
Siobhan Tullyce652d02013-10-08 21:52:35 -0400297 fields = ['name','site', 'serviceClass', 'service']
Tony Mack00d361f2013-04-28 10:28:42 -0400298 extra = 0
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400299 suit_classes = 'suit-tab suit-tab-slices'
300
Tony Mack5b061472014-02-04 07:57:10 -0500301 def queryset(self, request):
302 return Slice.select_by_user(request.user)
303
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500304class NodeROInline(ReadOnlyTabularInline):
305 model = Node
306 extra = 0
307 suit_classes = 'suit-tab suit-tab-nodes'
308 fields = ['name','deployment']
Tony Mack00d361f2013-04-28 10:28:42 -0400309
Siobhan Tullyd3515752013-06-21 16:34:53 -0400310class NodeInline(PlStackTabularInline):
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400311 model = Node
312 extra = 0
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400313 suit_classes = 'suit-tab suit-tab-nodes'
Tony Mack5b061472014-02-04 07:57:10 -0500314 fields = ['name','deployment']
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400315
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500316class DeploymentPrivilegeROInline(ReadOnlyTabularInline):
317 model = DeploymentPrivilege
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400318 extra = 0
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500319 suit_classes = 'suit-tab suit-tab-deploymentprivileges'
Scott Baker3ca51f62014-05-23 12:05:11 -0700320 fields = ['user','role','deployment']
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400321
322class DeploymentPrivilegeInline(PlStackTabularInline):
323 model = DeploymentPrivilege
324 extra = 0
325 suit_classes = 'suit-tab suit-tab-deploymentprivileges'
Scott Baker3ca51f62014-05-23 12:05:11 -0700326 fields = ['user','role','deployment']
Tony Mack5b061472014-02-04 07:57:10 -0500327
328 def queryset(self, request):
329 return DeploymentPrivilege.select_by_user(request.user)
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400330
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500331#CLEANUP DOUBLE SitePrivilegeInline
332class SitePrivilegeROInline(ReadOnlyTabularInline):
333 model = SitePrivilege
334 extra = 0
335 suit_classes = 'suit-tab suit-tab-siteprivileges'
336 fields = ['user','site', 'role']
337
Siobhan Tullyd3515752013-06-21 16:34:53 -0400338class SitePrivilegeInline(PlStackTabularInline):
Siobhan Tullyaa1bcd52013-05-10 12:43:09 -0400339 model = SitePrivilege
340 extra = 0
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400341 suit_classes = 'suit-tab suit-tab-siteprivileges'
Tony Mack5b061472014-02-04 07:57:10 -0500342 fields = ['user','site', 'role']
Siobhan Tullyaa1bcd52013-05-10 12:43:09 -0400343
Tony Mackc2835a92013-05-28 09:18:49 -0400344 def formfield_for_foreignkey(self, db_field, request, **kwargs):
345 if db_field.name == 'site':
Tony Mack5b061472014-02-04 07:57:10 -0500346 kwargs['queryset'] = Site.select_by_user(request.user)
Tony Mackc2835a92013-05-28 09:18:49 -0400347
348 if db_field.name == 'user':
Tony Mack5b061472014-02-04 07:57:10 -0500349 kwargs['queryset'] = User.select_by_user(request.user)
Tony Mackc2835a92013-05-28 09:18:49 -0400350 return super(SitePrivilegeInline, self).formfield_for_foreignkey(db_field, request, **kwargs)
351
Tony Mack5b061472014-02-04 07:57:10 -0500352 def queryset(self, request):
353 return SitePrivilege.select_by_user(request.user)
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400354
Tony Macke4be32f2014-03-11 20:45:25 -0400355class SiteDeploymentROInline(ReadOnlyTabularInline):
356 model = SiteDeployments
357 #model = Site.deployments.through
358 extra = 0
Scott Bakerf3982522014-05-23 11:58:20 -0700359 suit_classes = 'suit-tab suit-tab-deployments'
Tony Macke4be32f2014-03-11 20:45:25 -0400360 fields = ['deployment','site']
361
362class SiteDeploymentInline(PlStackTabularInline):
363 model = SiteDeployments
364 #model = Site.deployments.through
365 extra = 0
366 suit_classes = 'suit-tab suit-tab-deployments'
367 fields = ['deployment','site']
368
369 def formfield_for_foreignkey(self, db_field, request, **kwargs):
370 if db_field.name == 'site':
371 kwargs['queryset'] = Site.select_by_user(request.user)
372
373 if db_field.name == 'deployment':
374 kwargs['queryset'] = Deployment.select_by_user(request.user)
375 return super(SiteDeploymentInline, self).formfield_for_foreignkey(db_field, request, **kwargs)
376
377 def queryset(self, request):
378 return SiteDeployments.select_by_user(request.user)
379
380
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500381class SlicePrivilegeROInline(ReadOnlyTabularInline):
382 model = SlicePrivilege
383 extra = 0
384 suit_classes = 'suit-tab suit-tab-sliceprivileges'
385 fields = ['user', 'slice', 'role']
386
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400387class SlicePrivilegeInline(PlStackTabularInline):
388 model = SlicePrivilege
389 suit_classes = 'suit-tab suit-tab-sliceprivileges'
390 extra = 0
391 fields = ('user', 'slice','role')
Siobhan Tullyaa1bcd52013-05-10 12:43:09 -0400392
Tony Mackc2835a92013-05-28 09:18:49 -0400393 def formfield_for_foreignkey(self, db_field, request, **kwargs):
394 if db_field.name == 'slice':
Tony Mack5b061472014-02-04 07:57:10 -0500395 kwargs['queryset'] = Slice.select_by_user(request.user)
Tony Mackc2835a92013-05-28 09:18:49 -0400396 if db_field.name == 'user':
Tony Mack5b061472014-02-04 07:57:10 -0500397 kwargs['queryset'] = User.select_by_user(request.user)
Tony Mackc2835a92013-05-28 09:18:49 -0400398
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400399 return super(SlicePrivilegeInline, self).formfield_for_foreignkey(db_field, request, **kwargs)
Tony Mackc2835a92013-05-28 09:18:49 -0400400
Tony Mack5b061472014-02-04 07:57:10 -0500401 def queryset(self, request):
402 return SlicePrivilege.select_by_user(request.user)
403
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500404class SliceNetworkROInline(ReadOnlyTabularInline):
405 model = Network.slices.through
406 extra = 0
407 verbose_name = "Network Connection"
408 verbose_name_plural = "Network Connections"
409 suit_classes = 'suit-tab suit-tab-slicenetworks'
410 fields = ['network']
411
Scott Bakera0015eb2013-08-14 17:28:14 -0700412class SliceNetworkInline(PlStackTabularInline):
Scott Baker74d8e622013-07-29 16:04:22 -0700413 model = Network.slices.through
Scott Baker874936e2014-01-13 18:15:34 -0800414 selflink_fieldname = "network"
Scott Baker74d8e622013-07-29 16:04:22 -0700415 extra = 0
416 verbose_name = "Network Connection"
417 verbose_name_plural = "Network Connections"
Siobhan Tully2d95e482013-09-06 10:56:06 -0400418 suit_classes = 'suit-tab suit-tab-slicenetworks'
Scott Baker74d8e622013-07-29 16:04:22 -0700419
Tony Mack5e71a662013-05-03 23:30:41 -0400420class PlainTextWidget(forms.HiddenInput):
421 input_type = 'hidden'
422
423 def render(self, name, value, attrs=None):
424 if value is None:
425 value = ''
Tony Mack1d6b85f2013-05-07 18:49:14 -0400426 return mark_safe(str(value) + super(PlainTextWidget, self).render(name, value, attrs))
Tony Mack9bcbe4f2013-04-29 08:13:27 -0400427
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500428class PlanetStackBaseAdmin(ReadOnlyAwareAdmin):
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400429 save_on_top = False
Tony Mack332ee1d2014-02-04 15:33:45 -0500430
431 def save_model(self, request, obj, form, change):
Tony Mack3d042792014-03-17 19:18:37 -0400432 obj.caller = request.user
Tony Mack332ee1d2014-02-04 15:33:45 -0500433 # update openstack connection to use this site/tenant
434 obj.save_by_user(request.user)
435
436 def delete_model(self, request, obj):
437 obj.delete_by_user(request.user)
438
439 def save_formset(self, request, form, formset, change):
440 instances = formset.save(commit=False)
441 for instance in instances:
442 instance.save_by_user(request.user)
443 formset.save_m2m()
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400444
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400445class SliceRoleAdmin(PlanetStackBaseAdmin):
446 model = SliceRole
447 pass
448
449class SiteRoleAdmin(PlanetStackBaseAdmin):
450 model = SiteRole
451 pass
452
Siobhan Tullybf1153a2013-05-27 20:53:48 -0400453class DeploymentAdminForm(forms.ModelForm):
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400454 sites = forms.ModelMultipleChoiceField(
455 queryset=Site.objects.all(),
456 required=False,
457 widget=FilteredSelectMultiple(
458 verbose_name=('Sites'), is_stacked=False
459 )
460 )
461 class Meta:
Siobhan Tullybf1153a2013-05-27 20:53:48 -0400462 model = Deployment
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400463
Siobhan Tully320b4622014-01-17 15:11:14 -0500464 def __init__(self, *args, **kwargs):
465 super(DeploymentAdminForm, self).__init__(*args, **kwargs)
466
467 if self.instance and self.instance.pk:
Scott Bakerc9b14f72014-05-22 13:44:20 -0700468 self.fields['sites'].initial = [x.site for x in self.instance.sitedeployments_set.all()]
Siobhan Tully320b4622014-01-17 15:11:14 -0500469
470 def save(self, commit=True):
471 deployment = super(DeploymentAdminForm, self).save(commit=False)
472
473 if commit:
474 deployment.save()
475
476 if deployment.pk:
Scott Bakerc9b14f72014-05-22 13:44:20 -0700477 # save_m2m() doesn't seem to work with 'through' relations. So we
478 # create/destroy the through models ourselves. There has to be
479 # a better way...
480
481 sites = self.cleaned_data['sites']
482
483 existing_sites = []
484 for sdp in list(deployment.sitedeployments_set.all()):
485 if sdp.site not in sites:
486 #print "deleting site", sdp.site
487 sdp.delete()
488 else:
489 existing_sites.append(sdp.site)
490
491 for site in sites:
492 if site not in existing_sites:
493 #print "adding site", site
494 sdp = SiteDeployments(site=site, deployment=deployment)
495 sdp.save()
496
Siobhan Tully320b4622014-01-17 15:11:14 -0500497 self.save_m2m()
498
499 return deployment
500
Scott Bakerff5e0f32014-05-22 14:40:27 -0700501class DeploymentAdminROForm(DeploymentAdminForm):
502 def save(self, commit=True):
503 raise PermissionDenied
504
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500505class SiteAssocInline(PlStackTabularInline):
506 model = Site.deployments.through
507 extra = 0
508 suit_classes = 'suit-tab suit-tab-sites'
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400509
Siobhan Tullybf1153a2013-05-27 20:53:48 -0400510class DeploymentAdmin(PlanetStackBaseAdmin):
Scott Bakerff5e0f32014-05-22 14:40:27 -0700511 #form = DeploymentAdminForm
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500512 model = Deployment
513 fieldList = ['name','sites']
514 fieldsets = [(None, {'fields': fieldList, 'classes':['suit-tab suit-tab-sites']})]
Siobhan Tully2d95e482013-09-06 10:56:06 -0400515 inlines = [DeploymentPrivilegeInline,NodeInline,TagInline]
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500516
517 user_readonly_inlines = [DeploymentPrivilegeROInline,NodeROInline,TagROInline]
518 user_readonly_fields = ['name']
519
520 suit_form_tabs =(('sites','Deployment Details'),('nodes','Nodes'),('deploymentprivileges','Privileges'),('tags','Tags'))
521
Scott Bakerff5e0f32014-05-22 14:40:27 -0700522 def get_form(self, request, obj=None, **kwargs):
523 if request.user.isReadOnlyUser():
524 kwargs["form"] = DeploymentAdminROForm
525 else:
526 kwargs["form"] = DeploymentAdminForm
527 return super(DeploymentAdmin,self).get_form(request, obj, **kwargs)
528
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500529class ServiceAttrAsTabROInline(ReadOnlyTabularInline):
530 model = ServiceAttribute
531 fields = ['name','value']
532 extra = 0
533 suit_classes = 'suit-tab suit-tab-serviceattrs'
Tony Mack5cd13202013-05-01 21:48:38 -0400534
Siobhan Tullyce652d02013-10-08 21:52:35 -0400535class ServiceAttrAsTabInline(PlStackTabularInline):
536 model = ServiceAttribute
537 fields = ['name','value']
538 extra = 0
539 suit_classes = 'suit-tab suit-tab-serviceattrs'
540
Siobhan Tullyce652d02013-10-08 21:52:35 -0400541class ServiceAdmin(PlanetStackBaseAdmin):
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500542 list_display = ("name","description","versionNumber","enabled","published")
543 fieldList = ["name","description","versionNumber","enabled","published"]
544 fieldsets = [(None, {'fields': fieldList, 'classes':['suit-tab suit-tab-general']})]
545 inlines = [ServiceAttrAsTabInline,SliceInline]
546
547 user_readonly_fields = fieldList
548 user_readonly_inlines = [ServiceAttrAsTabROInline,SliceROInline]
549
550 suit_form_tabs =(('general', 'Service Details'),
551 ('slices','Slices'),
552 ('serviceattrs','Additional Attributes'),
553 )
Siobhan Tullyce652d02013-10-08 21:52:35 -0400554
Tony Mack0553f282013-06-10 22:54:50 -0400555class SiteAdmin(PlanetStackBaseAdmin):
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500556 fieldList = ['name', 'site_url', 'enabled', 'is_public', 'login_base', 'accountLink','location']
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400557 fieldsets = [
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500558 (None, {'fields': fieldList, 'classes':['suit-tab suit-tab-general']}),
Tony Macke4be32f2014-03-11 20:45:25 -0400559 #('Deployment Networks', {'fields': ['deployments'], 'classes':['suit-tab suit-tab-deployments']}),
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400560 ]
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400561 suit_form_tabs =(('general', 'Site Details'),
562 ('users','Users'),
Siobhan Tully2d95e482013-09-06 10:56:06 -0400563 ('siteprivileges','Privileges'),
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400564 ('deployments','Deployments'),
565 ('slices','Slices'),
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500566 ('nodes','Nodes'),
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400567 ('tags','Tags'),
568 )
Scott Baker545db2a2013-12-09 18:44:43 -0800569 readonly_fields = ['accountLink']
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500570
571 user_readonly_fields = ['name', 'deployments','site_url', 'enabled', 'is_public', 'login_base', 'accountLink']
Tony Macke4be32f2014-03-11 20:45:25 -0400572 user_readonly_inlines = [SliceROInline,UserROInline,TagROInline, NodeROInline, SitePrivilegeROInline,SiteDeploymentROInline]
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500573
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400574 list_display = ('name', 'login_base','site_url', 'enabled')
575 filter_horizontal = ('deployments',)
Tony Macke4be32f2014-03-11 20:45:25 -0400576 inlines = [SliceInline,UserInline,TagInline, NodeInline, SitePrivilegeInline, SiteDeploymentInline]
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400577 search_fields = ['name']
578
Tony Mack04062832013-05-10 08:22:44 -0400579 def queryset(self, request):
Tony Mack5b061472014-02-04 07:57:10 -0500580 return Site.select_by_user(request.user)
Tony Mack04062832013-05-10 08:22:44 -0400581
Tony Mack5cd13202013-05-01 21:48:38 -0400582 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
Tony Mack2bd5b412013-06-11 21:05:06 -0400587 if isinstance(inline, SliceInline):
588 inline.model.caller = request.user
589 yield inline.get_formset(request, obj)
590
591 def get_formsets(self, request, obj=None):
592 for inline in self.get_inline_instances(request, obj):
593 # hide MyInline in the add view
594 if obj is None:
595 continue
596 if isinstance(inline, SliverInline):
597 inline.model.caller = request.user
Tony Mack5cd13202013-05-01 21:48:38 -0400598 yield inline.get_formset(request, obj)
599
Scott Baker545db2a2013-12-09 18:44:43 -0800600 def accountLink(self, obj):
601 link_obj = obj.accounts.all()
602 if link_obj:
603 reverse_path = "admin:core_account_change"
604 url = reverse(reverse_path, args =(link_obj[0].id,))
605 return "<a href='%s'>%s</a>" % (url, "view billing details")
606 else:
607 return "no billing data for this site"
608 accountLink.allow_tags = True
609 accountLink.short_description = "Billing"
610
Tony Mack332ee1d2014-02-04 15:33:45 -0500611 def save_model(self, request, obj, form, change):
612 # update openstack connection to use this site/tenant
613 obj.save_by_user(request.user)
614
615 def delete_model(self, request, obj):
616 obj.delete_by_user(request.user)
617
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500618
Tony Mack9bcbe4f2013-04-29 08:13:27 -0400619class SitePrivilegeAdmin(PlanetStackBaseAdmin):
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500620 fieldList = ['user', 'site', 'role']
Tony Mack00d361f2013-04-28 10:28:42 -0400621 fieldsets = [
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500622 (None, {'fields': fieldList, 'classes':['collapse']})
Tony Mack00d361f2013-04-28 10:28:42 -0400623 ]
624 list_display = ('user', 'site', 'role')
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500625 user_readonly_fields = fieldList
626 user_readonly_inlines = []
Tony Mack00d361f2013-04-28 10:28:42 -0400627
Tony Mackc2835a92013-05-28 09:18:49 -0400628 def formfield_for_foreignkey(self, db_field, request, **kwargs):
629 if db_field.name == 'site':
630 if not request.user.is_admin:
631 # only show sites where user is an admin or pi
632 sites = set()
633 for site_privilege in SitePrivilege.objects.filer(user=request.user):
634 if site_privilege.role.role_type in ['admin', 'pi']:
635 sites.add(site_privilege.site)
636 kwargs['queryset'] = Site.objects.filter(site__in=list(sites))
637
638 if db_field.name == 'user':
639 if not request.user.is_admin:
640 # only show users from sites where caller has admin or pi role
641 roles = Role.objects.filter(role_type__in=['admin', 'pi'])
642 site_privileges = SitePrivilege.objects.filter(user=request.user).filter(role__in=roles)
643 sites = [site_privilege.site for site_privilege in site_privileges]
644 site_privileges = SitePrivilege.objects.filter(site__in=sites)
645 emails = [site_privilege.user.email for site_privilege in site_privileges]
646 users = User.objects.filter(email__in=emails)
647 kwargs['queryset'] = users
648
649 return super(SitePrivilegeAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)
650
Tony Mack04062832013-05-10 08:22:44 -0400651 def queryset(self, request):
652 # admins can see all privileges. Users can only see privileges at sites
Tony Mackc2835a92013-05-28 09:18:49 -0400653 # where they have the admin role or pi role.
Tony Mack04062832013-05-10 08:22:44 -0400654 qs = super(SitePrivilegeAdmin, self).queryset(request)
Tony Mack5b061472014-02-04 07:57:10 -0500655 #if not request.user.is_admin:
656 # roles = Role.objects.filter(role_type__in=['admin', 'pi'])
657 # site_privileges = SitePrivilege.objects.filter(user=request.user).filter(role__in=roles)
658 # login_bases = [site_privilege.site.login_base for site_privilege in site_privileges]
659 # sites = Site.objects.filter(login_base__in=login_bases)
660 # qs = qs.filter(site__in=sites)
Tony Mack04062832013-05-10 08:22:44 -0400661 return qs
662
Siobhan Tullyce652d02013-10-08 21:52:35 -0400663class SliceForm(forms.ModelForm):
664 class Meta:
665 model = Slice
666 widgets = {
667 'service': LinkedSelect
668 }
669
Tony Mack2bd5b412013-06-11 21:05:06 -0400670class SliceAdmin(PlanetStackBaseAdmin):
Siobhan Tullyce652d02013-10-08 21:52:35 -0400671 form = SliceForm
Tony Mack29bf5e82014-04-29 21:40:24 -0400672 fieldList = ['name', 'site', 'serviceClass', 'enabled','description', 'service', 'slice_url', 'max_slivers']
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500673 fieldsets = [('Slice Details', {'fields': fieldList, 'classes':['suit-tab suit-tab-general']}),]
Tony Mack29bf5e82014-04-29 21:40:24 -0400674 list_display = ('name', 'site','serviceClass', 'slice_url', 'max_slivers')
Siobhan Tully2d95e482013-09-06 10:56:06 -0400675 inlines = [SlicePrivilegeInline,SliverInline, TagInline, ReservationInline,SliceNetworkInline]
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400676
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500677 user_readonly_fields = fieldList
678 user_readonly_inlines = [SlicePrivilegeROInline,SliverROInline,TagROInline, ReservationROInline, SliceNetworkROInline]
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400679
680 suit_form_tabs =(('general', 'Slice Details'),
Siobhan Tully2d95e482013-09-06 10:56:06 -0400681 ('slicenetworks','Networks'),
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400682 ('sliceprivileges','Privileges'),
683 ('slivers','Slivers'),
684 ('tags','Tags'),
685 ('reservations','Reservations'),
686 )
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400687
Tony Mackc2835a92013-05-28 09:18:49 -0400688 def formfield_for_foreignkey(self, db_field, request, **kwargs):
689 if db_field.name == 'site':
Tony Mack5b061472014-02-04 07:57:10 -0500690 kwargs['queryset'] = Site.select_by_user(request.user)
691
Tony Mackc2835a92013-05-28 09:18:49 -0400692 return super(SliceAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)
693
Tony Mack04062832013-05-10 08:22:44 -0400694 def queryset(self, request):
695 # admins can see all keys. Users can only see slices they belong to.
Tony Mack5b061472014-02-04 07:57:10 -0500696 return Slice.select_by_user(request.user)
Tony Mack04062832013-05-10 08:22:44 -0400697
Tony Mack79748612013-05-01 14:52:03 -0400698 def get_formsets(self, request, obj=None):
699 for inline in self.get_inline_instances(request, obj):
700 # hide MyInline in the add view
701 if obj is None:
702 continue
Tony Mack2bd5b412013-06-11 21:05:06 -0400703 if isinstance(inline, SliverInline):
704 inline.model.caller = request.user
Tony Mack79748612013-05-01 14:52:03 -0400705 yield inline.get_formset(request, obj)
706
Tony Mack2bd5b412013-06-11 21:05:06 -0400707
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400708class SlicePrivilegeAdmin(PlanetStackBaseAdmin):
Tony Mack00d361f2013-04-28 10:28:42 -0400709 fieldsets = [
710 (None, {'fields': ['user', 'slice', 'role']})
711 ]
712 list_display = ('user', 'slice', 'role')
Tony Mack00d361f2013-04-28 10:28:42 -0400713
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500714 user_readonly_fields = ['user', 'slice', 'role']
715 user_readonly_inlines = []
716
Tony Mackc2835a92013-05-28 09:18:49 -0400717 def formfield_for_foreignkey(self, db_field, request, **kwargs):
718 if db_field.name == 'slice':
Tony Mack5b061472014-02-04 07:57:10 -0500719 kwargs['queryset'] = Slice.select_by_user(request.user)
Tony Mackc2835a92013-05-28 09:18:49 -0400720
721 if db_field.name == 'user':
Tony Mack5b061472014-02-04 07:57:10 -0500722 kwargs['queryset'] = User.select_by_user(request.user)
Tony Mackc2835a92013-05-28 09:18:49 -0400723
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400724 return super(SlicePrivilegeAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)
Tony Mackc2835a92013-05-28 09:18:49 -0400725
Tony Mack04062832013-05-10 08:22:44 -0400726 def queryset(self, request):
727 # admins can see all memberships. Users can only see memberships of
728 # slices where they have the admin role.
Tony Mack5b061472014-02-04 07:57:10 -0500729 return SlicePrivilege.select_by_user(request.user)
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400730
Tony Mack9bcbe4f2013-04-29 08:13:27 -0400731 def save_model(self, request, obj, form, change):
Tony Mack951dab42013-05-02 19:51:45 -0400732 # update openstack connection to use this site/tenant
733 auth = request.session.get('auth', {})
734 auth['tenant'] = obj.slice.name
735 obj.os_manager = OpenStackManager(auth=auth, caller=request.user)
Tony Mack9bcbe4f2013-04-29 08:13:27 -0400736 obj.save()
737
738 def delete_model(self, request, obj):
Tony Mack951dab42013-05-02 19:51:45 -0400739 # update openstack connection to use this site/tenant
740 auth = request.session.get('auth', {})
741 auth['tenant'] = obj.slice.name
742 obj.os_manager = OpenStackManager(auth=auth, caller=request.user)
Tony Mack9bcbe4f2013-04-29 08:13:27 -0400743 obj.delete()
744
Siobhan Tully567e3e62013-06-21 18:03:16 -0400745
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400746class ImageAdmin(PlanetStackBaseAdmin):
747
748 fieldsets = [('Image Details',
Scott Baker00b00b32014-05-07 08:47:54 -0700749 {'fields': ['name', 'disk_format', 'container_format'],
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400750 'classes': ['suit-tab suit-tab-general']})
751 ]
752
753 suit_form_tabs =(('general','Image Details'),('slivers','Slivers'))
754
755 inlines = [SliverInline]
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500756
Tony Mack32e1ce32014-05-07 13:29:41 -0400757 user_readonly_fields = ['name', 'disk_format', 'container_format']
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500758 user_readonly_inlines = [SliverROInline]
759
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400760class NodeForm(forms.ModelForm):
761 class Meta:
762 widgets = {
763 'site': LinkedSelect,
764 'deployment': LinkedSelect
765 }
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400766
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500767class NodeAdmin(PlanetStackBaseAdmin):
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400768 form = NodeForm
Siobhan Tullybf1153a2013-05-27 20:53:48 -0400769 list_display = ('name', 'site', 'deployment')
770 list_filter = ('deployment',)
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500771
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400772 inlines = [TagInline,SliverInline]
773 fieldsets = [('Node Details', {'fields': ['name','site','deployment'], 'classes':['suit-tab suit-tab-details']})]
774
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500775 user_readonly_fields = ['name','site','deployment']
776 user_readonly_inlines = [TagInline,SliverInline]
777
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400778 suit_form_tabs =(('details','Node Details'),('slivers','Slivers'),('tags','Tags'))
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400779
Siobhan Tully567e3e62013-06-21 18:03:16 -0400780
Tony Mackd90cdbf2013-04-16 22:48:40 -0400781class SliverForm(forms.ModelForm):
782 class Meta:
Tony Mack1d6b85f2013-05-07 18:49:14 -0400783 model = Sliver
Tony Mackd90cdbf2013-04-16 22:48:40 -0400784 ip = forms.CharField(widget=PlainTextWidget)
Tony Mack18261812013-05-02 16:39:20 -0400785 instance_name = forms.CharField(widget=PlainTextWidget)
Tony Mackd90cdbf2013-04-16 22:48:40 -0400786 widgets = {
787 'ip': PlainTextWidget(),
Tony Mack18261812013-05-02 16:39:20 -0400788 'instance_name': PlainTextWidget(),
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400789 'slice': LinkedSelect,
790 'deploymentNetwork': LinkedSelect,
791 'node': LinkedSelect,
792 'image': LinkedSelect
Siobhan Tully53437282013-04-26 19:30:27 -0400793 }
Tony Mackd90cdbf2013-04-16 22:48:40 -0400794
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500795class TagAdmin(PlanetStackBaseAdmin):
Siobhan Tullyce652d02013-10-08 21:52:35 -0400796 list_display = ['service', 'name', 'value', 'content_type', 'content_object',]
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500797 user_readonly_fields = ['service', 'name', 'value', 'content_type', 'content_object',]
798 user_readonly_inlines = []
Siobhan Tullyd3515752013-06-21 16:34:53 -0400799
Tony Mack9bcbe4f2013-04-29 08:13:27 -0400800class SliverAdmin(PlanetStackBaseAdmin):
Tony Mackd90cdbf2013-04-16 22:48:40 -0400801 form = SliverForm
Tony Mackcdec0902013-04-15 00:38:49 -0400802 fieldsets = [
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400803 ('Sliver Details', {'fields': ['slice', 'deploymentNetwork', 'node', 'ip', 'instance_name', 'numberCores', 'image', ], 'classes': ['suit-tab suit-tab-general'], })
Tony Mackcdec0902013-04-15 00:38:49 -0400804 ]
Siobhan Tully5d7dc8d2013-07-02 13:17:33 -0400805 list_display = ['ip', 'instance_name', 'slice', 'numberCores', 'image', 'node', 'deploymentNetwork']
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400806
807 suit_form_tabs =(('general', 'Sliver Details'),
808 ('tags','Tags'),
809 )
810
Siobhan Tullyde5450d2013-06-21 11:35:33 -0400811 inlines = [TagInline]
Tony Mack53106f32013-04-27 16:43:01 -0400812
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500813 user_readonly_fields = ['slice', 'deploymentNetwork', 'node', 'ip', 'instance_name', 'numberCores', 'image']
814 user_readonly_inlines = [TagROInline]
815
Tony Mackc2835a92013-05-28 09:18:49 -0400816 def formfield_for_foreignkey(self, db_field, request, **kwargs):
817 if db_field.name == 'slice':
Tony Mack5b061472014-02-04 07:57:10 -0500818 kwargs['queryset'] = Slice.select_by_user(request.user)
Tony Mackc2835a92013-05-28 09:18:49 -0400819
820 return super(SliverAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)
821
Tony Mack04062832013-05-10 08:22:44 -0400822 def queryset(self, request):
823 # admins can see all slivers. Users can only see slivers of
824 # the slices they belong to.
Tony Mack5b061472014-02-04 07:57:10 -0500825 return Sliver.select_by_user(request.user)
826
Tony Mack04062832013-05-10 08:22:44 -0400827
Tony Mack1d6b85f2013-05-07 18:49:14 -0400828 def get_formsets(self, request, obj=None):
829 # make some fields read only if we are updating an existing record
830 if obj == None:
831 #self.readonly_fields = ('ip', 'instance_name')
832 self.readonly_fields = ()
833 else:
Tony Mack1e889462013-05-10 21:34:54 -0400834 self.readonly_fields = ()
835 #self.readonly_fields = ('ip', 'instance_name', 'slice', 'image', 'key')
Tony Mack1d6b85f2013-05-07 18:49:14 -0400836
837 for inline in self.get_inline_instances(request, obj):
838 # hide MyInline in the add view
839 if obj is None:
840 continue
Scott Baker526b71e2014-05-13 13:18:01 -0700841 if isinstance(inline, SliverInline):
842 inline.model.caller = request.user
843 yield inline.get_formset(request, obj)
Tony Mack53106f32013-04-27 16:43:01 -0400844
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500845 #def save_model(self, request, obj, form, change):
846 # # update openstack connection to use this site/tenant
847 # auth = request.session.get('auth', {})
848 # auth['tenant'] = obj.slice.name
849 # obj.os_manager = OpenStackManager(auth=auth, caller=request.user)
850 # obj.creator = request.user
851 # obj.save()
Tony Mack53106f32013-04-27 16:43:01 -0400852
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500853 #def delete_model(self, request, obj):
854 # # update openstack connection to use this site/tenant
855 # auth = request.session.get('auth', {})
856 # auth['tenant'] = obj.slice.name
857 # obj.os_manager = OpenStackManager(auth=auth, caller=request.user)
858 # obj.delete()
Tony Mackcdec0902013-04-15 00:38:49 -0400859
Siobhan Tully53437282013-04-26 19:30:27 -0400860class UserCreationForm(forms.ModelForm):
861 """A form for creating new users. Includes all the required
862 fields, plus a repeated password."""
863 password1 = forms.CharField(label='Password', widget=forms.PasswordInput)
864 password2 = forms.CharField(label='Password confirmation', widget=forms.PasswordInput)
865
866 class Meta:
Siobhan Tully30fd4292013-05-10 08:59:56 -0400867 model = User
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400868 fields = ('email', 'firstname', 'lastname', 'phone', 'public_key')
Siobhan Tully53437282013-04-26 19:30:27 -0400869
870 def clean_password2(self):
871 # Check that the two password entries match
872 password1 = self.cleaned_data.get("password1")
873 password2 = self.cleaned_data.get("password2")
874 if password1 and password2 and password1 != password2:
875 raise forms.ValidationError("Passwords don't match")
876 return password2
877
878 def save(self, commit=True):
879 # Save the provided password in hashed format
880 user = super(UserCreationForm, self).save(commit=False)
Tony Mackf9f4afb2013-05-01 21:02:12 -0400881 user.password = self.cleaned_data["password1"]
882 #user.set_password(self.cleaned_data["password1"])
Siobhan Tully53437282013-04-26 19:30:27 -0400883 if commit:
884 user.save()
885 return user
886
Siobhan Tully567e3e62013-06-21 18:03:16 -0400887
Siobhan Tully53437282013-04-26 19:30:27 -0400888class UserChangeForm(forms.ModelForm):
889 """A form for updating users. Includes all the fields on
890 the user, but replaces the password field with admin's
891 password hash display field.
892 """
Siobhan Tully63b7ba42014-01-12 10:35:11 -0500893 password = ReadOnlyPasswordHashField(label='Password',
894 help_text= '<a href=\"password/\">Change Password</a>.')
Siobhan Tully53437282013-04-26 19:30:27 -0400895
896 class Meta:
Siobhan Tully30fd4292013-05-10 08:59:56 -0400897 model = User
Siobhan Tully53437282013-04-26 19:30:27 -0400898
899 def clean_password(self):
900 # Regardless of what the user provides, return the initial value.
901 # This is done here, rather than on the field, because the
902 # field does not have access to the initial value
903 return self.initial["password"]
904
Scott Baker2c3cb642014-05-19 17:55:56 -0700905class UserDashboardViewInline(PlStackTabularInline):
906 model = UserDashboardView
907 extra = 0
908 suit_classes = 'suit-tab suit-tab-dashboards'
909 fields = ['user', 'dashboardView', 'order']
910
Scott Bakered31f672014-05-21 18:14:03 -0700911class UserDashboardViewROInline(ReadOnlyTabularInline):
912 model = UserDashboardView
913 extra = 0
914 suit_classes = 'suit-tab suit-tab-dashboards'
915 fields = ['user', 'dashboardView', 'order']
916
Tony Mack2bd5b412013-06-11 21:05:06 -0400917class UserAdmin(UserAdmin):
Siobhan Tully53437282013-04-26 19:30:27 -0400918 class Meta:
919 app_label = "core"
920
921 # The forms to add and change user instances
922 form = UserChangeForm
923 add_form = UserCreationForm
924
925 # The fields to be used in displaying the User model.
926 # These override the definitions on the base UserAdmin
927 # that reference specific fields on auth.User.
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500928 list_display = ('email', 'firstname', 'lastname', 'site', 'last_login')
Siobhan Tullyce652d02013-10-08 21:52:35 -0400929 #list_display = ('email', 'username','firstname', 'lastname', 'is_admin', 'last_login')
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500930 list_filter = ('site',)
Scott Baker2c3cb642014-05-19 17:55:56 -0700931 inlines = [SlicePrivilegeInline,SitePrivilegeInline,DeploymentPrivilegeInline,UserDashboardViewInline]
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500932
933 fieldListLoginDetails = ['email','site','password','is_readonly','is_amin','public_key']
934 fieldListContactInfo = ['firstname','lastname','phone','timezone']
935
Siobhan Tully53437282013-04-26 19:30:27 -0400936 fieldsets = (
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500937 ('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 -0400938 ('Contact Information', {'fields': ('firstname','lastname','phone', 'timezone'), 'classes':['suit-tab suit-tab-contact']}),
Scott Baker2c3cb642014-05-19 17:55:56 -0700939 #('Dashboard Views', {'fields': ('dashboards',), 'classes':['suit-tab suit-tab-dashboards']}),
Siobhan Tully53437282013-04-26 19:30:27 -0400940 #('Important dates', {'fields': ('last_login',)}),
941 )
942 add_fieldsets = (
943 (None, {
944 'classes': ('wide',),
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500945 'fields': ('email', 'firstname', 'lastname', 'is_readonly', 'phone', 'public_key','password1', 'password2')}
Siobhan Tully53437282013-04-26 19:30:27 -0400946 ),
947 )
948 search_fields = ('email',)
949 ordering = ('email',)
950 filter_horizontal = ()
951
Scott Baker3ca51f62014-05-23 12:05:11 -0700952 user_readonly_fields = fieldListLoginDetails + fieldListContactInfo
Scott Bakered31f672014-05-21 18:14:03 -0700953 user_readonly_inlines = [SlicePrivilegeROInline,SitePrivilegeROInline,DeploymentPrivilegeROInline,UserDashboardViewROInline]
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500954
Scott Baker2c3cb642014-05-19 17:55:56 -0700955 suit_form_tabs =(('general','Login Details'),
956 ('contact','Contact Information'),
957 ('sliceprivileges','Slice Privileges'),
958 ('siteprivileges','Site Privileges'),
959 ('deploymentprivileges','Deployment Privileges'),
960 ('dashboards','Dashboard Views'))
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400961
Tony Mackc2835a92013-05-28 09:18:49 -0400962 def formfield_for_foreignkey(self, db_field, request, **kwargs):
963 if db_field.name == 'site':
Tony Mack5b061472014-02-04 07:57:10 -0500964 kwargs['queryset'] = Site.select_by_user(request.user)
Tony Mackc2835a92013-05-28 09:18:49 -0400965
966 return super(UserAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)
967
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500968 def has_add_permission(self, request, obj=None):
969 return (not self.__user_is_readonly(request))
970
971 def has_delete_permission(self, request, obj=None):
972 return (not self.__user_is_readonly(request))
973
974 def get_actions(self,request):
975 actions = super(UserAdmin,self).get_actions(request)
976
977 if self.__user_is_readonly(request):
978 if 'delete_selected' in actions:
979 del actions['delete_selected']
980
981 return actions
982
983 def change_view(self,request,object_id, extra_context=None):
984
985 if self.__user_is_readonly(request):
Scott Bakerf875eba2014-05-23 12:09:15 -0700986 if not hasattr(self, "readonly_save"):
987 # save the original readonly fields
988 self.readonly_save = self.readonly_fields
989 self.inlines_save = self.inlines
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500990 self.readonly_fields=self.user_readonly_fields
991 self.inlines = self.user_readonly_inlines
Scott Bakerf875eba2014-05-23 12:09:15 -0700992 else:
993 if hasattr(self, "readonly_save"):
994 # restore the original readonly fields
995 self.readonly_fields = self.readonly_save
996 self.inlines = self.inlines_save
997
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500998 try:
999 return super(UserAdmin, self).change_view(request, object_id, extra_context=extra_context)
1000 except PermissionDenied:
1001 pass
1002 if request.method == 'POST':
1003 raise PermissionDenied
1004 request.readonly = True
1005 return super(UserAdmin, self).change_view(request, object_id, extra_context=extra_context)
1006
1007 def __user_is_readonly(self, request):
1008 #groups = [x.name for x in request.user.groups.all() ]
1009 #return "readonly" in groups
1010 return request.user.isReadOnlyUser()
1011
Tony Mack5b061472014-02-04 07:57:10 -05001012 def queryset(self, request):
1013 return User.select_by_user(request.user)
1014
Scott Baker2c3cb642014-05-19 17:55:56 -07001015class DashboardViewAdmin(PlanetStackBaseAdmin):
1016 fieldsets = [('Dashboard View Details',
1017 {'fields': ['name', 'url'],
1018 'classes': ['suit-tab suit-tab-general']})
1019 ]
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001020
Scott Baker2c3cb642014-05-19 17:55:56 -07001021 suit_form_tabs =(('general','Dashboard View Details'),)
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001022
1023class ServiceResourceROInline(ReadOnlyTabularInline):
1024 model = ServiceResource
1025 extra = 0
1026 fields = ['serviceClass', 'name', 'maxUnitsDeployment', 'maxUnitsNode', 'maxDuration', 'bucketInRate', 'bucketMaxSize', 'cost', 'calendarReservable']
1027
Scott Baker0165fac2014-01-13 11:49:26 -08001028class ServiceResourceInline(PlStackTabularInline):
Scott Baker3de3e372013-05-10 16:50:44 -07001029 model = ServiceResource
1030 extra = 0
1031
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001032class ServiceClassAdmin(PlanetStackBaseAdmin):
Scott Baker3de3e372013-05-10 16:50:44 -07001033 list_display = ('name', 'commitment', 'membershipFee')
1034 inlines = [ServiceResourceInline]
1035
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001036 user_readonly_fields = ['name', 'commitment', 'membershipFee']
1037 user_readonly_inlines = []
1038
1039class ReservedResourceROInline(ReadOnlyTabularInline):
1040 model = ReservedResource
1041 extra = 0
1042 fields = ['sliver', 'resource','quantity','reservationSet']
1043 suit_classes = 'suit-tab suit-tab-reservedresources'
1044
Scott Baker0165fac2014-01-13 11:49:26 -08001045class ReservedResourceInline(PlStackTabularInline):
Scott Baker133c9212013-05-17 09:09:11 -07001046 model = ReservedResource
1047 extra = 0
Siobhan Tullybfd11dc2013-09-03 12:59:24 -04001048 suit_classes = 'suit-tab suit-tab-reservedresources'
Scott Baker133c9212013-05-17 09:09:11 -07001049
1050 def formfield_for_foreignkey(self, db_field, request=None, **kwargs):
1051 field = super(ReservedResourceInline, self).formfield_for_foreignkey(db_field, request, **kwargs)
1052
1053 if db_field.name == 'resource':
1054 # restrict resources to those that the slice's service class allows
1055 if request._slice is not None:
1056 field.queryset = field.queryset.filter(serviceClass = request._slice.serviceClass, calendarReservable=True)
1057 if len(field.queryset) > 0:
1058 field.initial = field.queryset.all()[0]
1059 else:
1060 field.queryset = field.queryset.none()
1061 elif db_field.name == 'sliver':
1062 # restrict slivers to those that belong to the slice
1063 if request._slice is not None:
1064 field.queryset = field.queryset.filter(slice = request._slice)
1065 else:
1066 field.queryset = field.queryset.none()
1067
1068 return field
1069
Tony Mack5b061472014-02-04 07:57:10 -05001070 def queryset(self, request):
1071 return ReservedResource.select_by_user(request.user)
1072
Scott Baker133c9212013-05-17 09:09:11 -07001073class ReservationChangeForm(forms.ModelForm):
1074 class Meta:
1075 model = Reservation
Siobhan Tullybfd11dc2013-09-03 12:59:24 -04001076 widgets = {
1077 'slice' : LinkedSelect
1078 }
Scott Baker133c9212013-05-17 09:09:11 -07001079
1080class ReservationAddForm(forms.ModelForm):
1081 slice = forms.ModelChoiceField(queryset=Slice.objects.all(), widget=forms.Select(attrs={"onChange":"document.getElementById('id_refresh').value=1; submit()"}))
1082 refresh = forms.CharField(widget=forms.HiddenInput())
1083
1084 class Media:
1085 css = {'all': ('planetstack.css',)} # .field-refresh { display: none; }
1086
1087 def clean_slice(self):
1088 slice = self.cleaned_data.get("slice")
1089 x = ServiceResource.objects.filter(serviceClass = slice.serviceClass, calendarReservable=True)
1090 if len(x) == 0:
1091 raise forms.ValidationError("The slice you selected does not have a service class that allows reservations")
1092 return slice
1093
1094 class Meta:
1095 model = Reservation
Siobhan Tullybfd11dc2013-09-03 12:59:24 -04001096 widgets = {
1097 'slice' : LinkedSelect
1098 }
1099
Scott Baker133c9212013-05-17 09:09:11 -07001100
1101class ReservationAddRefreshForm(ReservationAddForm):
1102 """ This form is displayed when the Reservation Form receives an update
1103 from the Slice dropdown onChange handler. It doesn't validate the
1104 data and doesn't save the data. This will cause the form to be
1105 redrawn.
1106 """
1107
Scott Baker8737e5f2013-05-17 09:35:32 -07001108 """ don't validate anything other than slice """
1109 dont_validate_fields = ("startTime", "duration")
1110
Scott Baker133c9212013-05-17 09:09:11 -07001111 def full_clean(self):
1112 result = super(ReservationAddForm, self).full_clean()
Scott Baker8737e5f2013-05-17 09:35:32 -07001113
1114 for fieldname in self.dont_validate_fields:
1115 if fieldname in self._errors:
1116 del self._errors[fieldname]
1117
Scott Baker133c9212013-05-17 09:09:11 -07001118 return result
1119
1120 """ don't save anything """
1121 def is_valid(self):
1122 return False
1123
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001124class ReservationAdmin(PlanetStackBaseAdmin):
1125 fieldList = ['slice', 'startTime', 'duration']
1126 fieldsets = [('Reservation Details', {'fields': fieldList, 'classes': ['suit-tab suit-tab-general']})]
Scott Baker133c9212013-05-17 09:09:11 -07001127 list_display = ('startTime', 'duration')
Scott Baker133c9212013-05-17 09:09:11 -07001128 form = ReservationAddForm
1129
Siobhan Tullybfd11dc2013-09-03 12:59:24 -04001130 suit_form_tabs = (('general','Reservation Details'), ('reservedresources','Reserved Resources'))
1131
1132 inlines = [ReservedResourceInline]
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001133 user_readonly_inlines = [ReservedResourceROInline]
1134 user_readonly_fields = fieldList
Siobhan Tullybfd11dc2013-09-03 12:59:24 -04001135
Scott Baker133c9212013-05-17 09:09:11 -07001136 def add_view(self, request, form_url='', extra_context=None):
Scott Bakeracd45142013-05-19 16:19:16 -07001137 timezone.activate(request.user.timezone)
Scott Baker133c9212013-05-17 09:09:11 -07001138 request._refresh = False
1139 request._slice = None
1140 if request.method == 'POST':
Scott Baker8737e5f2013-05-17 09:35:32 -07001141 # "refresh" will be set to "1" if the form was submitted due to
1142 # a change in the Slice dropdown.
Scott Baker133c9212013-05-17 09:09:11 -07001143 if request.POST.get("refresh","1") == "1":
1144 request._refresh = True
1145 request.POST["refresh"] = "0"
Scott Baker8737e5f2013-05-17 09:35:32 -07001146
1147 # Keep track of the slice that was selected, so the
1148 # reservedResource inline can filter items for the slice.
Scott Baker133c9212013-05-17 09:09:11 -07001149 request._slice = request.POST.get("slice",None)
1150 if (request._slice is not None):
1151 request._slice = Slice.objects.get(id=request._slice)
1152
1153 result = super(ReservationAdmin, self).add_view(request, form_url, extra_context)
1154 return result
1155
Scott Bakeracd45142013-05-19 16:19:16 -07001156 def changelist_view(self, request, extra_context = None):
1157 timezone.activate(request.user.timezone)
1158 return super(ReservationAdmin, self).changelist_view(request, extra_context)
1159
Scott Baker133c9212013-05-17 09:09:11 -07001160 def get_form(self, request, obj=None, **kwargs):
Siobhan Tullyd3515752013-06-21 16:34:53 -04001161 request._obj_ = obj
1162 if obj is not None:
1163 # For changes, set request._slice to the slice already set in the
1164 # object.
1165 request._slice = obj.slice
1166 self.form = ReservationChangeForm
1167 else:
1168 if getattr(request, "_refresh", False):
1169 self.form = ReservationAddRefreshForm
1170 else:
1171 self.form = ReservationAddForm
1172 return super(ReservationAdmin, self).get_form(request, obj, **kwargs)
1173
Scott Baker133c9212013-05-17 09:09:11 -07001174 def get_readonly_fields(self, request, obj=None):
Siobhan Tullyd3515752013-06-21 16:34:53 -04001175 if (obj is not None):
1176 # Prevent slice from being changed after the reservation has been
1177 # created.
1178 return ['slice']
1179 else:
Scott Baker133c9212013-05-17 09:09:11 -07001180 return []
Scott Baker3de3e372013-05-10 16:50:44 -07001181
Tony Mack5b061472014-02-04 07:57:10 -05001182 def queryset(self, request):
1183 return Reservation.select_by_user(request.user)
1184
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001185class NetworkParameterTypeAdmin(PlanetStackBaseAdmin):
Scott Baker74d8e622013-07-29 16:04:22 -07001186 list_display = ("name", )
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001187 user_readonly_fields = ['name']
1188 user_readonly_inlines = []
Scott Baker74d8e622013-07-29 16:04:22 -07001189
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001190class RouterAdmin(PlanetStackBaseAdmin):
Scott Baker74d8e622013-07-29 16:04:22 -07001191 list_display = ("name", )
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001192 user_readonly_fields = ['name']
1193 user_readonly_inlines = []
1194
1195class RouterROInline(ReadOnlyTabularInline):
1196 model = Router.networks.through
1197 extra = 0
1198 verbose_name_plural = "Routers"
1199 verbose_name = "Router"
1200 suit_classes = 'suit-tab suit-tab-routers'
1201
1202 fields = ['name', 'owner', 'permittedNetworks', 'networks']
Scott Baker74d8e622013-07-29 16:04:22 -07001203
Scott Baker0165fac2014-01-13 11:49:26 -08001204class RouterInline(PlStackTabularInline):
Scott Baker74d8e622013-07-29 16:04:22 -07001205 model = Router.networks.through
1206 extra = 0
1207 verbose_name_plural = "Routers"
1208 verbose_name = "Router"
Siobhan Tully2d95e482013-09-06 10:56:06 -04001209 suit_classes = 'suit-tab suit-tab-routers'
Scott Baker74d8e622013-07-29 16:04:22 -07001210
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001211class NetworkParameterROInline(ReadOnlyTabularInline):
1212 model = NetworkParameter
1213 extra = 1
1214 verbose_name_plural = "Parameters"
1215 verbose_name = "Parameter"
1216 suit_classes = 'suit-tab suit-tab-netparams'
1217 fields = ['parameter', 'value', 'content_type', 'object_id', 'content_object']
1218
Scott Baker74d8e622013-07-29 16:04:22 -07001219class NetworkParameterInline(generic.GenericTabularInline):
Scott Baker74d8e622013-07-29 16:04:22 -07001220 model = NetworkParameter
1221 extra = 1
1222 verbose_name_plural = "Parameters"
1223 verbose_name = "Parameter"
Siobhan Tully2d95e482013-09-06 10:56:06 -04001224 suit_classes = 'suit-tab suit-tab-netparams'
Scott Baker74d8e622013-07-29 16:04:22 -07001225
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001226class NetworkSliversROInline(ReadOnlyTabularInline):
1227 fields = ['network', 'sliver', 'ip', 'port_id']
1228 model = NetworkSliver
1229 extra = 0
1230 verbose_name_plural = "Slivers"
1231 verbose_name = "Sliver"
1232 suit_classes = 'suit-tab suit-tab-networkslivers'
1233
Scott Baker0165fac2014-01-13 11:49:26 -08001234class NetworkSliversInline(PlStackTabularInline):
Scott Baker74d8e622013-07-29 16:04:22 -07001235 readonly_fields = ("ip", )
1236 model = NetworkSliver
Scott Baker874936e2014-01-13 18:15:34 -08001237 selflink_fieldname = "sliver"
Scott Baker74d8e622013-07-29 16:04:22 -07001238 extra = 0
1239 verbose_name_plural = "Slivers"
1240 verbose_name = "Sliver"
Siobhan Tully2d95e482013-09-06 10:56:06 -04001241 suit_classes = 'suit-tab suit-tab-networkslivers'
Scott Baker74d8e622013-07-29 16:04:22 -07001242
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001243class NetworkSlicesROInline(ReadOnlyTabularInline):
1244 model = NetworkSlice
1245 extra = 0
1246 verbose_name_plural = "Slices"
1247 verbose_name = "Slice"
1248 suit_classes = 'suit-tab suit-tab-networkslices'
1249 fields = ['network','slice']
1250
Scott Baker0165fac2014-01-13 11:49:26 -08001251class NetworkSlicesInline(PlStackTabularInline):
Scott Bakerd7d2a392013-08-06 08:57:30 -07001252 model = NetworkSlice
Scott Baker874936e2014-01-13 18:15:34 -08001253 selflink_fieldname = "slice"
Scott Bakerd7d2a392013-08-06 08:57:30 -07001254 extra = 0
1255 verbose_name_plural = "Slices"
1256 verbose_name = "Slice"
Siobhan Tully2d95e482013-09-06 10:56:06 -04001257 suit_classes = 'suit-tab suit-tab-networkslices'
Scott Bakerd7d2a392013-08-06 08:57:30 -07001258
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001259class NetworkAdmin(PlanetStackBaseAdmin):
Scott Baker74d8e622013-07-29 16:04:22 -07001260 list_display = ("name", "subnet", "ports", "labels")
1261 readonly_fields = ("subnet", )
Siobhan Tully2d95e482013-09-06 10:56:06 -04001262
Scott Bakerd7d2a392013-08-06 08:57:30 -07001263 inlines = [NetworkParameterInline, NetworkSliversInline, NetworkSlicesInline, RouterInline]
Scott Baker74d8e622013-07-29 16:04:22 -07001264
Siobhan Tully2d95e482013-09-06 10:56:06 -04001265 fieldsets = [
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001266 (None, {'fields': ['name','template','ports','labels','owner','guaranteedBandwidth', 'permitAllSlices','permittedSlices','network_id','router_id','subnet_id','subnet'], 'classes':['suit-tab suit-tab-general']}),]
1267
1268 user_readonly_fields = ['name','template','ports','labels','owner','guaranteedBandwidth', 'permitAllSlices','permittedSlices','network_id','router_id','subnet_id','subnet']
1269 user_readonly_inlines = [NetworkParameterROInline, NetworkSliversROInline, NetworkSlicesROInline, RouterROInline]
Siobhan Tully2d95e482013-09-06 10:56:06 -04001270
1271 suit_form_tabs =(
1272 ('general','Network Details'),
1273 ('netparams', 'Parameters'),
1274 ('networkslivers','Slivers'),
1275 ('networkslices','Slices'),
1276 ('routers','Routers'),
1277 )
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001278class NetworkTemplateAdmin(PlanetStackBaseAdmin):
Scott Baker74d8e622013-07-29 16:04:22 -07001279 list_display = ("name", "guaranteedBandwidth", "visibility")
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001280 user_readonly_fields = ["name", "guaranteedBandwidth", "visibility"]
1281 user_readonly_inlines = []
Scott Baker74d8e622013-07-29 16:04:22 -07001282
Tony Mack31c2b8f2013-04-26 20:01:42 -04001283# register a signal that caches the user's credentials when they log in
1284def cache_credentials(sender, user, request, **kwds):
1285 auth = {'username': request.POST['username'],
1286 'password': request.POST['password']}
1287 request.session['auth'] = auth
1288user_logged_in.connect(cache_credentials)
1289
Scott Baker15cddfa2013-12-09 13:45:19 -08001290def dollar_field(fieldName, short_description):
1291 def newFunc(self, obj):
1292 try:
1293 x= "$ %0.2f" % float(getattr(obj, fieldName, 0.0))
1294 except:
1295 x=getattr(obj, fieldName, 0.0)
1296 return x
1297 newFunc.short_description = short_description
1298 return newFunc
1299
1300def right_dollar_field(fieldName, short_description):
1301 def newFunc(self, obj):
1302 try:
1303 #x= '<div align=right style="width:6em">$ %0.2f</div>' % float(getattr(obj, fieldName, 0.0))
1304 x= '<div align=right>$ %0.2f</div>' % float(getattr(obj, fieldName, 0.0))
1305 except:
1306 x=getattr(obj, fieldName, 0.0)
1307 return x
1308 newFunc.short_description = short_description
1309 newFunc.allow_tags = True
1310 return newFunc
Scott Baker43105042013-12-06 23:23:36 -08001311
Scott Baker0165fac2014-01-13 11:49:26 -08001312class InvoiceChargeInline(PlStackTabularInline):
Scott Baker43105042013-12-06 23:23:36 -08001313 model = Charge
Scott Baker15cddfa2013-12-09 13:45:19 -08001314 extra = 0
Scott Baker43105042013-12-06 23:23:36 -08001315 verbose_name_plural = "Charges"
1316 verbose_name = "Charge"
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001317 exclude = ['account']
Scott Baker9cb88a22013-12-09 18:56:00 -08001318 fields = ["date", "kind", "state", "object", "coreHours", "dollar_amount", "slice"]
1319 readonly_fields = ["date", "kind", "state", "object", "coreHours", "dollar_amount", "slice"]
1320 can_delete = False
1321 max_num = 0
1322
1323 dollar_amount = right_dollar_field("amount", "Amount")
Scott Baker43105042013-12-06 23:23:36 -08001324
1325class InvoiceAdmin(admin.ModelAdmin):
1326 list_display = ("date", "account")
1327
1328 inlines = [InvoiceChargeInline]
1329
Scott Baker9cb88a22013-12-09 18:56:00 -08001330 fields = ["date", "account", "dollar_amount"]
1331 readonly_fields = ["date", "account", "dollar_amount"]
1332
1333 dollar_amount = dollar_field("amount", "Amount")
Scott Baker43105042013-12-06 23:23:36 -08001334
Scott Baker0165fac2014-01-13 11:49:26 -08001335class InvoiceInline(PlStackTabularInline):
Scott Baker15cddfa2013-12-09 13:45:19 -08001336 model = Invoice
1337 extra = 0
1338 verbose_name_plural = "Invoices"
1339 verbose_name = "Invoice"
Scott Baker0165fac2014-01-13 11:49:26 -08001340 fields = ["date", "dollar_amount"]
1341 readonly_fields = ["date", "dollar_amount"]
Scott Baker15cddfa2013-12-09 13:45:19 -08001342 suit_classes = 'suit-tab suit-tab-accountinvoice'
1343 can_delete=False
1344 max_num=0
1345
1346 dollar_amount = right_dollar_field("amount", "Amount")
1347
Scott Baker0165fac2014-01-13 11:49:26 -08001348class PendingChargeInline(PlStackTabularInline):
Scott Baker43105042013-12-06 23:23:36 -08001349 model = Charge
Scott Baker15cddfa2013-12-09 13:45:19 -08001350 extra = 0
Scott Baker43105042013-12-06 23:23:36 -08001351 verbose_name_plural = "Charges"
1352 verbose_name = "Charge"
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001353 exclude = ["invoice"]
Scott Baker15cddfa2013-12-09 13:45:19 -08001354 fields = ["date", "kind", "state", "object", "coreHours", "dollar_amount", "slice"]
1355 readonly_fields = ["date", "kind", "state", "object", "coreHours", "dollar_amount", "slice"]
Scott Baker43105042013-12-06 23:23:36 -08001356 suit_classes = 'suit-tab suit-tab-accountpendingcharges'
Scott Baker15cddfa2013-12-09 13:45:19 -08001357 can_delete=False
1358 max_num=0
Scott Baker43105042013-12-06 23:23:36 -08001359
1360 def queryset(self, request):
1361 qs = super(PendingChargeInline, self).queryset(request)
1362 qs = qs.filter(state="pending")
1363 return qs
1364
Scott Baker15cddfa2013-12-09 13:45:19 -08001365 dollar_amount = right_dollar_field("amount", "Amount")
1366
Scott Baker0165fac2014-01-13 11:49:26 -08001367class PaymentInline(PlStackTabularInline):
Scott Baker43105042013-12-06 23:23:36 -08001368 model=Payment
1369 extra = 1
1370 verbose_name_plural = "Payments"
1371 verbose_name = "Payment"
Scott Baker15cddfa2013-12-09 13:45:19 -08001372 fields = ["date", "dollar_amount"]
1373 readonly_fields = ["date", "dollar_amount"]
Scott Baker43105042013-12-06 23:23:36 -08001374 suit_classes = 'suit-tab suit-tab-accountpayments'
Scott Baker15cddfa2013-12-09 13:45:19 -08001375 can_delete=False
1376 max_num=0
1377
1378 dollar_amount = right_dollar_field("amount", "Amount")
1379
Scott Baker43105042013-12-06 23:23:36 -08001380class AccountAdmin(admin.ModelAdmin):
1381 list_display = ("site", "balance_due")
1382
1383 inlines = [InvoiceInline, PaymentInline, PendingChargeInline]
1384
1385 fieldsets = [
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001386 (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 -08001387
Scott Baker15cddfa2013-12-09 13:45:19 -08001388 readonly_fields = ['site', 'dollar_balance_due', 'dollar_total_invoices', 'dollar_total_payments']
Scott Baker43105042013-12-06 23:23:36 -08001389
1390 suit_form_tabs =(
1391 ('general','Account Details'),
1392 ('accountinvoice', 'Invoices'),
1393 ('accountpayments', 'Payments'),
1394 ('accountpendingcharges','Pending Charges'),
1395 )
1396
Scott Baker15cddfa2013-12-09 13:45:19 -08001397 dollar_balance_due = dollar_field("balance_due", "Balance Due")
1398 dollar_total_invoices = dollar_field("total_invoices", "Total Invoices")
1399 dollar_total_payments = dollar_field("total_payments", "Total Payments")
1400
Siobhan Tullyce652d02013-10-08 21:52:35 -04001401
Siobhan Tully53437282013-04-26 19:30:27 -04001402# Now register the new UserAdmin...
Siobhan Tully30fd4292013-05-10 08:59:56 -04001403admin.site.register(User, UserAdmin)
Siobhan Tully53437282013-04-26 19:30:27 -04001404# ... and, since we're not using Django's builtin permissions,
1405# unregister the Group model from admin.
Siobhan Tullyce652d02013-10-08 21:52:35 -04001406#admin.site.unregister(Group)
Siobhan Tully53437282013-04-26 19:30:27 -04001407
Siobhan Tullybf1153a2013-05-27 20:53:48 -04001408#Do not show django evolution in the admin interface
1409from django_evolution.models import Version, Evolution
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001410#admin.site.unregister(Version)
1411#admin.site.unregister(Evolution)
Siobhan Tullybf1153a2013-05-27 20:53:48 -04001412
1413
1414# When debugging it is often easier to see all the classes, but for regular use
1415# only the top-levels should be displayed
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001416showAll = False
Scott Baker43105042013-12-06 23:23:36 -08001417
Siobhan Tullybf1153a2013-05-27 20:53:48 -04001418admin.site.register(Deployment, DeploymentAdmin)
Siobhan Tully4bc09f22013-04-10 21:15:21 -04001419admin.site.register(Site, SiteAdmin)
Siobhan Tully4bc09f22013-04-10 21:15:21 -04001420admin.site.register(Slice, SliceAdmin)
Siobhan Tullyce652d02013-10-08 21:52:35 -04001421admin.site.register(Service, ServiceAdmin)
smbakera3cf70c2013-06-27 02:01:41 -07001422admin.site.register(Reservation, ReservationAdmin)
Scott Baker74d8e622013-07-29 16:04:22 -07001423admin.site.register(Network, NetworkAdmin)
1424admin.site.register(Router, RouterAdmin)
Scott Baker74d8e622013-07-29 16:04:22 -07001425admin.site.register(NetworkTemplate, NetworkTemplateAdmin)
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001426admin.site.register(Account, AccountAdmin)
1427admin.site.register(Invoice, InvoiceAdmin)
Siobhan Tullybf1153a2013-05-27 20:53:48 -04001428
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001429if True:
1430 admin.site.register(NetworkParameterType, NetworkParameterTypeAdmin)
1431 admin.site.register(ServiceClass, ServiceClassAdmin)
Siobhan Tullybfd11dc2013-09-03 12:59:24 -04001432 #admin.site.register(PlanetStack)
Siobhan Tullyd3515752013-06-21 16:34:53 -04001433 admin.site.register(Tag, TagAdmin)
Siobhan Tullyce652d02013-10-08 21:52:35 -04001434 admin.site.register(DeploymentRole)
1435 admin.site.register(SiteRole)
1436 admin.site.register(SliceRole)
1437 admin.site.register(PlanetStackRole)
Siobhan Tullybf1153a2013-05-27 20:53:48 -04001438 admin.site.register(Node, NodeAdmin)
Siobhan Tullybfd11dc2013-09-03 12:59:24 -04001439 #admin.site.register(SlicePrivilege, SlicePrivilegeAdmin)
1440 #admin.site.register(SitePrivilege, SitePrivilegeAdmin)
Siobhan Tullybf1153a2013-05-27 20:53:48 -04001441 admin.site.register(Sliver, SliverAdmin)
Siobhan Tullybf1153a2013-05-27 20:53:48 -04001442 admin.site.register(Image, ImageAdmin)
Scott Baker2c3cb642014-05-19 17:55:56 -07001443 admin.site.register(DashboardView, DashboardViewAdmin)
Tony Mack7130ac32013-03-22 21:58:00 -04001444