blob: 767c65e5e160856de22026c2621c5408f684380d [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):
986 self.readonly_fields=self.user_readonly_fields
987 self.inlines = self.user_readonly_inlines
988 try:
989 return super(UserAdmin, self).change_view(request, object_id, extra_context=extra_context)
990 except PermissionDenied:
991 pass
992 if request.method == 'POST':
993 raise PermissionDenied
994 request.readonly = True
995 return super(UserAdmin, self).change_view(request, object_id, extra_context=extra_context)
996
997 def __user_is_readonly(self, request):
998 #groups = [x.name for x in request.user.groups.all() ]
999 #return "readonly" in groups
1000 return request.user.isReadOnlyUser()
1001
Tony Mack5b061472014-02-04 07:57:10 -05001002 def queryset(self, request):
1003 return User.select_by_user(request.user)
1004
Scott Baker2c3cb642014-05-19 17:55:56 -07001005class DashboardViewAdmin(PlanetStackBaseAdmin):
1006 fieldsets = [('Dashboard View Details',
1007 {'fields': ['name', 'url'],
1008 'classes': ['suit-tab suit-tab-general']})
1009 ]
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001010
Scott Baker2c3cb642014-05-19 17:55:56 -07001011 suit_form_tabs =(('general','Dashboard View Details'),)
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001012
1013class ServiceResourceROInline(ReadOnlyTabularInline):
1014 model = ServiceResource
1015 extra = 0
1016 fields = ['serviceClass', 'name', 'maxUnitsDeployment', 'maxUnitsNode', 'maxDuration', 'bucketInRate', 'bucketMaxSize', 'cost', 'calendarReservable']
1017
Scott Baker0165fac2014-01-13 11:49:26 -08001018class ServiceResourceInline(PlStackTabularInline):
Scott Baker3de3e372013-05-10 16:50:44 -07001019 model = ServiceResource
1020 extra = 0
1021
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001022class ServiceClassAdmin(PlanetStackBaseAdmin):
Scott Baker3de3e372013-05-10 16:50:44 -07001023 list_display = ('name', 'commitment', 'membershipFee')
1024 inlines = [ServiceResourceInline]
1025
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001026 user_readonly_fields = ['name', 'commitment', 'membershipFee']
1027 user_readonly_inlines = []
1028
1029class ReservedResourceROInline(ReadOnlyTabularInline):
1030 model = ReservedResource
1031 extra = 0
1032 fields = ['sliver', 'resource','quantity','reservationSet']
1033 suit_classes = 'suit-tab suit-tab-reservedresources'
1034
Scott Baker0165fac2014-01-13 11:49:26 -08001035class ReservedResourceInline(PlStackTabularInline):
Scott Baker133c9212013-05-17 09:09:11 -07001036 model = ReservedResource
1037 extra = 0
Siobhan Tullybfd11dc2013-09-03 12:59:24 -04001038 suit_classes = 'suit-tab suit-tab-reservedresources'
Scott Baker133c9212013-05-17 09:09:11 -07001039
1040 def formfield_for_foreignkey(self, db_field, request=None, **kwargs):
1041 field = super(ReservedResourceInline, self).formfield_for_foreignkey(db_field, request, **kwargs)
1042
1043 if db_field.name == 'resource':
1044 # restrict resources to those that the slice's service class allows
1045 if request._slice is not None:
1046 field.queryset = field.queryset.filter(serviceClass = request._slice.serviceClass, calendarReservable=True)
1047 if len(field.queryset) > 0:
1048 field.initial = field.queryset.all()[0]
1049 else:
1050 field.queryset = field.queryset.none()
1051 elif db_field.name == 'sliver':
1052 # restrict slivers to those that belong to the slice
1053 if request._slice is not None:
1054 field.queryset = field.queryset.filter(slice = request._slice)
1055 else:
1056 field.queryset = field.queryset.none()
1057
1058 return field
1059
Tony Mack5b061472014-02-04 07:57:10 -05001060 def queryset(self, request):
1061 return ReservedResource.select_by_user(request.user)
1062
Scott Baker133c9212013-05-17 09:09:11 -07001063class ReservationChangeForm(forms.ModelForm):
1064 class Meta:
1065 model = Reservation
Siobhan Tullybfd11dc2013-09-03 12:59:24 -04001066 widgets = {
1067 'slice' : LinkedSelect
1068 }
Scott Baker133c9212013-05-17 09:09:11 -07001069
1070class ReservationAddForm(forms.ModelForm):
1071 slice = forms.ModelChoiceField(queryset=Slice.objects.all(), widget=forms.Select(attrs={"onChange":"document.getElementById('id_refresh').value=1; submit()"}))
1072 refresh = forms.CharField(widget=forms.HiddenInput())
1073
1074 class Media:
1075 css = {'all': ('planetstack.css',)} # .field-refresh { display: none; }
1076
1077 def clean_slice(self):
1078 slice = self.cleaned_data.get("slice")
1079 x = ServiceResource.objects.filter(serviceClass = slice.serviceClass, calendarReservable=True)
1080 if len(x) == 0:
1081 raise forms.ValidationError("The slice you selected does not have a service class that allows reservations")
1082 return slice
1083
1084 class Meta:
1085 model = Reservation
Siobhan Tullybfd11dc2013-09-03 12:59:24 -04001086 widgets = {
1087 'slice' : LinkedSelect
1088 }
1089
Scott Baker133c9212013-05-17 09:09:11 -07001090
1091class ReservationAddRefreshForm(ReservationAddForm):
1092 """ This form is displayed when the Reservation Form receives an update
1093 from the Slice dropdown onChange handler. It doesn't validate the
1094 data and doesn't save the data. This will cause the form to be
1095 redrawn.
1096 """
1097
Scott Baker8737e5f2013-05-17 09:35:32 -07001098 """ don't validate anything other than slice """
1099 dont_validate_fields = ("startTime", "duration")
1100
Scott Baker133c9212013-05-17 09:09:11 -07001101 def full_clean(self):
1102 result = super(ReservationAddForm, self).full_clean()
Scott Baker8737e5f2013-05-17 09:35:32 -07001103
1104 for fieldname in self.dont_validate_fields:
1105 if fieldname in self._errors:
1106 del self._errors[fieldname]
1107
Scott Baker133c9212013-05-17 09:09:11 -07001108 return result
1109
1110 """ don't save anything """
1111 def is_valid(self):
1112 return False
1113
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001114class ReservationAdmin(PlanetStackBaseAdmin):
1115 fieldList = ['slice', 'startTime', 'duration']
1116 fieldsets = [('Reservation Details', {'fields': fieldList, 'classes': ['suit-tab suit-tab-general']})]
Scott Baker133c9212013-05-17 09:09:11 -07001117 list_display = ('startTime', 'duration')
Scott Baker133c9212013-05-17 09:09:11 -07001118 form = ReservationAddForm
1119
Siobhan Tullybfd11dc2013-09-03 12:59:24 -04001120 suit_form_tabs = (('general','Reservation Details'), ('reservedresources','Reserved Resources'))
1121
1122 inlines = [ReservedResourceInline]
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001123 user_readonly_inlines = [ReservedResourceROInline]
1124 user_readonly_fields = fieldList
Siobhan Tullybfd11dc2013-09-03 12:59:24 -04001125
Scott Baker133c9212013-05-17 09:09:11 -07001126 def add_view(self, request, form_url='', extra_context=None):
Scott Bakeracd45142013-05-19 16:19:16 -07001127 timezone.activate(request.user.timezone)
Scott Baker133c9212013-05-17 09:09:11 -07001128 request._refresh = False
1129 request._slice = None
1130 if request.method == 'POST':
Scott Baker8737e5f2013-05-17 09:35:32 -07001131 # "refresh" will be set to "1" if the form was submitted due to
1132 # a change in the Slice dropdown.
Scott Baker133c9212013-05-17 09:09:11 -07001133 if request.POST.get("refresh","1") == "1":
1134 request._refresh = True
1135 request.POST["refresh"] = "0"
Scott Baker8737e5f2013-05-17 09:35:32 -07001136
1137 # Keep track of the slice that was selected, so the
1138 # reservedResource inline can filter items for the slice.
Scott Baker133c9212013-05-17 09:09:11 -07001139 request._slice = request.POST.get("slice",None)
1140 if (request._slice is not None):
1141 request._slice = Slice.objects.get(id=request._slice)
1142
1143 result = super(ReservationAdmin, self).add_view(request, form_url, extra_context)
1144 return result
1145
Scott Bakeracd45142013-05-19 16:19:16 -07001146 def changelist_view(self, request, extra_context = None):
1147 timezone.activate(request.user.timezone)
1148 return super(ReservationAdmin, self).changelist_view(request, extra_context)
1149
Scott Baker133c9212013-05-17 09:09:11 -07001150 def get_form(self, request, obj=None, **kwargs):
Siobhan Tullyd3515752013-06-21 16:34:53 -04001151 request._obj_ = obj
1152 if obj is not None:
1153 # For changes, set request._slice to the slice already set in the
1154 # object.
1155 request._slice = obj.slice
1156 self.form = ReservationChangeForm
1157 else:
1158 if getattr(request, "_refresh", False):
1159 self.form = ReservationAddRefreshForm
1160 else:
1161 self.form = ReservationAddForm
1162 return super(ReservationAdmin, self).get_form(request, obj, **kwargs)
1163
Scott Baker133c9212013-05-17 09:09:11 -07001164 def get_readonly_fields(self, request, obj=None):
Siobhan Tullyd3515752013-06-21 16:34:53 -04001165 if (obj is not None):
1166 # Prevent slice from being changed after the reservation has been
1167 # created.
1168 return ['slice']
1169 else:
Scott Baker133c9212013-05-17 09:09:11 -07001170 return []
Scott Baker3de3e372013-05-10 16:50:44 -07001171
Tony Mack5b061472014-02-04 07:57:10 -05001172 def queryset(self, request):
1173 return Reservation.select_by_user(request.user)
1174
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001175class NetworkParameterTypeAdmin(PlanetStackBaseAdmin):
Scott Baker74d8e622013-07-29 16:04:22 -07001176 list_display = ("name", )
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001177 user_readonly_fields = ['name']
1178 user_readonly_inlines = []
Scott Baker74d8e622013-07-29 16:04:22 -07001179
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001180class RouterAdmin(PlanetStackBaseAdmin):
Scott Baker74d8e622013-07-29 16:04:22 -07001181 list_display = ("name", )
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001182 user_readonly_fields = ['name']
1183 user_readonly_inlines = []
1184
1185class RouterROInline(ReadOnlyTabularInline):
1186 model = Router.networks.through
1187 extra = 0
1188 verbose_name_plural = "Routers"
1189 verbose_name = "Router"
1190 suit_classes = 'suit-tab suit-tab-routers'
1191
1192 fields = ['name', 'owner', 'permittedNetworks', 'networks']
Scott Baker74d8e622013-07-29 16:04:22 -07001193
Scott Baker0165fac2014-01-13 11:49:26 -08001194class RouterInline(PlStackTabularInline):
Scott Baker74d8e622013-07-29 16:04:22 -07001195 model = Router.networks.through
1196 extra = 0
1197 verbose_name_plural = "Routers"
1198 verbose_name = "Router"
Siobhan Tully2d95e482013-09-06 10:56:06 -04001199 suit_classes = 'suit-tab suit-tab-routers'
Scott Baker74d8e622013-07-29 16:04:22 -07001200
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001201class NetworkParameterROInline(ReadOnlyTabularInline):
1202 model = NetworkParameter
1203 extra = 1
1204 verbose_name_plural = "Parameters"
1205 verbose_name = "Parameter"
1206 suit_classes = 'suit-tab suit-tab-netparams'
1207 fields = ['parameter', 'value', 'content_type', 'object_id', 'content_object']
1208
Scott Baker74d8e622013-07-29 16:04:22 -07001209class NetworkParameterInline(generic.GenericTabularInline):
Scott Baker74d8e622013-07-29 16:04:22 -07001210 model = NetworkParameter
1211 extra = 1
1212 verbose_name_plural = "Parameters"
1213 verbose_name = "Parameter"
Siobhan Tully2d95e482013-09-06 10:56:06 -04001214 suit_classes = 'suit-tab suit-tab-netparams'
Scott Baker74d8e622013-07-29 16:04:22 -07001215
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001216class NetworkSliversROInline(ReadOnlyTabularInline):
1217 fields = ['network', 'sliver', 'ip', 'port_id']
1218 model = NetworkSliver
1219 extra = 0
1220 verbose_name_plural = "Slivers"
1221 verbose_name = "Sliver"
1222 suit_classes = 'suit-tab suit-tab-networkslivers'
1223
Scott Baker0165fac2014-01-13 11:49:26 -08001224class NetworkSliversInline(PlStackTabularInline):
Scott Baker74d8e622013-07-29 16:04:22 -07001225 readonly_fields = ("ip", )
1226 model = NetworkSliver
Scott Baker874936e2014-01-13 18:15:34 -08001227 selflink_fieldname = "sliver"
Scott Baker74d8e622013-07-29 16:04:22 -07001228 extra = 0
1229 verbose_name_plural = "Slivers"
1230 verbose_name = "Sliver"
Siobhan Tully2d95e482013-09-06 10:56:06 -04001231 suit_classes = 'suit-tab suit-tab-networkslivers'
Scott Baker74d8e622013-07-29 16:04:22 -07001232
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001233class NetworkSlicesROInline(ReadOnlyTabularInline):
1234 model = NetworkSlice
1235 extra = 0
1236 verbose_name_plural = "Slices"
1237 verbose_name = "Slice"
1238 suit_classes = 'suit-tab suit-tab-networkslices'
1239 fields = ['network','slice']
1240
Scott Baker0165fac2014-01-13 11:49:26 -08001241class NetworkSlicesInline(PlStackTabularInline):
Scott Bakerd7d2a392013-08-06 08:57:30 -07001242 model = NetworkSlice
Scott Baker874936e2014-01-13 18:15:34 -08001243 selflink_fieldname = "slice"
Scott Bakerd7d2a392013-08-06 08:57:30 -07001244 extra = 0
1245 verbose_name_plural = "Slices"
1246 verbose_name = "Slice"
Siobhan Tully2d95e482013-09-06 10:56:06 -04001247 suit_classes = 'suit-tab suit-tab-networkslices'
Scott Bakerd7d2a392013-08-06 08:57:30 -07001248
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001249class NetworkAdmin(PlanetStackBaseAdmin):
Scott Baker74d8e622013-07-29 16:04:22 -07001250 list_display = ("name", "subnet", "ports", "labels")
1251 readonly_fields = ("subnet", )
Siobhan Tully2d95e482013-09-06 10:56:06 -04001252
Scott Bakerd7d2a392013-08-06 08:57:30 -07001253 inlines = [NetworkParameterInline, NetworkSliversInline, NetworkSlicesInline, RouterInline]
Scott Baker74d8e622013-07-29 16:04:22 -07001254
Siobhan Tully2d95e482013-09-06 10:56:06 -04001255 fieldsets = [
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001256 (None, {'fields': ['name','template','ports','labels','owner','guaranteedBandwidth', 'permitAllSlices','permittedSlices','network_id','router_id','subnet_id','subnet'], 'classes':['suit-tab suit-tab-general']}),]
1257
1258 user_readonly_fields = ['name','template','ports','labels','owner','guaranteedBandwidth', 'permitAllSlices','permittedSlices','network_id','router_id','subnet_id','subnet']
1259 user_readonly_inlines = [NetworkParameterROInline, NetworkSliversROInline, NetworkSlicesROInline, RouterROInline]
Siobhan Tully2d95e482013-09-06 10:56:06 -04001260
1261 suit_form_tabs =(
1262 ('general','Network Details'),
1263 ('netparams', 'Parameters'),
1264 ('networkslivers','Slivers'),
1265 ('networkslices','Slices'),
1266 ('routers','Routers'),
1267 )
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001268class NetworkTemplateAdmin(PlanetStackBaseAdmin):
Scott Baker74d8e622013-07-29 16:04:22 -07001269 list_display = ("name", "guaranteedBandwidth", "visibility")
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001270 user_readonly_fields = ["name", "guaranteedBandwidth", "visibility"]
1271 user_readonly_inlines = []
Scott Baker74d8e622013-07-29 16:04:22 -07001272
Tony Mack31c2b8f2013-04-26 20:01:42 -04001273# register a signal that caches the user's credentials when they log in
1274def cache_credentials(sender, user, request, **kwds):
1275 auth = {'username': request.POST['username'],
1276 'password': request.POST['password']}
1277 request.session['auth'] = auth
1278user_logged_in.connect(cache_credentials)
1279
Scott Baker15cddfa2013-12-09 13:45:19 -08001280def dollar_field(fieldName, short_description):
1281 def newFunc(self, obj):
1282 try:
1283 x= "$ %0.2f" % float(getattr(obj, fieldName, 0.0))
1284 except:
1285 x=getattr(obj, fieldName, 0.0)
1286 return x
1287 newFunc.short_description = short_description
1288 return newFunc
1289
1290def right_dollar_field(fieldName, short_description):
1291 def newFunc(self, obj):
1292 try:
1293 #x= '<div align=right style="width:6em">$ %0.2f</div>' % float(getattr(obj, fieldName, 0.0))
1294 x= '<div align=right>$ %0.2f</div>' % float(getattr(obj, fieldName, 0.0))
1295 except:
1296 x=getattr(obj, fieldName, 0.0)
1297 return x
1298 newFunc.short_description = short_description
1299 newFunc.allow_tags = True
1300 return newFunc
Scott Baker43105042013-12-06 23:23:36 -08001301
Scott Baker0165fac2014-01-13 11:49:26 -08001302class InvoiceChargeInline(PlStackTabularInline):
Scott Baker43105042013-12-06 23:23:36 -08001303 model = Charge
Scott Baker15cddfa2013-12-09 13:45:19 -08001304 extra = 0
Scott Baker43105042013-12-06 23:23:36 -08001305 verbose_name_plural = "Charges"
1306 verbose_name = "Charge"
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001307 exclude = ['account']
Scott Baker9cb88a22013-12-09 18:56:00 -08001308 fields = ["date", "kind", "state", "object", "coreHours", "dollar_amount", "slice"]
1309 readonly_fields = ["date", "kind", "state", "object", "coreHours", "dollar_amount", "slice"]
1310 can_delete = False
1311 max_num = 0
1312
1313 dollar_amount = right_dollar_field("amount", "Amount")
Scott Baker43105042013-12-06 23:23:36 -08001314
1315class InvoiceAdmin(admin.ModelAdmin):
1316 list_display = ("date", "account")
1317
1318 inlines = [InvoiceChargeInline]
1319
Scott Baker9cb88a22013-12-09 18:56:00 -08001320 fields = ["date", "account", "dollar_amount"]
1321 readonly_fields = ["date", "account", "dollar_amount"]
1322
1323 dollar_amount = dollar_field("amount", "Amount")
Scott Baker43105042013-12-06 23:23:36 -08001324
Scott Baker0165fac2014-01-13 11:49:26 -08001325class InvoiceInline(PlStackTabularInline):
Scott Baker15cddfa2013-12-09 13:45:19 -08001326 model = Invoice
1327 extra = 0
1328 verbose_name_plural = "Invoices"
1329 verbose_name = "Invoice"
Scott Baker0165fac2014-01-13 11:49:26 -08001330 fields = ["date", "dollar_amount"]
1331 readonly_fields = ["date", "dollar_amount"]
Scott Baker15cddfa2013-12-09 13:45:19 -08001332 suit_classes = 'suit-tab suit-tab-accountinvoice'
1333 can_delete=False
1334 max_num=0
1335
1336 dollar_amount = right_dollar_field("amount", "Amount")
1337
Scott Baker0165fac2014-01-13 11:49:26 -08001338class PendingChargeInline(PlStackTabularInline):
Scott Baker43105042013-12-06 23:23:36 -08001339 model = Charge
Scott Baker15cddfa2013-12-09 13:45:19 -08001340 extra = 0
Scott Baker43105042013-12-06 23:23:36 -08001341 verbose_name_plural = "Charges"
1342 verbose_name = "Charge"
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001343 exclude = ["invoice"]
Scott Baker15cddfa2013-12-09 13:45:19 -08001344 fields = ["date", "kind", "state", "object", "coreHours", "dollar_amount", "slice"]
1345 readonly_fields = ["date", "kind", "state", "object", "coreHours", "dollar_amount", "slice"]
Scott Baker43105042013-12-06 23:23:36 -08001346 suit_classes = 'suit-tab suit-tab-accountpendingcharges'
Scott Baker15cddfa2013-12-09 13:45:19 -08001347 can_delete=False
1348 max_num=0
Scott Baker43105042013-12-06 23:23:36 -08001349
1350 def queryset(self, request):
1351 qs = super(PendingChargeInline, self).queryset(request)
1352 qs = qs.filter(state="pending")
1353 return qs
1354
Scott Baker15cddfa2013-12-09 13:45:19 -08001355 dollar_amount = right_dollar_field("amount", "Amount")
1356
Scott Baker0165fac2014-01-13 11:49:26 -08001357class PaymentInline(PlStackTabularInline):
Scott Baker43105042013-12-06 23:23:36 -08001358 model=Payment
1359 extra = 1
1360 verbose_name_plural = "Payments"
1361 verbose_name = "Payment"
Scott Baker15cddfa2013-12-09 13:45:19 -08001362 fields = ["date", "dollar_amount"]
1363 readonly_fields = ["date", "dollar_amount"]
Scott Baker43105042013-12-06 23:23:36 -08001364 suit_classes = 'suit-tab suit-tab-accountpayments'
Scott Baker15cddfa2013-12-09 13:45:19 -08001365 can_delete=False
1366 max_num=0
1367
1368 dollar_amount = right_dollar_field("amount", "Amount")
1369
Scott Baker43105042013-12-06 23:23:36 -08001370class AccountAdmin(admin.ModelAdmin):
1371 list_display = ("site", "balance_due")
1372
1373 inlines = [InvoiceInline, PaymentInline, PendingChargeInline]
1374
1375 fieldsets = [
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001376 (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 -08001377
Scott Baker15cddfa2013-12-09 13:45:19 -08001378 readonly_fields = ['site', 'dollar_balance_due', 'dollar_total_invoices', 'dollar_total_payments']
Scott Baker43105042013-12-06 23:23:36 -08001379
1380 suit_form_tabs =(
1381 ('general','Account Details'),
1382 ('accountinvoice', 'Invoices'),
1383 ('accountpayments', 'Payments'),
1384 ('accountpendingcharges','Pending Charges'),
1385 )
1386
Scott Baker15cddfa2013-12-09 13:45:19 -08001387 dollar_balance_due = dollar_field("balance_due", "Balance Due")
1388 dollar_total_invoices = dollar_field("total_invoices", "Total Invoices")
1389 dollar_total_payments = dollar_field("total_payments", "Total Payments")
1390
Siobhan Tullyce652d02013-10-08 21:52:35 -04001391
Siobhan Tully53437282013-04-26 19:30:27 -04001392# Now register the new UserAdmin...
Siobhan Tully30fd4292013-05-10 08:59:56 -04001393admin.site.register(User, UserAdmin)
Siobhan Tully53437282013-04-26 19:30:27 -04001394# ... and, since we're not using Django's builtin permissions,
1395# unregister the Group model from admin.
Siobhan Tullyce652d02013-10-08 21:52:35 -04001396#admin.site.unregister(Group)
Siobhan Tully53437282013-04-26 19:30:27 -04001397
Siobhan Tullybf1153a2013-05-27 20:53:48 -04001398#Do not show django evolution in the admin interface
1399from django_evolution.models import Version, Evolution
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001400#admin.site.unregister(Version)
1401#admin.site.unregister(Evolution)
Siobhan Tullybf1153a2013-05-27 20:53:48 -04001402
1403
1404# When debugging it is often easier to see all the classes, but for regular use
1405# only the top-levels should be displayed
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001406showAll = False
Scott Baker43105042013-12-06 23:23:36 -08001407
Siobhan Tullybf1153a2013-05-27 20:53:48 -04001408admin.site.register(Deployment, DeploymentAdmin)
Siobhan Tully4bc09f22013-04-10 21:15:21 -04001409admin.site.register(Site, SiteAdmin)
Siobhan Tully4bc09f22013-04-10 21:15:21 -04001410admin.site.register(Slice, SliceAdmin)
Siobhan Tullyce652d02013-10-08 21:52:35 -04001411admin.site.register(Service, ServiceAdmin)
smbakera3cf70c2013-06-27 02:01:41 -07001412admin.site.register(Reservation, ReservationAdmin)
Scott Baker74d8e622013-07-29 16:04:22 -07001413admin.site.register(Network, NetworkAdmin)
1414admin.site.register(Router, RouterAdmin)
Scott Baker74d8e622013-07-29 16:04:22 -07001415admin.site.register(NetworkTemplate, NetworkTemplateAdmin)
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001416admin.site.register(Account, AccountAdmin)
1417admin.site.register(Invoice, InvoiceAdmin)
Siobhan Tullybf1153a2013-05-27 20:53:48 -04001418
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001419if True:
1420 admin.site.register(NetworkParameterType, NetworkParameterTypeAdmin)
1421 admin.site.register(ServiceClass, ServiceClassAdmin)
Siobhan Tullybfd11dc2013-09-03 12:59:24 -04001422 #admin.site.register(PlanetStack)
Siobhan Tullyd3515752013-06-21 16:34:53 -04001423 admin.site.register(Tag, TagAdmin)
Siobhan Tullyce652d02013-10-08 21:52:35 -04001424 admin.site.register(DeploymentRole)
1425 admin.site.register(SiteRole)
1426 admin.site.register(SliceRole)
1427 admin.site.register(PlanetStackRole)
Siobhan Tullybf1153a2013-05-27 20:53:48 -04001428 admin.site.register(Node, NodeAdmin)
Siobhan Tullybfd11dc2013-09-03 12:59:24 -04001429 #admin.site.register(SlicePrivilege, SlicePrivilegeAdmin)
1430 #admin.site.register(SitePrivilege, SitePrivilegeAdmin)
Siobhan Tullybf1153a2013-05-27 20:53:48 -04001431 admin.site.register(Sliver, SliverAdmin)
Siobhan Tullybf1153a2013-05-27 20:53:48 -04001432 admin.site.register(Image, ImageAdmin)
Scott Baker2c3cb642014-05-19 17:55:56 -07001433 admin.site.register(DashboardView, DashboardViewAdmin)
Tony Mack7130ac32013-03-22 21:58:00 -04001434