blob: ea44376af09a1627ea0a5b9af3d99b74a5fedbbd [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
Scott Bakere8859f92014-05-23 12:42:40 -070051 if hasattr(self, "user_readonly_fields"):
52 self.readonly_fields=self.user_readonly_fields
53 if hasattr(self, "user_readonly_inlines"):
54 self.inlines = self.user_readonly_inlines
Scott Bakeraf73e102014-04-22 22:40:07 -070055 else:
56 if hasattr(self, "readonly_save"):
57 # restore the original readonly fields
58 self.readonly_fields = self.readonly_save
Scott Bakere8859f92014-05-23 12:42:40 -070059 if hasattr(self, "inlines_save"):
Scott Bakeraf73e102014-04-22 22:40:07 -070060 self.inlines = self.inlines_save
Siobhan Tullycf04fb62014-01-11 11:25:57 -050061
62 try:
63 return super(ReadOnlyAwareAdmin, self).change_view(request, object_id, extra_context=extra_context)
64 except PermissionDenied:
65 pass
66 if request.method == 'POST':
67 raise PermissionDenied
68 request.readonly = True
69 return super(ReadOnlyAwareAdmin, self).change_view(request, object_id, extra_context=extra_context)
70
Siobhan Tullycf04fb62014-01-11 11:25:57 -050071 def __user_is_readonly(self, request):
72 return request.user.isReadOnlyUser()
73
Scott Bakere8859f92014-05-23 12:42:40 -070074class SingletonAdmin (ReadOnlyAwareAdmin):
Siobhan Tullyce652d02013-10-08 21:52:35 -040075 def has_add_permission(self, request):
Scott Bakere8859f92014-05-23 12:42:40 -070076 if not super(SingletonAdmin, self).has_add_permission(request):
77 return False
78
Siobhan Tullyce652d02013-10-08 21:52:35 -040079 num_objects = self.model.objects.count()
80 if num_objects >= 1:
81 return False
82 else:
83 return True
84
85
Siobhan Tullyd3515752013-06-21 16:34:53 -040086class PlStackTabularInline(admin.TabularInline):
Scott Baker86568322014-01-12 16:53:31 -080087 def __init__(self, *args, **kwargs):
88 super(PlStackTabularInline, self).__init__(*args, **kwargs)
89
90 # InlineModelAdmin as no get_fields() method, so in order to add
91 # the selflink field, we override __init__ to modify self.fields and
92 # self.readonly_fields.
93
Scott Bakere2bbf7e2014-01-13 12:09:31 -080094 self.setup_selflink()
95
Scott Baker874936e2014-01-13 18:15:34 -080096 def get_change_url(self, model, id):
97 """ Get the URL to a change form in the admin for this model """
98 reverse_path = "admin:%s_change" % (model._meta.db_table)
Scott Bakere2bbf7e2014-01-13 12:09:31 -080099 try:
Scott Baker874936e2014-01-13 18:15:34 -0800100 url = reverse(reverse_path, args=(id,))
Scott Bakere2bbf7e2014-01-13 12:09:31 -0800101 except NoReverseMatch:
Scott Baker874936e2014-01-13 18:15:34 -0800102 return None
103
104 return url
105
106 def setup_selflink(self):
107 if hasattr(self, "selflink_fieldname"):
108 """ self.selflink_model can be defined to punch through a relation
109 to its target object. For example, in SliceNetworkInline, set
110 selflink_model = "network", and the URL will lead to the Network
111 object instead of trying to bring up a change view of the
112 SliceNetwork object.
113 """
114 self.selflink_model = getattr(self.model,self.selflink_fieldname).field.rel.to
115 else:
116 self.selflink_model = self.model
117
118 url = self.get_change_url(self.selflink_model, 0)
119
120 # We don't have an admin for this object, so don't create the
121 # selflink.
122 if (url == None):
Scott Bakere2bbf7e2014-01-13 12:09:31 -0800123 return
124
Scott Baker874936e2014-01-13 18:15:34 -0800125 # Since we need to add "selflink" to the field list, we need to create
126 # self.fields if it is None.
Scott Baker0165fac2014-01-13 11:49:26 -0800127 if (self.fields is None):
128 self.fields = []
129 for f in self.model._meta.fields:
130 if f.editable and f.name != "id":
131 self.fields.append(f.name)
Scott Baker86568322014-01-12 16:53:31 -0800132
Scott Baker874936e2014-01-13 18:15:34 -0800133 self.fields = tuple(self.fields) + ("selflink", )
Scott Baker86568322014-01-12 16:53:31 -0800134
Scott Baker874936e2014-01-13 18:15:34 -0800135 if self.readonly_fields is None:
136 self.readonly_fields = ()
Scott Baker86568322014-01-12 16:53:31 -0800137
Scott Baker874936e2014-01-13 18:15:34 -0800138 self.readonly_fields = tuple(self.readonly_fields) + ("selflink", )
Scott Baker86568322014-01-12 16:53:31 -0800139
140 def selflink(self, obj):
Scott Baker874936e2014-01-13 18:15:34 -0800141 if hasattr(self, "selflink_fieldname"):
142 obj = getattr(obj, self.selflink_fieldname)
143
Scott Baker86568322014-01-12 16:53:31 -0800144 if obj.id:
Scott Baker874936e2014-01-13 18:15:34 -0800145 url = self.get_change_url(self.selflink_model, obj.id)
146 return "<a href='%s'>Details</a>" % str(url)
Scott Baker86568322014-01-12 16:53:31 -0800147 else:
Scott Bakere2bbf7e2014-01-13 12:09:31 -0800148 return "Not present"
Scott Baker86568322014-01-12 16:53:31 -0800149
150 selflink.allow_tags = True
151 selflink.short_description = "Details"
Siobhan Tullyd3515752013-06-21 16:34:53 -0400152
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500153class ReadOnlyTabularInline(PlStackTabularInline):
154 can_delete = False
155
156 def get_readonly_fields(self, request, obj=None):
157 return self.fields
158
159 def has_add_permission(self, request):
160 return False
161
162class ReservationROInline(ReadOnlyTabularInline):
163 model = Reservation
164 extra = 0
165 suit_classes = 'suit-tab suit-tab-reservations'
166 fields = ['startTime','slice','duration']
167
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400168class ReservationInline(PlStackTabularInline):
169 model = Reservation
170 extra = 0
171 suit_classes = 'suit-tab suit-tab-reservations'
Tony Mack5b061472014-02-04 07:57:10 -0500172
173 def queryset(self, request):
174 return Reservation.select_by_user(request.user)
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400175
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500176class TagROInline(generic.GenericTabularInline):
177 model = Tag
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400178 extra = 0
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500179 suit_classes = 'suit-tab suit-tab-tags'
180 can_delete = False
181 fields = ['service', 'name', 'value']
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400182
183 def get_readonly_fields(self, request, obj=None):
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500184 return self.fields
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400185
186 def has_add_permission(self, request):
187 return False
188
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500189
Siobhan Tullyde5450d2013-06-21 11:35:33 -0400190class TagInline(generic.GenericTabularInline):
191 model = Tag
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400192 extra = 0
193 suit_classes = 'suit-tab suit-tab-tags'
Tony Mack5b061472014-02-04 07:57:10 -0500194 fields = ['service', 'name', 'value']
195
196 def queryset(self, request):
197 return Tag.select_by_user(request.user)
Siobhan Tullyde5450d2013-06-21 11:35:33 -0400198
Scott Baker74d8e622013-07-29 16:04:22 -0700199class NetworkLookerUpper:
Siobhan Tully2c780ad2013-09-06 11:22:40 -0400200 """ This is a callable that looks up a network name in a sliver and returns
201 the ip address for that network.
202 """
203
204 def __init__(self, name):
205 self.short_description = name
206 self.__name__ = name
207 self.network_name = name
208
209 def __call__(self, obj):
210 if obj is not None:
211 for nbs in obj.networksliver_set.all():
212 if (nbs.network.name == self.network_name):
213 return nbs.ip
Scott Baker74d8e622013-07-29 16:04:22 -0700214 return ""
215
216 def __str__(self):
217 return self.network_name
218
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500219class SliverROInline(ReadOnlyTabularInline):
220 model = Sliver
221 fields = ['ip', 'instance_name', 'slice', 'numberCores', 'image', 'node', 'deploymentNetwork']
222 suit_classes = 'suit-tab suit-tab-slivers'
223
Siobhan Tullyd3515752013-06-21 16:34:53 -0400224class SliverInline(PlStackTabularInline):
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400225 model = Sliver
Tony Mackb0d97422013-06-10 09:57:45 -0400226 fields = ['ip', 'instance_name', 'slice', 'numberCores', 'image', 'node', 'deploymentNetwork']
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400227 extra = 0
Tony Mack3777b012013-05-07 21:38:06 -0400228 readonly_fields = ['ip', 'instance_name']
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400229 suit_classes = 'suit-tab suit-tab-slivers'
Scott Baker74d8e622013-07-29 16:04:22 -0700230
Tony Mack5b061472014-02-04 07:57:10 -0500231 def queryset(self, request):
232 return Sliver.select_by_user(request.user)
233
Siobhan Tully2d95e482013-09-06 10:56:06 -0400234# Note this is breaking in the admin.py when trying to use an inline to add a node/image
235# def _declared_fieldsets(self):
236# # Return None so django will call get_fieldsets and we can insert our
237# # dynamic fields
238# return None
239#
240# def get_readonly_fields(self, request, obj=None):
241# readonly_fields = super(SliverInline, self).get_readonly_fields(request, obj)
242#
243# # Lookup the networks that are bound to the slivers, and add those
244# # network names to the list of readonly fields.
245#
246# for sliver in obj.slivers.all():
247# for nbs in sliver.networksliver_set.all():
248# if nbs.ip:
249# network_name = nbs.network.name
250# if network_name not in [str(x) for x in readonly_fields]:
251# readonly_fields.append(NetworkLookerUpper(network_name))
252#
253# return readonly_fields
254#
255# def get_fieldsets(self, request, obj=None):
256# form = self.get_formset(request, obj).form
257# # fields = the read/write files + the read-only fields
258# fields = self.fields
259# for fieldName in self.get_readonly_fields(request,obj):
260# if not fieldName in fields:
261# fields.append(fieldName)
262#
263# return [(None, {'fields': fields})]
Scott Baker74d8e622013-07-29 16:04:22 -0700264
Tony Mackc2835a92013-05-28 09:18:49 -0400265
Siobhan Tully567e3e62013-06-21 18:03:16 -0400266
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500267class SiteROInline(ReadOnlyTabularInline):
268 model = Site
269 extra = 0
270 fields = ['name', 'login_base', 'site_url', 'enabled']
271 suit_classes = 'suit-tab suit-tab-sites'
272
Siobhan Tullyd3515752013-06-21 16:34:53 -0400273class SiteInline(PlStackTabularInline):
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400274 model = Site
275 extra = 0
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400276 suit_classes = 'suit-tab suit-tab-sites'
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400277
Tony Mack5b061472014-02-04 07:57:10 -0500278 def queryset(self, request):
279 return Site.select_by_user(request.user)
280
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500281class UserROInline(ReadOnlyTabularInline):
282 model = User
283 fields = ['email', 'firstname', 'lastname']
284 extra = 0
285 suit_classes = 'suit-tab suit-tab-users'
286
Siobhan Tullyd3515752013-06-21 16:34:53 -0400287class UserInline(PlStackTabularInline):
Siobhan Tully30fd4292013-05-10 08:59:56 -0400288 model = User
Siobhan Tully47ae1b52013-05-10 15:53:14 -0400289 fields = ['email', 'firstname', 'lastname']
Siobhan Tully30fd4292013-05-10 08:59:56 -0400290 extra = 0
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400291 suit_classes = 'suit-tab suit-tab-users'
Siobhan Tully30fd4292013-05-10 08:59:56 -0400292
Tony Mack5b061472014-02-04 07:57:10 -0500293 def queryset(self, request):
294 return User.select_by_user(request.user)
295
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500296class SliceROInline(ReadOnlyTabularInline):
297 model = Slice
298 suit_classes = 'suit-tab suit-tab-slices'
299 fields = ['name','site', 'serviceClass', 'service']
300
Siobhan Tullyd3515752013-06-21 16:34:53 -0400301class SliceInline(PlStackTabularInline):
Tony Mack00d361f2013-04-28 10:28:42 -0400302 model = Slice
Siobhan Tullyce652d02013-10-08 21:52:35 -0400303 fields = ['name','site', 'serviceClass', 'service']
Tony Mack00d361f2013-04-28 10:28:42 -0400304 extra = 0
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400305 suit_classes = 'suit-tab suit-tab-slices'
306
Tony Mack5b061472014-02-04 07:57:10 -0500307 def queryset(self, request):
308 return Slice.select_by_user(request.user)
309
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500310class NodeROInline(ReadOnlyTabularInline):
311 model = Node
312 extra = 0
313 suit_classes = 'suit-tab suit-tab-nodes'
314 fields = ['name','deployment']
Tony Mack00d361f2013-04-28 10:28:42 -0400315
Siobhan Tullyd3515752013-06-21 16:34:53 -0400316class NodeInline(PlStackTabularInline):
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400317 model = Node
318 extra = 0
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400319 suit_classes = 'suit-tab suit-tab-nodes'
Tony Mack5b061472014-02-04 07:57:10 -0500320 fields = ['name','deployment']
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400321
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500322class DeploymentPrivilegeROInline(ReadOnlyTabularInline):
323 model = DeploymentPrivilege
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400324 extra = 0
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500325 suit_classes = 'suit-tab suit-tab-deploymentprivileges'
Scott Baker3ca51f62014-05-23 12:05:11 -0700326 fields = ['user','role','deployment']
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400327
328class DeploymentPrivilegeInline(PlStackTabularInline):
329 model = DeploymentPrivilege
330 extra = 0
331 suit_classes = 'suit-tab suit-tab-deploymentprivileges'
Scott Baker3ca51f62014-05-23 12:05:11 -0700332 fields = ['user','role','deployment']
Tony Mack5b061472014-02-04 07:57:10 -0500333
334 def queryset(self, request):
335 return DeploymentPrivilege.select_by_user(request.user)
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400336
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500337#CLEANUP DOUBLE SitePrivilegeInline
338class SitePrivilegeROInline(ReadOnlyTabularInline):
339 model = SitePrivilege
340 extra = 0
341 suit_classes = 'suit-tab suit-tab-siteprivileges'
342 fields = ['user','site', 'role']
343
Siobhan Tullyd3515752013-06-21 16:34:53 -0400344class SitePrivilegeInline(PlStackTabularInline):
Siobhan Tullyaa1bcd52013-05-10 12:43:09 -0400345 model = SitePrivilege
346 extra = 0
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400347 suit_classes = 'suit-tab suit-tab-siteprivileges'
Tony Mack5b061472014-02-04 07:57:10 -0500348 fields = ['user','site', 'role']
Siobhan Tullyaa1bcd52013-05-10 12:43:09 -0400349
Tony Mackc2835a92013-05-28 09:18:49 -0400350 def formfield_for_foreignkey(self, db_field, request, **kwargs):
351 if db_field.name == 'site':
Tony Mack5b061472014-02-04 07:57:10 -0500352 kwargs['queryset'] = Site.select_by_user(request.user)
Tony Mackc2835a92013-05-28 09:18:49 -0400353
354 if db_field.name == 'user':
Tony Mack5b061472014-02-04 07:57:10 -0500355 kwargs['queryset'] = User.select_by_user(request.user)
Tony Mackc2835a92013-05-28 09:18:49 -0400356 return super(SitePrivilegeInline, self).formfield_for_foreignkey(db_field, request, **kwargs)
357
Tony Mack5b061472014-02-04 07:57:10 -0500358 def queryset(self, request):
359 return SitePrivilege.select_by_user(request.user)
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400360
Tony Macke4be32f2014-03-11 20:45:25 -0400361class SiteDeploymentROInline(ReadOnlyTabularInline):
362 model = SiteDeployments
363 #model = Site.deployments.through
364 extra = 0
Scott Bakerf3982522014-05-23 11:58:20 -0700365 suit_classes = 'suit-tab suit-tab-deployments'
Tony Macke4be32f2014-03-11 20:45:25 -0400366 fields = ['deployment','site']
367
368class SiteDeploymentInline(PlStackTabularInline):
369 model = SiteDeployments
370 #model = Site.deployments.through
371 extra = 0
372 suit_classes = 'suit-tab suit-tab-deployments'
373 fields = ['deployment','site']
374
375 def formfield_for_foreignkey(self, db_field, request, **kwargs):
376 if db_field.name == 'site':
377 kwargs['queryset'] = Site.select_by_user(request.user)
378
379 if db_field.name == 'deployment':
380 kwargs['queryset'] = Deployment.select_by_user(request.user)
381 return super(SiteDeploymentInline, self).formfield_for_foreignkey(db_field, request, **kwargs)
382
383 def queryset(self, request):
384 return SiteDeployments.select_by_user(request.user)
385
386
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500387class SlicePrivilegeROInline(ReadOnlyTabularInline):
388 model = SlicePrivilege
389 extra = 0
390 suit_classes = 'suit-tab suit-tab-sliceprivileges'
391 fields = ['user', 'slice', 'role']
392
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400393class SlicePrivilegeInline(PlStackTabularInline):
394 model = SlicePrivilege
395 suit_classes = 'suit-tab suit-tab-sliceprivileges'
396 extra = 0
397 fields = ('user', 'slice','role')
Siobhan Tullyaa1bcd52013-05-10 12:43:09 -0400398
Tony Mackc2835a92013-05-28 09:18:49 -0400399 def formfield_for_foreignkey(self, db_field, request, **kwargs):
400 if db_field.name == 'slice':
Tony Mack5b061472014-02-04 07:57:10 -0500401 kwargs['queryset'] = Slice.select_by_user(request.user)
Tony Mackc2835a92013-05-28 09:18:49 -0400402 if db_field.name == 'user':
Tony Mack5b061472014-02-04 07:57:10 -0500403 kwargs['queryset'] = User.select_by_user(request.user)
Tony Mackc2835a92013-05-28 09:18:49 -0400404
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400405 return super(SlicePrivilegeInline, self).formfield_for_foreignkey(db_field, request, **kwargs)
Tony Mackc2835a92013-05-28 09:18:49 -0400406
Tony Mack5b061472014-02-04 07:57:10 -0500407 def queryset(self, request):
408 return SlicePrivilege.select_by_user(request.user)
409
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500410class SliceNetworkROInline(ReadOnlyTabularInline):
411 model = Network.slices.through
412 extra = 0
413 verbose_name = "Network Connection"
414 verbose_name_plural = "Network Connections"
415 suit_classes = 'suit-tab suit-tab-slicenetworks'
416 fields = ['network']
417
Scott Bakera0015eb2013-08-14 17:28:14 -0700418class SliceNetworkInline(PlStackTabularInline):
Scott Baker74d8e622013-07-29 16:04:22 -0700419 model = Network.slices.through
Scott Baker874936e2014-01-13 18:15:34 -0800420 selflink_fieldname = "network"
Scott Baker74d8e622013-07-29 16:04:22 -0700421 extra = 0
422 verbose_name = "Network Connection"
423 verbose_name_plural = "Network Connections"
Siobhan Tully2d95e482013-09-06 10:56:06 -0400424 suit_classes = 'suit-tab suit-tab-slicenetworks'
Scott Baker2170b972014-06-03 12:14:07 -0700425 fields = ['network']
426
427class ImageDeploymentsInline(PlStackTabularInline):
428 model = ImageDeployments
429 extra = 0
430 verbose_name = "Image Deployments"
431 verbose_name_plural = "Image Deployments"
432 suit_classes = 'suit-tab suit-tab-imagedeployments'
433 fields = ['deployment', 'glance_image_id']
434 readonly_fields = ['deployment', 'glance_image_id']
Scott Baker74d8e622013-07-29 16:04:22 -0700435
Tony Mack5e71a662013-05-03 23:30:41 -0400436class PlainTextWidget(forms.HiddenInput):
437 input_type = 'hidden'
438
439 def render(self, name, value, attrs=None):
440 if value is None:
441 value = ''
Tony Mack1d6b85f2013-05-07 18:49:14 -0400442 return mark_safe(str(value) + super(PlainTextWidget, self).render(name, value, attrs))
Tony Mack9bcbe4f2013-04-29 08:13:27 -0400443
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500444class PlanetStackBaseAdmin(ReadOnlyAwareAdmin):
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400445 save_on_top = False
Tony Mack332ee1d2014-02-04 15:33:45 -0500446
447 def save_model(self, request, obj, form, change):
Tony Mack3d042792014-03-17 19:18:37 -0400448 obj.caller = request.user
Tony Mack332ee1d2014-02-04 15:33:45 -0500449 # update openstack connection to use this site/tenant
450 obj.save_by_user(request.user)
451
452 def delete_model(self, request, obj):
453 obj.delete_by_user(request.user)
454
455 def save_formset(self, request, form, formset, change):
456 instances = formset.save(commit=False)
457 for instance in instances:
458 instance.save_by_user(request.user)
459 formset.save_m2m()
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400460
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400461class SliceRoleAdmin(PlanetStackBaseAdmin):
462 model = SliceRole
463 pass
464
465class SiteRoleAdmin(PlanetStackBaseAdmin):
466 model = SiteRole
467 pass
468
Siobhan Tullybf1153a2013-05-27 20:53:48 -0400469class DeploymentAdminForm(forms.ModelForm):
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400470 sites = forms.ModelMultipleChoiceField(
471 queryset=Site.objects.all(),
472 required=False,
473 widget=FilteredSelectMultiple(
474 verbose_name=('Sites'), is_stacked=False
475 )
476 )
477 class Meta:
Siobhan Tullybf1153a2013-05-27 20:53:48 -0400478 model = Deployment
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400479
Siobhan Tully320b4622014-01-17 15:11:14 -0500480 def __init__(self, *args, **kwargs):
481 super(DeploymentAdminForm, self).__init__(*args, **kwargs)
482
483 if self.instance and self.instance.pk:
Scott Bakerc9b14f72014-05-22 13:44:20 -0700484 self.fields['sites'].initial = [x.site for x in self.instance.sitedeployments_set.all()]
Siobhan Tully320b4622014-01-17 15:11:14 -0500485
486 def save(self, commit=True):
487 deployment = super(DeploymentAdminForm, self).save(commit=False)
488
489 if commit:
490 deployment.save()
491
492 if deployment.pk:
Scott Bakerc9b14f72014-05-22 13:44:20 -0700493 # save_m2m() doesn't seem to work with 'through' relations. So we
494 # create/destroy the through models ourselves. There has to be
495 # a better way...
496
497 sites = self.cleaned_data['sites']
498
499 existing_sites = []
500 for sdp in list(deployment.sitedeployments_set.all()):
501 if sdp.site not in sites:
502 #print "deleting site", sdp.site
503 sdp.delete()
504 else:
505 existing_sites.append(sdp.site)
506
507 for site in sites:
508 if site not in existing_sites:
509 #print "adding site", site
510 sdp = SiteDeployments(site=site, deployment=deployment)
511 sdp.save()
512
Siobhan Tully320b4622014-01-17 15:11:14 -0500513 self.save_m2m()
514
515 return deployment
516
Scott Bakerff5e0f32014-05-22 14:40:27 -0700517class DeploymentAdminROForm(DeploymentAdminForm):
518 def save(self, commit=True):
519 raise PermissionDenied
520
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500521class SiteAssocInline(PlStackTabularInline):
522 model = Site.deployments.through
523 extra = 0
524 suit_classes = 'suit-tab suit-tab-sites'
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400525
Siobhan Tullybf1153a2013-05-27 20:53:48 -0400526class DeploymentAdmin(PlanetStackBaseAdmin):
Scott Bakerff5e0f32014-05-22 14:40:27 -0700527 #form = DeploymentAdminForm
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500528 model = Deployment
529 fieldList = ['name','sites']
530 fieldsets = [(None, {'fields': fieldList, 'classes':['suit-tab suit-tab-sites']})]
Siobhan Tully2d95e482013-09-06 10:56:06 -0400531 inlines = [DeploymentPrivilegeInline,NodeInline,TagInline]
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500532
533 user_readonly_inlines = [DeploymentPrivilegeROInline,NodeROInline,TagROInline]
534 user_readonly_fields = ['name']
535
536 suit_form_tabs =(('sites','Deployment Details'),('nodes','Nodes'),('deploymentprivileges','Privileges'),('tags','Tags'))
537
Scott Bakerff5e0f32014-05-22 14:40:27 -0700538 def get_form(self, request, obj=None, **kwargs):
539 if request.user.isReadOnlyUser():
540 kwargs["form"] = DeploymentAdminROForm
541 else:
542 kwargs["form"] = DeploymentAdminForm
543 return super(DeploymentAdmin,self).get_form(request, obj, **kwargs)
544
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500545class ServiceAttrAsTabROInline(ReadOnlyTabularInline):
546 model = ServiceAttribute
547 fields = ['name','value']
548 extra = 0
549 suit_classes = 'suit-tab suit-tab-serviceattrs'
Tony Mack5cd13202013-05-01 21:48:38 -0400550
Siobhan Tullyce652d02013-10-08 21:52:35 -0400551class ServiceAttrAsTabInline(PlStackTabularInline):
552 model = ServiceAttribute
553 fields = ['name','value']
554 extra = 0
555 suit_classes = 'suit-tab suit-tab-serviceattrs'
556
Siobhan Tullyce652d02013-10-08 21:52:35 -0400557class ServiceAdmin(PlanetStackBaseAdmin):
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500558 list_display = ("name","description","versionNumber","enabled","published")
559 fieldList = ["name","description","versionNumber","enabled","published"]
560 fieldsets = [(None, {'fields': fieldList, 'classes':['suit-tab suit-tab-general']})]
561 inlines = [ServiceAttrAsTabInline,SliceInline]
562
563 user_readonly_fields = fieldList
564 user_readonly_inlines = [ServiceAttrAsTabROInline,SliceROInline]
565
566 suit_form_tabs =(('general', 'Service Details'),
567 ('slices','Slices'),
568 ('serviceattrs','Additional Attributes'),
569 )
Siobhan Tullyce652d02013-10-08 21:52:35 -0400570
Tony Mack0553f282013-06-10 22:54:50 -0400571class SiteAdmin(PlanetStackBaseAdmin):
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500572 fieldList = ['name', 'site_url', 'enabled', 'is_public', 'login_base', 'accountLink','location']
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400573 fieldsets = [
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500574 (None, {'fields': fieldList, 'classes':['suit-tab suit-tab-general']}),
Tony Macke4be32f2014-03-11 20:45:25 -0400575 #('Deployment Networks', {'fields': ['deployments'], 'classes':['suit-tab suit-tab-deployments']}),
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400576 ]
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400577 suit_form_tabs =(('general', 'Site Details'),
578 ('users','Users'),
Siobhan Tully2d95e482013-09-06 10:56:06 -0400579 ('siteprivileges','Privileges'),
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400580 ('deployments','Deployments'),
581 ('slices','Slices'),
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500582 ('nodes','Nodes'),
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400583 ('tags','Tags'),
584 )
Scott Baker545db2a2013-12-09 18:44:43 -0800585 readonly_fields = ['accountLink']
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500586
587 user_readonly_fields = ['name', 'deployments','site_url', 'enabled', 'is_public', 'login_base', 'accountLink']
Tony Macke4be32f2014-03-11 20:45:25 -0400588 user_readonly_inlines = [SliceROInline,UserROInline,TagROInline, NodeROInline, SitePrivilegeROInline,SiteDeploymentROInline]
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500589
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400590 list_display = ('name', 'login_base','site_url', 'enabled')
591 filter_horizontal = ('deployments',)
Tony Macke4be32f2014-03-11 20:45:25 -0400592 inlines = [SliceInline,UserInline,TagInline, NodeInline, SitePrivilegeInline, SiteDeploymentInline]
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400593 search_fields = ['name']
594
Tony Mack04062832013-05-10 08:22:44 -0400595 def queryset(self, request):
Tony Mack5b061472014-02-04 07:57:10 -0500596 return Site.select_by_user(request.user)
Tony Mack04062832013-05-10 08:22:44 -0400597
Tony Mack5cd13202013-05-01 21:48:38 -0400598 def get_formsets(self, request, obj=None):
599 for inline in self.get_inline_instances(request, obj):
600 # hide MyInline in the add view
601 if obj is None:
602 continue
Tony Mack2bd5b412013-06-11 21:05:06 -0400603 if isinstance(inline, SliceInline):
604 inline.model.caller = request.user
605 yield inline.get_formset(request, obj)
606
607 def get_formsets(self, request, obj=None):
608 for inline in self.get_inline_instances(request, obj):
609 # hide MyInline in the add view
610 if obj is None:
611 continue
612 if isinstance(inline, SliverInline):
613 inline.model.caller = request.user
Tony Mack5cd13202013-05-01 21:48:38 -0400614 yield inline.get_formset(request, obj)
615
Scott Baker545db2a2013-12-09 18:44:43 -0800616 def accountLink(self, obj):
617 link_obj = obj.accounts.all()
618 if link_obj:
619 reverse_path = "admin:core_account_change"
620 url = reverse(reverse_path, args =(link_obj[0].id,))
621 return "<a href='%s'>%s</a>" % (url, "view billing details")
622 else:
623 return "no billing data for this site"
624 accountLink.allow_tags = True
625 accountLink.short_description = "Billing"
626
Tony Mack332ee1d2014-02-04 15:33:45 -0500627 def save_model(self, request, obj, form, change):
628 # update openstack connection to use this site/tenant
629 obj.save_by_user(request.user)
630
631 def delete_model(self, request, obj):
632 obj.delete_by_user(request.user)
633
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500634
Tony Mack9bcbe4f2013-04-29 08:13:27 -0400635class SitePrivilegeAdmin(PlanetStackBaseAdmin):
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500636 fieldList = ['user', 'site', 'role']
Tony Mack00d361f2013-04-28 10:28:42 -0400637 fieldsets = [
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500638 (None, {'fields': fieldList, 'classes':['collapse']})
Tony Mack00d361f2013-04-28 10:28:42 -0400639 ]
640 list_display = ('user', 'site', 'role')
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500641 user_readonly_fields = fieldList
642 user_readonly_inlines = []
Tony Mack00d361f2013-04-28 10:28:42 -0400643
Tony Mackc2835a92013-05-28 09:18:49 -0400644 def formfield_for_foreignkey(self, db_field, request, **kwargs):
645 if db_field.name == 'site':
646 if not request.user.is_admin:
647 # only show sites where user is an admin or pi
648 sites = set()
649 for site_privilege in SitePrivilege.objects.filer(user=request.user):
650 if site_privilege.role.role_type in ['admin', 'pi']:
651 sites.add(site_privilege.site)
652 kwargs['queryset'] = Site.objects.filter(site__in=list(sites))
653
654 if db_field.name == 'user':
655 if not request.user.is_admin:
656 # only show users from sites where caller has admin or pi role
657 roles = Role.objects.filter(role_type__in=['admin', 'pi'])
658 site_privileges = SitePrivilege.objects.filter(user=request.user).filter(role__in=roles)
659 sites = [site_privilege.site for site_privilege in site_privileges]
660 site_privileges = SitePrivilege.objects.filter(site__in=sites)
661 emails = [site_privilege.user.email for site_privilege in site_privileges]
662 users = User.objects.filter(email__in=emails)
663 kwargs['queryset'] = users
664
665 return super(SitePrivilegeAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)
666
Tony Mack04062832013-05-10 08:22:44 -0400667 def queryset(self, request):
668 # admins can see all privileges. Users can only see privileges at sites
Tony Mackc2835a92013-05-28 09:18:49 -0400669 # where they have the admin role or pi role.
Tony Mack04062832013-05-10 08:22:44 -0400670 qs = super(SitePrivilegeAdmin, self).queryset(request)
Tony Mack5b061472014-02-04 07:57:10 -0500671 #if not request.user.is_admin:
672 # roles = Role.objects.filter(role_type__in=['admin', 'pi'])
673 # site_privileges = SitePrivilege.objects.filter(user=request.user).filter(role__in=roles)
674 # login_bases = [site_privilege.site.login_base for site_privilege in site_privileges]
675 # sites = Site.objects.filter(login_base__in=login_bases)
676 # qs = qs.filter(site__in=sites)
Tony Mack04062832013-05-10 08:22:44 -0400677 return qs
678
Siobhan Tullyce652d02013-10-08 21:52:35 -0400679class SliceForm(forms.ModelForm):
680 class Meta:
681 model = Slice
682 widgets = {
683 'service': LinkedSelect
684 }
685
Tony Mack2bd5b412013-06-11 21:05:06 -0400686class SliceAdmin(PlanetStackBaseAdmin):
Siobhan Tullyce652d02013-10-08 21:52:35 -0400687 form = SliceForm
Tony Mack29bf5e82014-04-29 21:40:24 -0400688 fieldList = ['name', 'site', 'serviceClass', 'enabled','description', 'service', 'slice_url', 'max_slivers']
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500689 fieldsets = [('Slice Details', {'fields': fieldList, 'classes':['suit-tab suit-tab-general']}),]
Tony Mack29bf5e82014-04-29 21:40:24 -0400690 list_display = ('name', 'site','serviceClass', 'slice_url', 'max_slivers')
Siobhan Tully2d95e482013-09-06 10:56:06 -0400691 inlines = [SlicePrivilegeInline,SliverInline, TagInline, ReservationInline,SliceNetworkInline]
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400692
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500693 user_readonly_fields = fieldList
694 user_readonly_inlines = [SlicePrivilegeROInline,SliverROInline,TagROInline, ReservationROInline, SliceNetworkROInline]
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400695
696 suit_form_tabs =(('general', 'Slice Details'),
Siobhan Tully2d95e482013-09-06 10:56:06 -0400697 ('slicenetworks','Networks'),
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400698 ('sliceprivileges','Privileges'),
699 ('slivers','Slivers'),
700 ('tags','Tags'),
701 ('reservations','Reservations'),
702 )
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400703
Tony Mackc2835a92013-05-28 09:18:49 -0400704 def formfield_for_foreignkey(self, db_field, request, **kwargs):
705 if db_field.name == 'site':
Tony Mack5b061472014-02-04 07:57:10 -0500706 kwargs['queryset'] = Site.select_by_user(request.user)
707
Tony Mackc2835a92013-05-28 09:18:49 -0400708 return super(SliceAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)
709
Tony Mack04062832013-05-10 08:22:44 -0400710 def queryset(self, request):
711 # admins can see all keys. Users can only see slices they belong to.
Tony Mack5b061472014-02-04 07:57:10 -0500712 return Slice.select_by_user(request.user)
Tony Mack04062832013-05-10 08:22:44 -0400713
Tony Mack79748612013-05-01 14:52:03 -0400714 def get_formsets(self, request, obj=None):
715 for inline in self.get_inline_instances(request, obj):
716 # hide MyInline in the add view
717 if obj is None:
718 continue
Tony Mack2bd5b412013-06-11 21:05:06 -0400719 if isinstance(inline, SliverInline):
720 inline.model.caller = request.user
Tony Mack79748612013-05-01 14:52:03 -0400721 yield inline.get_formset(request, obj)
722
Tony Mack2bd5b412013-06-11 21:05:06 -0400723
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400724class SlicePrivilegeAdmin(PlanetStackBaseAdmin):
Tony Mack00d361f2013-04-28 10:28:42 -0400725 fieldsets = [
726 (None, {'fields': ['user', 'slice', 'role']})
727 ]
728 list_display = ('user', 'slice', 'role')
Tony Mack00d361f2013-04-28 10:28:42 -0400729
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500730 user_readonly_fields = ['user', 'slice', 'role']
731 user_readonly_inlines = []
732
Tony Mackc2835a92013-05-28 09:18:49 -0400733 def formfield_for_foreignkey(self, db_field, request, **kwargs):
734 if db_field.name == 'slice':
Tony Mack5b061472014-02-04 07:57:10 -0500735 kwargs['queryset'] = Slice.select_by_user(request.user)
Tony Mackc2835a92013-05-28 09:18:49 -0400736
737 if db_field.name == 'user':
Tony Mack5b061472014-02-04 07:57:10 -0500738 kwargs['queryset'] = User.select_by_user(request.user)
Tony Mackc2835a92013-05-28 09:18:49 -0400739
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400740 return super(SlicePrivilegeAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)
Tony Mackc2835a92013-05-28 09:18:49 -0400741
Tony Mack04062832013-05-10 08:22:44 -0400742 def queryset(self, request):
743 # admins can see all memberships. Users can only see memberships of
744 # slices where they have the admin role.
Tony Mack5b061472014-02-04 07:57:10 -0500745 return SlicePrivilege.select_by_user(request.user)
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400746
Tony Mack9bcbe4f2013-04-29 08:13:27 -0400747 def save_model(self, request, obj, form, change):
Tony Mack951dab42013-05-02 19:51:45 -0400748 # update openstack connection to use this site/tenant
749 auth = request.session.get('auth', {})
750 auth['tenant'] = obj.slice.name
751 obj.os_manager = OpenStackManager(auth=auth, caller=request.user)
Tony Mack9bcbe4f2013-04-29 08:13:27 -0400752 obj.save()
753
754 def delete_model(self, request, obj):
Tony Mack951dab42013-05-02 19:51:45 -0400755 # update openstack connection to use this site/tenant
756 auth = request.session.get('auth', {})
757 auth['tenant'] = obj.slice.name
758 obj.os_manager = OpenStackManager(auth=auth, caller=request.user)
Tony Mack9bcbe4f2013-04-29 08:13:27 -0400759 obj.delete()
760
Siobhan Tully567e3e62013-06-21 18:03:16 -0400761
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400762class ImageAdmin(PlanetStackBaseAdmin):
763
764 fieldsets = [('Image Details',
Scott Baker00b00b32014-05-07 08:47:54 -0700765 {'fields': ['name', 'disk_format', 'container_format'],
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400766 'classes': ['suit-tab suit-tab-general']})
767 ]
768
Scott Baker2170b972014-06-03 12:14:07 -0700769 suit_form_tabs =(('general','Image Details'),('slivers','Slivers'),('imagedeployments','Deployments'))
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400770
Scott Baker2170b972014-06-03 12:14:07 -0700771 inlines = [SliverInline, ImageDeploymentsInline]
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500772
Tony Mack32e1ce32014-05-07 13:29:41 -0400773 user_readonly_fields = ['name', 'disk_format', 'container_format']
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500774 user_readonly_inlines = [SliverROInline]
775
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400776class NodeForm(forms.ModelForm):
777 class Meta:
778 widgets = {
779 'site': LinkedSelect,
780 'deployment': LinkedSelect
781 }
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400782
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500783class NodeAdmin(PlanetStackBaseAdmin):
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400784 form = NodeForm
Siobhan Tullybf1153a2013-05-27 20:53:48 -0400785 list_display = ('name', 'site', 'deployment')
786 list_filter = ('deployment',)
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500787
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400788 inlines = [TagInline,SliverInline]
789 fieldsets = [('Node Details', {'fields': ['name','site','deployment'], 'classes':['suit-tab suit-tab-details']})]
790
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500791 user_readonly_fields = ['name','site','deployment']
792 user_readonly_inlines = [TagInline,SliverInline]
793
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400794 suit_form_tabs =(('details','Node Details'),('slivers','Slivers'),('tags','Tags'))
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400795
Siobhan Tully567e3e62013-06-21 18:03:16 -0400796
Tony Mackd90cdbf2013-04-16 22:48:40 -0400797class SliverForm(forms.ModelForm):
798 class Meta:
Tony Mack1d6b85f2013-05-07 18:49:14 -0400799 model = Sliver
Tony Mackd90cdbf2013-04-16 22:48:40 -0400800 ip = forms.CharField(widget=PlainTextWidget)
Tony Mack18261812013-05-02 16:39:20 -0400801 instance_name = forms.CharField(widget=PlainTextWidget)
Tony Mackd90cdbf2013-04-16 22:48:40 -0400802 widgets = {
803 'ip': PlainTextWidget(),
Tony Mack18261812013-05-02 16:39:20 -0400804 'instance_name': PlainTextWidget(),
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400805 'slice': LinkedSelect,
806 'deploymentNetwork': LinkedSelect,
807 'node': LinkedSelect,
808 'image': LinkedSelect
Siobhan Tully53437282013-04-26 19:30:27 -0400809 }
Tony Mackd90cdbf2013-04-16 22:48:40 -0400810
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500811class TagAdmin(PlanetStackBaseAdmin):
Siobhan Tullyce652d02013-10-08 21:52:35 -0400812 list_display = ['service', 'name', 'value', 'content_type', 'content_object',]
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500813 user_readonly_fields = ['service', 'name', 'value', 'content_type', 'content_object',]
814 user_readonly_inlines = []
Siobhan Tullyd3515752013-06-21 16:34:53 -0400815
Tony Mack9bcbe4f2013-04-29 08:13:27 -0400816class SliverAdmin(PlanetStackBaseAdmin):
Tony Mackd90cdbf2013-04-16 22:48:40 -0400817 form = SliverForm
Tony Mackcdec0902013-04-15 00:38:49 -0400818 fieldsets = [
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400819 ('Sliver Details', {'fields': ['slice', 'deploymentNetwork', 'node', 'ip', 'instance_name', 'numberCores', 'image', ], 'classes': ['suit-tab suit-tab-general'], })
Tony Mackcdec0902013-04-15 00:38:49 -0400820 ]
Siobhan Tully5d7dc8d2013-07-02 13:17:33 -0400821 list_display = ['ip', 'instance_name', 'slice', 'numberCores', 'image', 'node', 'deploymentNetwork']
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400822
823 suit_form_tabs =(('general', 'Sliver Details'),
824 ('tags','Tags'),
825 )
826
Siobhan Tullyde5450d2013-06-21 11:35:33 -0400827 inlines = [TagInline]
Tony Mack53106f32013-04-27 16:43:01 -0400828
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500829 user_readonly_fields = ['slice', 'deploymentNetwork', 'node', 'ip', 'instance_name', 'numberCores', 'image']
830 user_readonly_inlines = [TagROInline]
831
Tony Mackc2835a92013-05-28 09:18:49 -0400832 def formfield_for_foreignkey(self, db_field, request, **kwargs):
833 if db_field.name == 'slice':
Tony Mack5b061472014-02-04 07:57:10 -0500834 kwargs['queryset'] = Slice.select_by_user(request.user)
Tony Mackc2835a92013-05-28 09:18:49 -0400835
836 return super(SliverAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)
837
Tony Mack04062832013-05-10 08:22:44 -0400838 def queryset(self, request):
839 # admins can see all slivers. Users can only see slivers of
840 # the slices they belong to.
Tony Mack5b061472014-02-04 07:57:10 -0500841 return Sliver.select_by_user(request.user)
842
Tony Mack04062832013-05-10 08:22:44 -0400843
Tony Mack1d6b85f2013-05-07 18:49:14 -0400844 def get_formsets(self, request, obj=None):
845 # make some fields read only if we are updating an existing record
846 if obj == None:
847 #self.readonly_fields = ('ip', 'instance_name')
848 self.readonly_fields = ()
849 else:
Tony Mack1e889462013-05-10 21:34:54 -0400850 self.readonly_fields = ()
851 #self.readonly_fields = ('ip', 'instance_name', 'slice', 'image', 'key')
Tony Mack1d6b85f2013-05-07 18:49:14 -0400852
853 for inline in self.get_inline_instances(request, obj):
854 # hide MyInline in the add view
855 if obj is None:
856 continue
Scott Baker526b71e2014-05-13 13:18:01 -0700857 if isinstance(inline, SliverInline):
858 inline.model.caller = request.user
859 yield inline.get_formset(request, obj)
Tony Mack53106f32013-04-27 16:43:01 -0400860
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500861 #def save_model(self, request, obj, form, change):
862 # # update openstack connection to use this site/tenant
863 # auth = request.session.get('auth', {})
864 # auth['tenant'] = obj.slice.name
865 # obj.os_manager = OpenStackManager(auth=auth, caller=request.user)
866 # obj.creator = request.user
867 # obj.save()
Tony Mack53106f32013-04-27 16:43:01 -0400868
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500869 #def delete_model(self, request, obj):
870 # # update openstack connection to use this site/tenant
871 # auth = request.session.get('auth', {})
872 # auth['tenant'] = obj.slice.name
873 # obj.os_manager = OpenStackManager(auth=auth, caller=request.user)
874 # obj.delete()
Tony Mackcdec0902013-04-15 00:38:49 -0400875
Siobhan Tully53437282013-04-26 19:30:27 -0400876class UserCreationForm(forms.ModelForm):
877 """A form for creating new users. Includes all the required
878 fields, plus a repeated password."""
879 password1 = forms.CharField(label='Password', widget=forms.PasswordInput)
880 password2 = forms.CharField(label='Password confirmation', widget=forms.PasswordInput)
881
882 class Meta:
Siobhan Tully30fd4292013-05-10 08:59:56 -0400883 model = User
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400884 fields = ('email', 'firstname', 'lastname', 'phone', 'public_key')
Siobhan Tully53437282013-04-26 19:30:27 -0400885
886 def clean_password2(self):
887 # Check that the two password entries match
888 password1 = self.cleaned_data.get("password1")
889 password2 = self.cleaned_data.get("password2")
890 if password1 and password2 and password1 != password2:
891 raise forms.ValidationError("Passwords don't match")
892 return password2
893
894 def save(self, commit=True):
895 # Save the provided password in hashed format
896 user = super(UserCreationForm, self).save(commit=False)
Tony Mackf9f4afb2013-05-01 21:02:12 -0400897 user.password = self.cleaned_data["password1"]
898 #user.set_password(self.cleaned_data["password1"])
Siobhan Tully53437282013-04-26 19:30:27 -0400899 if commit:
900 user.save()
901 return user
902
Siobhan Tully567e3e62013-06-21 18:03:16 -0400903
Siobhan Tully53437282013-04-26 19:30:27 -0400904class UserChangeForm(forms.ModelForm):
905 """A form for updating users. Includes all the fields on
906 the user, but replaces the password field with admin's
907 password hash display field.
908 """
Siobhan Tully63b7ba42014-01-12 10:35:11 -0500909 password = ReadOnlyPasswordHashField(label='Password',
910 help_text= '<a href=\"password/\">Change Password</a>.')
Siobhan Tully53437282013-04-26 19:30:27 -0400911
912 class Meta:
Siobhan Tully30fd4292013-05-10 08:59:56 -0400913 model = User
Siobhan Tully53437282013-04-26 19:30:27 -0400914
915 def clean_password(self):
916 # Regardless of what the user provides, return the initial value.
917 # This is done here, rather than on the field, because the
918 # field does not have access to the initial value
919 return self.initial["password"]
920
Scott Baker2c3cb642014-05-19 17:55:56 -0700921class UserDashboardViewInline(PlStackTabularInline):
922 model = UserDashboardView
923 extra = 0
924 suit_classes = 'suit-tab suit-tab-dashboards'
925 fields = ['user', 'dashboardView', 'order']
926
Scott Bakered31f672014-05-21 18:14:03 -0700927class UserDashboardViewROInline(ReadOnlyTabularInline):
928 model = UserDashboardView
929 extra = 0
930 suit_classes = 'suit-tab suit-tab-dashboards'
931 fields = ['user', 'dashboardView', 'order']
932
Tony Mack2bd5b412013-06-11 21:05:06 -0400933class UserAdmin(UserAdmin):
Siobhan Tully53437282013-04-26 19:30:27 -0400934 class Meta:
935 app_label = "core"
936
937 # The forms to add and change user instances
938 form = UserChangeForm
939 add_form = UserCreationForm
940
941 # The fields to be used in displaying the User model.
942 # These override the definitions on the base UserAdmin
943 # that reference specific fields on auth.User.
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500944 list_display = ('email', 'firstname', 'lastname', 'site', 'last_login')
Siobhan Tullyce652d02013-10-08 21:52:35 -0400945 #list_display = ('email', 'username','firstname', 'lastname', 'is_admin', 'last_login')
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500946 list_filter = ('site',)
Scott Baker2c3cb642014-05-19 17:55:56 -0700947 inlines = [SlicePrivilegeInline,SitePrivilegeInline,DeploymentPrivilegeInline,UserDashboardViewInline]
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500948
949 fieldListLoginDetails = ['email','site','password','is_readonly','is_amin','public_key']
950 fieldListContactInfo = ['firstname','lastname','phone','timezone']
951
Siobhan Tully53437282013-04-26 19:30:27 -0400952 fieldsets = (
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500953 ('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 -0400954 ('Contact Information', {'fields': ('firstname','lastname','phone', 'timezone'), 'classes':['suit-tab suit-tab-contact']}),
Scott Baker2c3cb642014-05-19 17:55:56 -0700955 #('Dashboard Views', {'fields': ('dashboards',), 'classes':['suit-tab suit-tab-dashboards']}),
Siobhan Tully53437282013-04-26 19:30:27 -0400956 #('Important dates', {'fields': ('last_login',)}),
957 )
958 add_fieldsets = (
959 (None, {
960 'classes': ('wide',),
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500961 'fields': ('email', 'firstname', 'lastname', 'is_readonly', 'phone', 'public_key','password1', 'password2')}
Siobhan Tully53437282013-04-26 19:30:27 -0400962 ),
963 )
964 search_fields = ('email',)
965 ordering = ('email',)
966 filter_horizontal = ()
967
Scott Baker3ca51f62014-05-23 12:05:11 -0700968 user_readonly_fields = fieldListLoginDetails + fieldListContactInfo
Scott Bakered31f672014-05-21 18:14:03 -0700969 user_readonly_inlines = [SlicePrivilegeROInline,SitePrivilegeROInline,DeploymentPrivilegeROInline,UserDashboardViewROInline]
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500970
Scott Baker2c3cb642014-05-19 17:55:56 -0700971 suit_form_tabs =(('general','Login Details'),
972 ('contact','Contact Information'),
973 ('sliceprivileges','Slice Privileges'),
974 ('siteprivileges','Site Privileges'),
975 ('deploymentprivileges','Deployment Privileges'),
976 ('dashboards','Dashboard Views'))
Siobhan Tullybfd11dc2013-09-03 12:59:24 -0400977
Tony Mackc2835a92013-05-28 09:18:49 -0400978 def formfield_for_foreignkey(self, db_field, request, **kwargs):
979 if db_field.name == 'site':
Tony Mack5b061472014-02-04 07:57:10 -0500980 kwargs['queryset'] = Site.select_by_user(request.user)
Tony Mackc2835a92013-05-28 09:18:49 -0400981
982 return super(UserAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)
983
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500984 def has_add_permission(self, request, obj=None):
985 return (not self.__user_is_readonly(request))
986
987 def has_delete_permission(self, request, obj=None):
988 return (not self.__user_is_readonly(request))
989
990 def get_actions(self,request):
991 actions = super(UserAdmin,self).get_actions(request)
992
993 if self.__user_is_readonly(request):
994 if 'delete_selected' in actions:
995 del actions['delete_selected']
996
997 return actions
998
999 def change_view(self,request,object_id, extra_context=None):
1000
1001 if self.__user_is_readonly(request):
Scott Bakerf875eba2014-05-23 12:09:15 -07001002 if not hasattr(self, "readonly_save"):
1003 # save the original readonly fields
1004 self.readonly_save = self.readonly_fields
1005 self.inlines_save = self.inlines
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001006 self.readonly_fields=self.user_readonly_fields
1007 self.inlines = self.user_readonly_inlines
Scott Bakerf875eba2014-05-23 12:09:15 -07001008 else:
1009 if hasattr(self, "readonly_save"):
1010 # restore the original readonly fields
1011 self.readonly_fields = self.readonly_save
1012 self.inlines = self.inlines_save
1013
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001014 try:
1015 return super(UserAdmin, self).change_view(request, object_id, extra_context=extra_context)
1016 except PermissionDenied:
1017 pass
1018 if request.method == 'POST':
1019 raise PermissionDenied
1020 request.readonly = True
1021 return super(UserAdmin, self).change_view(request, object_id, extra_context=extra_context)
1022
1023 def __user_is_readonly(self, request):
1024 #groups = [x.name for x in request.user.groups.all() ]
1025 #return "readonly" in groups
1026 return request.user.isReadOnlyUser()
1027
Tony Mack5b061472014-02-04 07:57:10 -05001028 def queryset(self, request):
1029 return User.select_by_user(request.user)
1030
Scott Baker2c3cb642014-05-19 17:55:56 -07001031class DashboardViewAdmin(PlanetStackBaseAdmin):
1032 fieldsets = [('Dashboard View Details',
1033 {'fields': ['name', 'url'],
1034 'classes': ['suit-tab suit-tab-general']})
1035 ]
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001036
Scott Baker2c3cb642014-05-19 17:55:56 -07001037 suit_form_tabs =(('general','Dashboard View Details'),)
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001038
1039class ServiceResourceROInline(ReadOnlyTabularInline):
1040 model = ServiceResource
1041 extra = 0
1042 fields = ['serviceClass', 'name', 'maxUnitsDeployment', 'maxUnitsNode', 'maxDuration', 'bucketInRate', 'bucketMaxSize', 'cost', 'calendarReservable']
1043
Scott Baker0165fac2014-01-13 11:49:26 -08001044class ServiceResourceInline(PlStackTabularInline):
Scott Baker3de3e372013-05-10 16:50:44 -07001045 model = ServiceResource
1046 extra = 0
1047
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001048class ServiceClassAdmin(PlanetStackBaseAdmin):
Scott Baker3de3e372013-05-10 16:50:44 -07001049 list_display = ('name', 'commitment', 'membershipFee')
1050 inlines = [ServiceResourceInline]
1051
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001052 user_readonly_fields = ['name', 'commitment', 'membershipFee']
1053 user_readonly_inlines = []
1054
1055class ReservedResourceROInline(ReadOnlyTabularInline):
1056 model = ReservedResource
1057 extra = 0
1058 fields = ['sliver', 'resource','quantity','reservationSet']
1059 suit_classes = 'suit-tab suit-tab-reservedresources'
1060
Scott Baker0165fac2014-01-13 11:49:26 -08001061class ReservedResourceInline(PlStackTabularInline):
Scott Baker133c9212013-05-17 09:09:11 -07001062 model = ReservedResource
1063 extra = 0
Siobhan Tullybfd11dc2013-09-03 12:59:24 -04001064 suit_classes = 'suit-tab suit-tab-reservedresources'
Scott Baker133c9212013-05-17 09:09:11 -07001065
1066 def formfield_for_foreignkey(self, db_field, request=None, **kwargs):
1067 field = super(ReservedResourceInline, self).formfield_for_foreignkey(db_field, request, **kwargs)
1068
1069 if db_field.name == 'resource':
1070 # restrict resources to those that the slice's service class allows
1071 if request._slice is not None:
1072 field.queryset = field.queryset.filter(serviceClass = request._slice.serviceClass, calendarReservable=True)
1073 if len(field.queryset) > 0:
1074 field.initial = field.queryset.all()[0]
1075 else:
1076 field.queryset = field.queryset.none()
1077 elif db_field.name == 'sliver':
1078 # restrict slivers to those that belong to the slice
1079 if request._slice is not None:
1080 field.queryset = field.queryset.filter(slice = request._slice)
1081 else:
1082 field.queryset = field.queryset.none()
1083
1084 return field
1085
Tony Mack5b061472014-02-04 07:57:10 -05001086 def queryset(self, request):
1087 return ReservedResource.select_by_user(request.user)
1088
Scott Baker133c9212013-05-17 09:09:11 -07001089class ReservationChangeForm(forms.ModelForm):
1090 class Meta:
1091 model = Reservation
Siobhan Tullybfd11dc2013-09-03 12:59:24 -04001092 widgets = {
1093 'slice' : LinkedSelect
1094 }
Scott Baker133c9212013-05-17 09:09:11 -07001095
1096class ReservationAddForm(forms.ModelForm):
1097 slice = forms.ModelChoiceField(queryset=Slice.objects.all(), widget=forms.Select(attrs={"onChange":"document.getElementById('id_refresh').value=1; submit()"}))
1098 refresh = forms.CharField(widget=forms.HiddenInput())
1099
1100 class Media:
1101 css = {'all': ('planetstack.css',)} # .field-refresh { display: none; }
1102
1103 def clean_slice(self):
1104 slice = self.cleaned_data.get("slice")
1105 x = ServiceResource.objects.filter(serviceClass = slice.serviceClass, calendarReservable=True)
1106 if len(x) == 0:
1107 raise forms.ValidationError("The slice you selected does not have a service class that allows reservations")
1108 return slice
1109
1110 class Meta:
1111 model = Reservation
Siobhan Tullybfd11dc2013-09-03 12:59:24 -04001112 widgets = {
1113 'slice' : LinkedSelect
1114 }
1115
Scott Baker133c9212013-05-17 09:09:11 -07001116
1117class ReservationAddRefreshForm(ReservationAddForm):
1118 """ This form is displayed when the Reservation Form receives an update
1119 from the Slice dropdown onChange handler. It doesn't validate the
1120 data and doesn't save the data. This will cause the form to be
1121 redrawn.
1122 """
1123
Scott Baker8737e5f2013-05-17 09:35:32 -07001124 """ don't validate anything other than slice """
1125 dont_validate_fields = ("startTime", "duration")
1126
Scott Baker133c9212013-05-17 09:09:11 -07001127 def full_clean(self):
1128 result = super(ReservationAddForm, self).full_clean()
Scott Baker8737e5f2013-05-17 09:35:32 -07001129
1130 for fieldname in self.dont_validate_fields:
1131 if fieldname in self._errors:
1132 del self._errors[fieldname]
1133
Scott Baker133c9212013-05-17 09:09:11 -07001134 return result
1135
1136 """ don't save anything """
1137 def is_valid(self):
1138 return False
1139
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001140class ReservationAdmin(PlanetStackBaseAdmin):
1141 fieldList = ['slice', 'startTime', 'duration']
1142 fieldsets = [('Reservation Details', {'fields': fieldList, 'classes': ['suit-tab suit-tab-general']})]
Scott Baker133c9212013-05-17 09:09:11 -07001143 list_display = ('startTime', 'duration')
Scott Baker133c9212013-05-17 09:09:11 -07001144 form = ReservationAddForm
1145
Siobhan Tullybfd11dc2013-09-03 12:59:24 -04001146 suit_form_tabs = (('general','Reservation Details'), ('reservedresources','Reserved Resources'))
1147
1148 inlines = [ReservedResourceInline]
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001149 user_readonly_inlines = [ReservedResourceROInline]
1150 user_readonly_fields = fieldList
Siobhan Tullybfd11dc2013-09-03 12:59:24 -04001151
Scott Baker133c9212013-05-17 09:09:11 -07001152 def add_view(self, request, form_url='', extra_context=None):
Scott Bakeracd45142013-05-19 16:19:16 -07001153 timezone.activate(request.user.timezone)
Scott Baker133c9212013-05-17 09:09:11 -07001154 request._refresh = False
1155 request._slice = None
1156 if request.method == 'POST':
Scott Baker8737e5f2013-05-17 09:35:32 -07001157 # "refresh" will be set to "1" if the form was submitted due to
1158 # a change in the Slice dropdown.
Scott Baker133c9212013-05-17 09:09:11 -07001159 if request.POST.get("refresh","1") == "1":
1160 request._refresh = True
1161 request.POST["refresh"] = "0"
Scott Baker8737e5f2013-05-17 09:35:32 -07001162
1163 # Keep track of the slice that was selected, so the
1164 # reservedResource inline can filter items for the slice.
Scott Baker133c9212013-05-17 09:09:11 -07001165 request._slice = request.POST.get("slice",None)
1166 if (request._slice is not None):
1167 request._slice = Slice.objects.get(id=request._slice)
1168
1169 result = super(ReservationAdmin, self).add_view(request, form_url, extra_context)
1170 return result
1171
Scott Bakeracd45142013-05-19 16:19:16 -07001172 def changelist_view(self, request, extra_context = None):
1173 timezone.activate(request.user.timezone)
1174 return super(ReservationAdmin, self).changelist_view(request, extra_context)
1175
Scott Baker133c9212013-05-17 09:09:11 -07001176 def get_form(self, request, obj=None, **kwargs):
Siobhan Tullyd3515752013-06-21 16:34:53 -04001177 request._obj_ = obj
1178 if obj is not None:
1179 # For changes, set request._slice to the slice already set in the
1180 # object.
1181 request._slice = obj.slice
1182 self.form = ReservationChangeForm
1183 else:
1184 if getattr(request, "_refresh", False):
1185 self.form = ReservationAddRefreshForm
1186 else:
1187 self.form = ReservationAddForm
1188 return super(ReservationAdmin, self).get_form(request, obj, **kwargs)
1189
Scott Baker133c9212013-05-17 09:09:11 -07001190 def get_readonly_fields(self, request, obj=None):
Siobhan Tullyd3515752013-06-21 16:34:53 -04001191 if (obj is not None):
1192 # Prevent slice from being changed after the reservation has been
1193 # created.
1194 return ['slice']
1195 else:
Scott Baker133c9212013-05-17 09:09:11 -07001196 return []
Scott Baker3de3e372013-05-10 16:50:44 -07001197
Tony Mack5b061472014-02-04 07:57:10 -05001198 def queryset(self, request):
1199 return Reservation.select_by_user(request.user)
1200
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001201class NetworkParameterTypeAdmin(PlanetStackBaseAdmin):
Scott Baker74d8e622013-07-29 16:04:22 -07001202 list_display = ("name", )
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001203 user_readonly_fields = ['name']
1204 user_readonly_inlines = []
Scott Baker74d8e622013-07-29 16:04:22 -07001205
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001206class RouterAdmin(PlanetStackBaseAdmin):
Scott Baker74d8e622013-07-29 16:04:22 -07001207 list_display = ("name", )
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001208 user_readonly_fields = ['name']
1209 user_readonly_inlines = []
1210
1211class RouterROInline(ReadOnlyTabularInline):
1212 model = Router.networks.through
1213 extra = 0
1214 verbose_name_plural = "Routers"
1215 verbose_name = "Router"
1216 suit_classes = 'suit-tab suit-tab-routers'
1217
1218 fields = ['name', 'owner', 'permittedNetworks', 'networks']
Scott Baker74d8e622013-07-29 16:04:22 -07001219
Scott Baker0165fac2014-01-13 11:49:26 -08001220class RouterInline(PlStackTabularInline):
Scott Baker74d8e622013-07-29 16:04:22 -07001221 model = Router.networks.through
1222 extra = 0
1223 verbose_name_plural = "Routers"
1224 verbose_name = "Router"
Siobhan Tully2d95e482013-09-06 10:56:06 -04001225 suit_classes = 'suit-tab suit-tab-routers'
Scott Baker74d8e622013-07-29 16:04:22 -07001226
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001227class NetworkParameterROInline(ReadOnlyTabularInline):
1228 model = NetworkParameter
1229 extra = 1
1230 verbose_name_plural = "Parameters"
1231 verbose_name = "Parameter"
1232 suit_classes = 'suit-tab suit-tab-netparams'
1233 fields = ['parameter', 'value', 'content_type', 'object_id', 'content_object']
1234
Scott Baker74d8e622013-07-29 16:04:22 -07001235class NetworkParameterInline(generic.GenericTabularInline):
Scott Baker74d8e622013-07-29 16:04:22 -07001236 model = NetworkParameter
1237 extra = 1
1238 verbose_name_plural = "Parameters"
1239 verbose_name = "Parameter"
Siobhan Tully2d95e482013-09-06 10:56:06 -04001240 suit_classes = 'suit-tab suit-tab-netparams'
Scott Baker74d8e622013-07-29 16:04:22 -07001241
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001242class NetworkSliversROInline(ReadOnlyTabularInline):
1243 fields = ['network', 'sliver', 'ip', 'port_id']
1244 model = NetworkSliver
1245 extra = 0
1246 verbose_name_plural = "Slivers"
1247 verbose_name = "Sliver"
1248 suit_classes = 'suit-tab suit-tab-networkslivers'
1249
Scott Baker0165fac2014-01-13 11:49:26 -08001250class NetworkSliversInline(PlStackTabularInline):
Scott Baker74d8e622013-07-29 16:04:22 -07001251 readonly_fields = ("ip", )
1252 model = NetworkSliver
Scott Baker874936e2014-01-13 18:15:34 -08001253 selflink_fieldname = "sliver"
Scott Baker74d8e622013-07-29 16:04:22 -07001254 extra = 0
1255 verbose_name_plural = "Slivers"
1256 verbose_name = "Sliver"
Siobhan Tully2d95e482013-09-06 10:56:06 -04001257 suit_classes = 'suit-tab suit-tab-networkslivers'
Scott Baker74d8e622013-07-29 16:04:22 -07001258
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001259class NetworkSlicesROInline(ReadOnlyTabularInline):
1260 model = NetworkSlice
1261 extra = 0
1262 verbose_name_plural = "Slices"
1263 verbose_name = "Slice"
1264 suit_classes = 'suit-tab suit-tab-networkslices'
1265 fields = ['network','slice']
1266
Scott Baker0165fac2014-01-13 11:49:26 -08001267class NetworkSlicesInline(PlStackTabularInline):
Scott Bakerd7d2a392013-08-06 08:57:30 -07001268 model = NetworkSlice
Scott Baker874936e2014-01-13 18:15:34 -08001269 selflink_fieldname = "slice"
Scott Bakerd7d2a392013-08-06 08:57:30 -07001270 extra = 0
1271 verbose_name_plural = "Slices"
1272 verbose_name = "Slice"
Siobhan Tully2d95e482013-09-06 10:56:06 -04001273 suit_classes = 'suit-tab suit-tab-networkslices'
Scott Bakerd7d2a392013-08-06 08:57:30 -07001274
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001275class NetworkAdmin(PlanetStackBaseAdmin):
Scott Baker74d8e622013-07-29 16:04:22 -07001276 list_display = ("name", "subnet", "ports", "labels")
1277 readonly_fields = ("subnet", )
Siobhan Tully2d95e482013-09-06 10:56:06 -04001278
Scott Bakerd7d2a392013-08-06 08:57:30 -07001279 inlines = [NetworkParameterInline, NetworkSliversInline, NetworkSlicesInline, RouterInline]
Scott Baker74d8e622013-07-29 16:04:22 -07001280
Siobhan Tully2d95e482013-09-06 10:56:06 -04001281 fieldsets = [
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001282 (None, {'fields': ['name','template','ports','labels','owner','guaranteedBandwidth', 'permitAllSlices','permittedSlices','network_id','router_id','subnet_id','subnet'], 'classes':['suit-tab suit-tab-general']}),]
1283
1284 user_readonly_fields = ['name','template','ports','labels','owner','guaranteedBandwidth', 'permitAllSlices','permittedSlices','network_id','router_id','subnet_id','subnet']
1285 user_readonly_inlines = [NetworkParameterROInline, NetworkSliversROInline, NetworkSlicesROInline, RouterROInline]
Siobhan Tully2d95e482013-09-06 10:56:06 -04001286
1287 suit_form_tabs =(
1288 ('general','Network Details'),
1289 ('netparams', 'Parameters'),
1290 ('networkslivers','Slivers'),
1291 ('networkslices','Slices'),
1292 ('routers','Routers'),
1293 )
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001294class NetworkTemplateAdmin(PlanetStackBaseAdmin):
Scott Baker74d8e622013-07-29 16:04:22 -07001295 list_display = ("name", "guaranteedBandwidth", "visibility")
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001296 user_readonly_fields = ["name", "guaranteedBandwidth", "visibility"]
1297 user_readonly_inlines = []
Scott Baker74d8e622013-07-29 16:04:22 -07001298
Tony Mack31c2b8f2013-04-26 20:01:42 -04001299# register a signal that caches the user's credentials when they log in
1300def cache_credentials(sender, user, request, **kwds):
1301 auth = {'username': request.POST['username'],
1302 'password': request.POST['password']}
1303 request.session['auth'] = auth
1304user_logged_in.connect(cache_credentials)
1305
Scott Baker15cddfa2013-12-09 13:45:19 -08001306def dollar_field(fieldName, short_description):
1307 def newFunc(self, obj):
1308 try:
1309 x= "$ %0.2f" % float(getattr(obj, fieldName, 0.0))
1310 except:
1311 x=getattr(obj, fieldName, 0.0)
1312 return x
1313 newFunc.short_description = short_description
1314 return newFunc
1315
1316def right_dollar_field(fieldName, short_description):
1317 def newFunc(self, obj):
1318 try:
1319 #x= '<div align=right style="width:6em">$ %0.2f</div>' % float(getattr(obj, fieldName, 0.0))
1320 x= '<div align=right>$ %0.2f</div>' % float(getattr(obj, fieldName, 0.0))
1321 except:
1322 x=getattr(obj, fieldName, 0.0)
1323 return x
1324 newFunc.short_description = short_description
1325 newFunc.allow_tags = True
1326 return newFunc
Scott Baker43105042013-12-06 23:23:36 -08001327
Scott Baker0165fac2014-01-13 11:49:26 -08001328class InvoiceChargeInline(PlStackTabularInline):
Scott Baker43105042013-12-06 23:23:36 -08001329 model = Charge
Scott Baker15cddfa2013-12-09 13:45:19 -08001330 extra = 0
Scott Baker43105042013-12-06 23:23:36 -08001331 verbose_name_plural = "Charges"
1332 verbose_name = "Charge"
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001333 exclude = ['account']
Scott Baker9cb88a22013-12-09 18:56:00 -08001334 fields = ["date", "kind", "state", "object", "coreHours", "dollar_amount", "slice"]
1335 readonly_fields = ["date", "kind", "state", "object", "coreHours", "dollar_amount", "slice"]
1336 can_delete = False
1337 max_num = 0
1338
1339 dollar_amount = right_dollar_field("amount", "Amount")
Scott Baker43105042013-12-06 23:23:36 -08001340
1341class InvoiceAdmin(admin.ModelAdmin):
1342 list_display = ("date", "account")
1343
1344 inlines = [InvoiceChargeInline]
1345
Scott Baker9cb88a22013-12-09 18:56:00 -08001346 fields = ["date", "account", "dollar_amount"]
1347 readonly_fields = ["date", "account", "dollar_amount"]
1348
1349 dollar_amount = dollar_field("amount", "Amount")
Scott Baker43105042013-12-06 23:23:36 -08001350
Scott Baker0165fac2014-01-13 11:49:26 -08001351class InvoiceInline(PlStackTabularInline):
Scott Baker15cddfa2013-12-09 13:45:19 -08001352 model = Invoice
1353 extra = 0
1354 verbose_name_plural = "Invoices"
1355 verbose_name = "Invoice"
Scott Baker0165fac2014-01-13 11:49:26 -08001356 fields = ["date", "dollar_amount"]
1357 readonly_fields = ["date", "dollar_amount"]
Scott Baker15cddfa2013-12-09 13:45:19 -08001358 suit_classes = 'suit-tab suit-tab-accountinvoice'
1359 can_delete=False
1360 max_num=0
1361
1362 dollar_amount = right_dollar_field("amount", "Amount")
1363
Scott Baker0165fac2014-01-13 11:49:26 -08001364class PendingChargeInline(PlStackTabularInline):
Scott Baker43105042013-12-06 23:23:36 -08001365 model = Charge
Scott Baker15cddfa2013-12-09 13:45:19 -08001366 extra = 0
Scott Baker43105042013-12-06 23:23:36 -08001367 verbose_name_plural = "Charges"
1368 verbose_name = "Charge"
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001369 exclude = ["invoice"]
Scott Baker15cddfa2013-12-09 13:45:19 -08001370 fields = ["date", "kind", "state", "object", "coreHours", "dollar_amount", "slice"]
1371 readonly_fields = ["date", "kind", "state", "object", "coreHours", "dollar_amount", "slice"]
Scott Baker43105042013-12-06 23:23:36 -08001372 suit_classes = 'suit-tab suit-tab-accountpendingcharges'
Scott Baker15cddfa2013-12-09 13:45:19 -08001373 can_delete=False
1374 max_num=0
Scott Baker43105042013-12-06 23:23:36 -08001375
1376 def queryset(self, request):
1377 qs = super(PendingChargeInline, self).queryset(request)
1378 qs = qs.filter(state="pending")
1379 return qs
1380
Scott Baker15cddfa2013-12-09 13:45:19 -08001381 dollar_amount = right_dollar_field("amount", "Amount")
1382
Scott Baker0165fac2014-01-13 11:49:26 -08001383class PaymentInline(PlStackTabularInline):
Scott Baker43105042013-12-06 23:23:36 -08001384 model=Payment
1385 extra = 1
1386 verbose_name_plural = "Payments"
1387 verbose_name = "Payment"
Scott Baker15cddfa2013-12-09 13:45:19 -08001388 fields = ["date", "dollar_amount"]
1389 readonly_fields = ["date", "dollar_amount"]
Scott Baker43105042013-12-06 23:23:36 -08001390 suit_classes = 'suit-tab suit-tab-accountpayments'
Scott Baker15cddfa2013-12-09 13:45:19 -08001391 can_delete=False
1392 max_num=0
1393
1394 dollar_amount = right_dollar_field("amount", "Amount")
1395
Scott Baker43105042013-12-06 23:23:36 -08001396class AccountAdmin(admin.ModelAdmin):
1397 list_display = ("site", "balance_due")
1398
1399 inlines = [InvoiceInline, PaymentInline, PendingChargeInline]
1400
1401 fieldsets = [
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001402 (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 -08001403
Scott Baker15cddfa2013-12-09 13:45:19 -08001404 readonly_fields = ['site', 'dollar_balance_due', 'dollar_total_invoices', 'dollar_total_payments']
Scott Baker43105042013-12-06 23:23:36 -08001405
1406 suit_form_tabs =(
1407 ('general','Account Details'),
1408 ('accountinvoice', 'Invoices'),
1409 ('accountpayments', 'Payments'),
1410 ('accountpendingcharges','Pending Charges'),
1411 )
1412
Scott Baker15cddfa2013-12-09 13:45:19 -08001413 dollar_balance_due = dollar_field("balance_due", "Balance Due")
1414 dollar_total_invoices = dollar_field("total_invoices", "Total Invoices")
1415 dollar_total_payments = dollar_field("total_payments", "Total Payments")
1416
Siobhan Tullyce652d02013-10-08 21:52:35 -04001417
Siobhan Tully53437282013-04-26 19:30:27 -04001418# Now register the new UserAdmin...
Siobhan Tully30fd4292013-05-10 08:59:56 -04001419admin.site.register(User, UserAdmin)
Siobhan Tully53437282013-04-26 19:30:27 -04001420# ... and, since we're not using Django's builtin permissions,
1421# unregister the Group model from admin.
Siobhan Tullyce652d02013-10-08 21:52:35 -04001422#admin.site.unregister(Group)
Siobhan Tully53437282013-04-26 19:30:27 -04001423
Siobhan Tullybf1153a2013-05-27 20:53:48 -04001424#Do not show django evolution in the admin interface
1425from django_evolution.models import Version, Evolution
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001426#admin.site.unregister(Version)
1427#admin.site.unregister(Evolution)
Siobhan Tullybf1153a2013-05-27 20:53:48 -04001428
1429
1430# When debugging it is often easier to see all the classes, but for regular use
1431# only the top-levels should be displayed
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001432showAll = False
Scott Baker43105042013-12-06 23:23:36 -08001433
Siobhan Tullybf1153a2013-05-27 20:53:48 -04001434admin.site.register(Deployment, DeploymentAdmin)
Siobhan Tully4bc09f22013-04-10 21:15:21 -04001435admin.site.register(Site, SiteAdmin)
Siobhan Tully4bc09f22013-04-10 21:15:21 -04001436admin.site.register(Slice, SliceAdmin)
Siobhan Tullyce652d02013-10-08 21:52:35 -04001437admin.site.register(Service, ServiceAdmin)
smbakera3cf70c2013-06-27 02:01:41 -07001438admin.site.register(Reservation, ReservationAdmin)
Scott Baker74d8e622013-07-29 16:04:22 -07001439admin.site.register(Network, NetworkAdmin)
1440admin.site.register(Router, RouterAdmin)
Scott Baker74d8e622013-07-29 16:04:22 -07001441admin.site.register(NetworkTemplate, NetworkTemplateAdmin)
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001442admin.site.register(Account, AccountAdmin)
1443admin.site.register(Invoice, InvoiceAdmin)
Siobhan Tullybf1153a2013-05-27 20:53:48 -04001444
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001445if True:
1446 admin.site.register(NetworkParameterType, NetworkParameterTypeAdmin)
1447 admin.site.register(ServiceClass, ServiceClassAdmin)
Siobhan Tullybfd11dc2013-09-03 12:59:24 -04001448 #admin.site.register(PlanetStack)
Siobhan Tullyd3515752013-06-21 16:34:53 -04001449 admin.site.register(Tag, TagAdmin)
Siobhan Tullyce652d02013-10-08 21:52:35 -04001450 admin.site.register(DeploymentRole)
1451 admin.site.register(SiteRole)
1452 admin.site.register(SliceRole)
1453 admin.site.register(PlanetStackRole)
Siobhan Tullybf1153a2013-05-27 20:53:48 -04001454 admin.site.register(Node, NodeAdmin)
Siobhan Tullybfd11dc2013-09-03 12:59:24 -04001455 #admin.site.register(SlicePrivilege, SlicePrivilegeAdmin)
1456 #admin.site.register(SitePrivilege, SitePrivilegeAdmin)
Siobhan Tullybf1153a2013-05-27 20:53:48 -04001457 admin.site.register(Sliver, SliverAdmin)
Siobhan Tullybf1153a2013-05-27 20:53:48 -04001458 admin.site.register(Image, ImageAdmin)
Scott Baker2c3cb642014-05-19 17:55:56 -07001459 admin.site.register(DashboardView, DashboardViewAdmin)
Tony Mack7130ac32013-03-22 21:58:00 -04001460