blob: 0c90b9aa1d700133894730363ba69fa6cd767d9a [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 Tullybf1153a2013-05-27 20:53:48 -040014import django_evolution
Tony Mack7130ac32013-03-22 21:58:00 -040015
Siobhan Tully4bc09f22013-04-10 21:15:21 -040016
17class ReadonlyTabularInline(admin.TabularInline):
18 can_delete = False
19 extra = 0
20 editable_fields = []
21
22 def get_readonly_fields(self, request, obj=None):
23 fields = []
24 for field in self.model._meta.get_all_field_names():
25 if (not field == 'id'):
26 if (field not in self.editable_fields):
27 fields.append(field)
28 return fields
29
30 def has_add_permission(self, request):
31 return False
32
33class SliverInline(admin.TabularInline):
34 model = Sliver
Tony Mackb0d97422013-06-10 09:57:45 -040035 fields = ['ip', 'instance_name', 'slice', 'numberCores', 'image', 'node', 'deploymentNetwork']
Siobhan Tully4bc09f22013-04-10 21:15:21 -040036 extra = 0
Tony Mack3777b012013-05-07 21:38:06 -040037 #readonly_fields = ['ip', 'instance_name', 'image']
38 readonly_fields = ['ip', 'instance_name']
Tony Mackc2835a92013-05-28 09:18:49 -040039
Siobhan Tully4bc09f22013-04-10 21:15:21 -040040
41class SiteInline(admin.TabularInline):
42 model = Site
43 extra = 0
44
Siobhan Tully30fd4292013-05-10 08:59:56 -040045class UserInline(admin.TabularInline):
46 model = User
Siobhan Tully47ae1b52013-05-10 15:53:14 -040047 fields = ['email', 'firstname', 'lastname']
Siobhan Tully30fd4292013-05-10 08:59:56 -040048 extra = 0
49
Tony Mack00d361f2013-04-28 10:28:42 -040050class SliceInline(admin.TabularInline):
51 model = Slice
52 extra = 0
53
Tony Mack00d361f2013-04-28 10:28:42 -040054class RoleInline(admin.TabularInline):
55 model = Role
56 extra = 0
57
Siobhan Tully4bc09f22013-04-10 21:15:21 -040058class NodeInline(admin.TabularInline):
59 model = Node
60 extra = 0
61
Siobhan Tullyaa1bcd52013-05-10 12:43:09 -040062class SitePrivilegeInline(admin.TabularInline):
63 model = SitePrivilege
64 extra = 0
65
Tony Mackc2835a92013-05-28 09:18:49 -040066 def formfield_for_foreignkey(self, db_field, request, **kwargs):
67 if db_field.name == 'site':
68 if not request.user.is_admin:
69 # only show sites where user is an admin or pi
70 roles = Role.objects.filter(role_type__in=['admin', 'pi'])
71 site_privileges = SitePrivilege.objects.filter(user=request.user).filter(role__in=roles)
72 login_bases = [site_privilege.site.login_base for site_privilege in site_privileges]
73 sites = Site.objects.filter(login_base__in=login_bases)
74 kwargs['queryset'] = sites
75
76 if db_field.name == 'user':
77 if not request.user.is_admin:
78 # only show users from sites where caller has admin or pi role
79 roles = Role.objects.filter(role_type__in=['admin', 'pi'])
80 site_privileges = SitePrivilege.objects.filter(user=request.user).filter(role__in=roles)
81 sites = [site_privilege.site for site_privilege in site_privileges]
82 site_privileges = SitePrivilege.objects.filter(site__in=sites)
83 emails = [site_privilege.user.email for site_privilege in site_privileges]
84 users = User.objects.filter(email__in=emails)
85 kwargs['queryset'] = users
86 return super(SitePrivilegeInline, self).formfield_for_foreignkey(db_field, request, **kwargs)
87
Siobhan Tullyaa1bcd52013-05-10 12:43:09 -040088class SliceMembershipInline(admin.TabularInline):
89 model = SliceMembership
90 extra = 0
91
Tony Mackc2835a92013-05-28 09:18:49 -040092 def formfield_for_foreignkey(self, db_field, request, **kwargs):
93 if db_field.name == 'slice':
94 if not request.user.is_admin:
95 # only show slices at sites where caller has admin or pi role
96 roles = Role.objects.filter(role_type__in=['admin', 'pi'])
97 site_privileges = SitePrivilege.objects.filter(user=request.user).filter(role__in=roles)
98 sites = [site_privilege.site for site_privilege in site_privileges]
99 slices = Slice.objects.filter(site__in=sites)
100 kwargs['queryset'] = slices
101 if db_field.name == 'user':
102 if not request.user.is_admin:
103 # only show users from sites where caller has admin or pi role
104 roles = Role.objects.filter(role_type__in=['admin', 'pi'])
105 site_privileges = SitePrivilege.objects.filter(user=request.user).filter(role__in=roles)
106 sites = [site_privilege.site for site_privilege in site_privileges]
107 site_privileges = SitePrivilege.objects.filter(site__in=sites)
108 emails = [site_privilege.user.email for site_privilege in site_privileges]
109 users = User.objects.filter(email__in=emails)
110 kwargs['queryset'] = list(users)
111
112 return super(SliceMembershipInline, self).formfield_for_foreignkey(db_field, request, **kwargs)
113
Scott Baker307e06f2013-05-21 17:25:56 -0700114class SliceTagInline(admin.TabularInline):
115 model = SliceTag
116 extra = 0
117
Tony Mack5e71a662013-05-03 23:30:41 -0400118class PlainTextWidget(forms.HiddenInput):
119 input_type = 'hidden'
120
121 def render(self, name, value, attrs=None):
122 if value is None:
123 value = ''
Tony Mack1d6b85f2013-05-07 18:49:14 -0400124 return mark_safe(str(value) + super(PlainTextWidget, self).render(name, value, attrs))
Tony Mack9bcbe4f2013-04-29 08:13:27 -0400125
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400126class PlanetStackBaseAdmin(admin.ModelAdmin):
127 save_on_top = False
128
Tony Mack0553f282013-06-10 22:54:50 -0400129class RoleAdmin(PlanetStackBaseAdmin):
Tony Mack9bcbe4f2013-04-29 08:13:27 -0400130 fieldsets = [
131 ('Role', {'fields': ['role_type']})
132 ]
133 list_display = ('role_type',)
Tony Mackfdd4d802013-04-27 13:02:33 -0400134
Tony Mack02755d42013-05-02 00:00:10 -0400135
Siobhan Tullybf1153a2013-05-27 20:53:48 -0400136class DeploymentAdminForm(forms.ModelForm):
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400137 sites = forms.ModelMultipleChoiceField(
138 queryset=Site.objects.all(),
139 required=False,
140 widget=FilteredSelectMultiple(
141 verbose_name=('Sites'), is_stacked=False
142 )
143 )
144 class Meta:
Siobhan Tullybf1153a2013-05-27 20:53:48 -0400145 model = Deployment
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400146
147 def __init__(self, *args, **kwargs):
Siobhan Tullybf1153a2013-05-27 20:53:48 -0400148 super(DeploymentAdminForm, self).__init__(*args, **kwargs)
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400149
150 if self.instance and self.instance.pk:
151 self.fields['sites'].initial = self.instance.sites.all()
152
153 def save(self, commit=True):
Siobhan Tullybf1153a2013-05-27 20:53:48 -0400154 deploymentNetwork = super(DeploymentAdminForm, self).save(commit=False)
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400155 if commit:
156 deploymentNetwork.save()
157
158 if deploymentNetwork.pk:
159 deploymentNetwork.sites = self.cleaned_data['sites']
160 self.save_m2m()
161
162 return deploymentNetwork
163
Siobhan Tullybf1153a2013-05-27 20:53:48 -0400164class DeploymentAdmin(PlanetStackBaseAdmin):
165 form = DeploymentAdminForm
Siobhan Tullyaa1bcd52013-05-10 12:43:09 -0400166 inlines = [NodeInline,SliverInline]
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400167
Tony Mack5cd13202013-05-01 21:48:38 -0400168 def get_formsets(self, request, obj=None):
169 for inline in self.get_inline_instances(request, obj):
170 # hide MyInline in the add view
171 if obj is None:
172 continue
173 # give inline object access to driver and caller
Tony Macked163d72013-05-02 20:05:42 -0400174 auth = request.session.get('auth', {})
Siobhan Tully73291342013-05-10 10:50:08 -0400175 if request.user.site:
176 auth['tenant'] = request.user.site.login_base
Tony Macked163d72013-05-02 20:05:42 -0400177 inline.model.os_manager = OpenStackManager(auth=auth, caller=request.user)
Tony Mack5cd13202013-05-01 21:48:38 -0400178 yield inline.get_formset(request, obj)
179
Tony Mack0553f282013-06-10 22:54:50 -0400180class SiteAdmin(PlanetStackBaseAdmin):
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400181 fieldsets = [
182 (None, {'fields': ['name', 'site_url', 'enabled', 'is_public', 'login_base']}),
183 ('Location', {'fields': ['latitude', 'longitude']}),
184 ('Deployment Networks', {'fields': ['deployments']})
185 ]
186 list_display = ('name', 'login_base','site_url', 'enabled')
187 filter_horizontal = ('deployments',)
Siobhan Tullyaa1bcd52013-05-10 12:43:09 -0400188 inlines = [NodeInline, UserInline, SitePrivilegeInline]
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400189 search_fields = ['name']
190
Tony Mack04062832013-05-10 08:22:44 -0400191 def queryset(self, request):
192 # admins can see all keys. Users can only see sites they belong to.
193 qs = super(SiteAdmin, self).queryset(request)
194 if not request.user.is_admin:
195 valid_sites = [request.user.site.login_base]
196 roles = request.user.get_roles()
197 for tenant_list in roles.values():
198 valid_sites.extend(tenant_list)
199 qs = qs.filter(login_base__in=valid_sites)
200 return qs
201
Tony Mack5cd13202013-05-01 21:48:38 -0400202 def get_formsets(self, request, obj=None):
203 for inline in self.get_inline_instances(request, obj):
204 # hide MyInline in the add view
205 if obj is None:
206 continue
Tony Mack5cd13202013-05-01 21:48:38 -0400207 yield inline.get_formset(request, obj)
208
Tony Mack9bcbe4f2013-04-29 08:13:27 -0400209class SitePrivilegeAdmin(PlanetStackBaseAdmin):
Tony Mack00d361f2013-04-28 10:28:42 -0400210 fieldsets = [
211 (None, {'fields': ['user', 'site', 'role']})
212 ]
213 list_display = ('user', 'site', 'role')
214
Tony Mackc2835a92013-05-28 09:18:49 -0400215 def formfield_for_foreignkey(self, db_field, request, **kwargs):
216 if db_field.name == 'site':
217 if not request.user.is_admin:
218 # only show sites where user is an admin or pi
219 sites = set()
220 for site_privilege in SitePrivilege.objects.filer(user=request.user):
221 if site_privilege.role.role_type in ['admin', 'pi']:
222 sites.add(site_privilege.site)
223 kwargs['queryset'] = Site.objects.filter(site__in=list(sites))
224
225 if db_field.name == 'user':
226 if not request.user.is_admin:
227 # only show users from sites where caller has admin or pi role
228 roles = Role.objects.filter(role_type__in=['admin', 'pi'])
229 site_privileges = SitePrivilege.objects.filter(user=request.user).filter(role__in=roles)
230 sites = [site_privilege.site for site_privilege in site_privileges]
231 site_privileges = SitePrivilege.objects.filter(site__in=sites)
232 emails = [site_privilege.user.email for site_privilege in site_privileges]
233 users = User.objects.filter(email__in=emails)
234 kwargs['queryset'] = users
235
236 return super(SitePrivilegeAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)
237
Tony Mack04062832013-05-10 08:22:44 -0400238 def queryset(self, request):
239 # admins can see all privileges. Users can only see privileges at sites
Tony Mackc2835a92013-05-28 09:18:49 -0400240 # where they have the admin role or pi role.
Tony Mack04062832013-05-10 08:22:44 -0400241 qs = super(SitePrivilegeAdmin, self).queryset(request)
242 if not request.user.is_admin:
Tony Mackc2835a92013-05-28 09:18:49 -0400243 roles = Role.objects.filter(role_type__in=['admin', 'pi'])
244 site_privileges = SitePrivilege.objects.filter(user=request.user).filter(role__in=roles)
245 login_bases = [site_privilege.site.login_base for site_privilege in site_privileges]
246 sites = Site.objects.filter(login_base__in=login_bases)
247 qs = qs.filter(site__in=sites)
Tony Mack04062832013-05-10 08:22:44 -0400248 return qs
249
Tony Mackfdd4d802013-04-27 13:02:33 -0400250class SliceAdmin(OSModelAdmin):
Siobhan Tully30fd4292013-05-10 08:59:56 -0400251 fields = ['name', 'site', 'serviceClass', 'description', 'slice_url']
252 list_display = ('name', 'site','serviceClass', 'slice_url')
Scott Baker307e06f2013-05-21 17:25:56 -0700253 inlines = [SliverInline, SliceMembershipInline, SliceTagInline]
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400254
Tony Mackc2835a92013-05-28 09:18:49 -0400255 def formfield_for_foreignkey(self, db_field, request, **kwargs):
256 if db_field.name == 'site':
257 if not request.user.is_admin:
258 # only show sites where user is a pi or admin
259 roles = Role.objects.filter(role_type__in=['admin', 'pi'])
260 site_privileges = SitePrivilege.objects.filter(user=request.user).filter(role__in=roles)
261 login_bases = [site_privilege.site.login_base for site_privilege in site_privileges]
262 sites = Site.objects.filter(login_base__in=login_bases)
263 kwargs['queryset'] = sites
264
265 return super(SliceAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)
266
Tony Mack04062832013-05-10 08:22:44 -0400267 def queryset(self, request):
268 # admins can see all keys. Users can only see slices they belong to.
269 qs = super(SliceAdmin, self).queryset(request)
270 if not request.user.is_admin:
271 valid_slices = []
272 roles = request.user.get_roles()
273 for tenant_list in roles.values():
274 valid_slices.extend(tenant_list)
275 qs = qs.filter(name__in=valid_slices)
276 return qs
277
Tony Mack79748612013-05-01 14:52:03 -0400278 def get_formsets(self, request, obj=None):
279 for inline in self.get_inline_instances(request, obj):
280 # hide MyInline in the add view
281 if obj is None:
282 continue
283 # give inline object access to driver and caller
Tony Mack93048c22013-05-02 11:20:26 -0400284 auth = request.session.get('auth', {})
285 auth['tenant'] = obj.name # meed to connect using slice's tenant
286 inline.model.os_manager = OpenStackManager(auth=auth, caller=request.user)
Tony Mackb0d97422013-06-10 09:57:45 -0400287 inline.model.creator = request.user
Tony Mack79748612013-05-01 14:52:03 -0400288 yield inline.get_formset(request, obj)
289
Tony Mackfdd4d802013-04-27 13:02:33 -0400290 def get_queryset(self, request):
291 qs = super(SliceAdmin, self).get_queryset(request)
292 if request.user.is_superuser:
293 return qs
294 # users can only see slices at their site
295 return qs.filter(site=request.user.site)
296
Tony Mack9bcbe4f2013-04-29 08:13:27 -0400297class SliceMembershipAdmin(PlanetStackBaseAdmin):
Tony Mack00d361f2013-04-28 10:28:42 -0400298 fieldsets = [
299 (None, {'fields': ['user', 'slice', 'role']})
300 ]
301 list_display = ('user', 'slice', 'role')
Tony Mack00d361f2013-04-28 10:28:42 -0400302
Tony Mackc2835a92013-05-28 09:18:49 -0400303 def formfield_for_foreignkey(self, db_field, request, **kwargs):
304 if db_field.name == 'slice':
305 if not request.user.is_admin:
306 # only show slices at sites where caller has admin or pi role
307 roles = Role.objects.filter(role_type__in=['admin', 'pi'])
308 site_privileges = SitePrivilege.objects.filter(user=request.user).filter(role__in=roles)
309 sites = [site_privilege.site for site_privilege in site_privileges]
310 slices = Slice.objects.filter(site__in=sites)
311 kwargs['queryset'] = slices
312
313 if db_field.name == 'user':
314 if not request.user.is_admin:
315 # only show users from sites where caller has admin or pi role
316 roles = Role.objects.filter(role_type__in=['admin', 'pi'])
317 site_privileges = SitePrivilege.objects.filter(user=request.user).filter(role__in=roles)
318 sites = [site_privilege.site for site_privilege in site_privileges]
319 site_privileges = SitePrivilege.objects.filter(site__in=sites)
320 emails = [site_privilege.user.email for site_privilege in site_privileges]
321 users = User.objects.filter(email__in=emails)
322 kwargs['queryset'] = users
323
324 return super(SliceMembershipAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)
325
Tony Mack04062832013-05-10 08:22:44 -0400326 def queryset(self, request):
327 # admins can see all memberships. Users can only see memberships of
328 # slices where they have the admin role.
329 qs = super(SliceMembershipAdmin, self).queryset(request)
330 if not request.user.is_admin:
Tony Mackc2835a92013-05-28 09:18:49 -0400331 roles = Role.objects.filter(role_type__in=['admin', 'pi'])
332 site_privileges = SitePrivilege.objects.filter(user=request.user).filter(role__in=roles)
333 login_bases = [site_privilege.site.login_base for site_privilege in site_privileges]
334 sites = Site.objects.filter(login_base__in=login_bases)
335 slices = Slice.objects.filter(site__in=sites)
336 qs = qs.filter(slice__in=slices)
Tony Mack04062832013-05-10 08:22:44 -0400337 return qs
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400338
Tony Mack9bcbe4f2013-04-29 08:13:27 -0400339 def save_model(self, request, obj, form, change):
Tony Mack951dab42013-05-02 19:51:45 -0400340 # update openstack connection to use this site/tenant
341 auth = request.session.get('auth', {})
342 auth['tenant'] = obj.slice.name
343 obj.os_manager = OpenStackManager(auth=auth, caller=request.user)
Tony Mack9bcbe4f2013-04-29 08:13:27 -0400344 obj.save()
345
346 def delete_model(self, request, obj):
Tony Mack951dab42013-05-02 19:51:45 -0400347 # update openstack connection to use this site/tenant
348 auth = request.session.get('auth', {})
349 auth['tenant'] = obj.slice.name
350 obj.os_manager = OpenStackManager(auth=auth, caller=request.user)
Tony Mack9bcbe4f2013-04-29 08:13:27 -0400351 obj.delete()
352
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400353
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400354class ImageAdmin(admin.ModelAdmin):
355 fields = ['image_id', 'name', 'disk_format', 'container_format']
356
357class NodeAdmin(admin.ModelAdmin):
Siobhan Tullybf1153a2013-05-27 20:53:48 -0400358 list_display = ('name', 'site', 'deployment')
359 list_filter = ('deployment',)
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400360
Tony Mackd90cdbf2013-04-16 22:48:40 -0400361
362class SliverForm(forms.ModelForm):
363 class Meta:
Tony Mack1d6b85f2013-05-07 18:49:14 -0400364 model = Sliver
Tony Mackd90cdbf2013-04-16 22:48:40 -0400365 ip = forms.CharField(widget=PlainTextWidget)
Tony Mack18261812013-05-02 16:39:20 -0400366 instance_name = forms.CharField(widget=PlainTextWidget)
Tony Mackd90cdbf2013-04-16 22:48:40 -0400367 widgets = {
368 'ip': PlainTextWidget(),
Tony Mack18261812013-05-02 16:39:20 -0400369 'instance_name': PlainTextWidget(),
Siobhan Tully53437282013-04-26 19:30:27 -0400370 }
Tony Mackd90cdbf2013-04-16 22:48:40 -0400371
Tony Mack9bcbe4f2013-04-29 08:13:27 -0400372class SliverAdmin(PlanetStackBaseAdmin):
Tony Mackd90cdbf2013-04-16 22:48:40 -0400373 form = SliverForm
Tony Mackcdec0902013-04-15 00:38:49 -0400374 fieldsets = [
Tony Mack10082022013-05-06 17:15:00 -0400375 ('Sliver', {'fields': ['ip', 'instance_name', 'slice', 'numberCores', 'image', 'key', 'node', 'deploymentNetwork']})
Tony Mackcdec0902013-04-15 00:38:49 -0400376 ]
Tony Mack10082022013-05-06 17:15:00 -0400377 list_display = ['ip', 'instance_name', 'slice', 'numberCores', 'image', 'key', 'node', 'deploymentNetwork']
Tony Mack53106f32013-04-27 16:43:01 -0400378
Tony Mackc2835a92013-05-28 09:18:49 -0400379 def formfield_for_foreignkey(self, db_field, request, **kwargs):
380 if db_field.name == 'slice':
381 if not request.user.is_admin:
382 slices = set([sm.slice.name for sm in SliceMembership.objects.filter(user=request.user)])
383 kwargs['queryset'] = Slice.objects.filter(name__in=list(slices))
384
385 return super(SliverAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)
386
Tony Mack04062832013-05-10 08:22:44 -0400387 def queryset(self, request):
388 # admins can see all slivers. Users can only see slivers of
389 # the slices they belong to.
390 qs = super(SliverAdmin, self).queryset(request)
391 if not request.user.is_admin:
392 tenants = []
393 roles = request.user.get_roles()
394 for tenant_list in roles.values():
395 tenants.extend(tenant_list)
396 valid_slices = Slice.objects.filter(name__in=tenants)
397 qs = qs.filter(slice__in=valid_slices)
398 return qs
399
Tony Mack1d6b85f2013-05-07 18:49:14 -0400400 def get_formsets(self, request, obj=None):
401 # make some fields read only if we are updating an existing record
402 if obj == None:
403 #self.readonly_fields = ('ip', 'instance_name')
404 self.readonly_fields = ()
405 else:
Tony Mack1e889462013-05-10 21:34:54 -0400406 self.readonly_fields = ()
407 #self.readonly_fields = ('ip', 'instance_name', 'slice', 'image', 'key')
Tony Mack1d6b85f2013-05-07 18:49:14 -0400408
409 for inline in self.get_inline_instances(request, obj):
410 # hide MyInline in the add view
411 if obj is None:
412 continue
413 # give inline object access to driver and caller
414 auth = request.session.get('auth', {})
415 auth['tenant'] = obj.name # meed to connect using slice's tenant
416 inline.model.os_manager = OpenStackManager(auth=auth, caller=request.user)
417 yield inline.get_formset(request, obj)
Tony Mack53106f32013-04-27 16:43:01 -0400418
419 def save_model(self, request, obj, form, change):
Tony Mack951dab42013-05-02 19:51:45 -0400420 # update openstack connection to use this site/tenant
421 auth = request.session.get('auth', {})
422 auth['tenant'] = obj.slice.name
423 obj.os_manager = OpenStackManager(auth=auth, caller=request.user)
Tony Mackb0d97422013-06-10 09:57:45 -0400424 obj.creator = request.user
Tony Mack53106f32013-04-27 16:43:01 -0400425 obj.save()
426
427 def delete_model(self, request, obj):
Tony Mack951dab42013-05-02 19:51:45 -0400428 # update openstack connection to use this site/tenant
429 auth = request.session.get('auth', {})
430 auth['tenant'] = obj.slice.name
431 obj.os_manager = OpenStackManager(auth=auth, caller=request.user)
Tony Mack53106f32013-04-27 16:43:01 -0400432 obj.delete()
Tony Mackcdec0902013-04-15 00:38:49 -0400433
Siobhan Tully53437282013-04-26 19:30:27 -0400434class UserCreationForm(forms.ModelForm):
435 """A form for creating new users. Includes all the required
436 fields, plus a repeated password."""
437 password1 = forms.CharField(label='Password', widget=forms.PasswordInput)
438 password2 = forms.CharField(label='Password confirmation', widget=forms.PasswordInput)
439
440 class Meta:
Siobhan Tully30fd4292013-05-10 08:59:56 -0400441 model = User
Tony Mackb0d97422013-06-10 09:57:45 -0400442 fields = ('email', 'firstname', 'lastname', 'phone', 'public_key', 'site')
Siobhan Tully53437282013-04-26 19:30:27 -0400443
444 def clean_password2(self):
445 # Check that the two password entries match
446 password1 = self.cleaned_data.get("password1")
447 password2 = self.cleaned_data.get("password2")
448 if password1 and password2 and password1 != password2:
449 raise forms.ValidationError("Passwords don't match")
450 return password2
451
452 def save(self, commit=True):
453 # Save the provided password in hashed format
454 user = super(UserCreationForm, self).save(commit=False)
Tony Mackf9f4afb2013-05-01 21:02:12 -0400455 user.password = self.cleaned_data["password1"]
456 #user.set_password(self.cleaned_data["password1"])
Siobhan Tully53437282013-04-26 19:30:27 -0400457 if commit:
458 user.save()
459 return user
460
461
462class UserChangeForm(forms.ModelForm):
463 """A form for updating users. Includes all the fields on
464 the user, but replaces the password field with admin's
465 password hash display field.
466 """
467 password = ReadOnlyPasswordHashField()
468
469 class Meta:
Siobhan Tully30fd4292013-05-10 08:59:56 -0400470 model = User
Siobhan Tully53437282013-04-26 19:30:27 -0400471
472 def clean_password(self):
473 # Regardless of what the user provides, return the initial value.
474 # This is done here, rather than on the field, because the
475 # field does not have access to the initial value
476 return self.initial["password"]
477
478
Siobhan Tully30fd4292013-05-10 08:59:56 -0400479class UserAdmin(UserAdmin, OSModelAdmin):
Siobhan Tully53437282013-04-26 19:30:27 -0400480 class Meta:
481 app_label = "core"
482
483 # The forms to add and change user instances
484 form = UserChangeForm
485 add_form = UserCreationForm
486
487 # The fields to be used in displaying the User model.
488 # These override the definitions on the base UserAdmin
489 # that reference specific fields on auth.User.
Tony Mack416c0f22013-05-09 16:59:09 -0400490 list_display = ('email', 'site', 'firstname', 'lastname', 'is_admin', 'last_login')
Siobhan Tully53437282013-04-26 19:30:27 -0400491 list_filter = ('site',)
Siobhan Tullyaa1bcd52013-05-10 12:43:09 -0400492 inlines = [SitePrivilegeInline, SliceMembershipInline]
Siobhan Tully53437282013-04-26 19:30:27 -0400493 fieldsets = (
Scott Baker9266e6b2013-05-19 15:54:48 -0700494 (None, {'fields': ('email', 'password', 'site', 'is_admin', 'timezone')}),
Tony Mackb0d97422013-06-10 09:57:45 -0400495 ('Personal info', {'fields': ('firstname','lastname','phone', 'public_key')}),
Siobhan Tully53437282013-04-26 19:30:27 -0400496 #('Important dates', {'fields': ('last_login',)}),
497 )
498 add_fieldsets = (
499 (None, {
500 'classes': ('wide',),
Tony Mackb0d97422013-06-10 09:57:45 -0400501 'fields': ('email', 'firstname', 'lastname', 'phone', 'site', 'public_key','password1', 'password2', 'is_admin')}
Siobhan Tully53437282013-04-26 19:30:27 -0400502 ),
503 )
504 search_fields = ('email',)
505 ordering = ('email',)
506 filter_horizontal = ()
507
Tony Mackc2835a92013-05-28 09:18:49 -0400508 def formfield_for_foreignkey(self, db_field, request, **kwargs):
509 if db_field.name == 'site':
510 if not request.user.is_admin:
511 # show sites where caller is an admin or pi
512 sites = []
513 for site_privilege in SitePrivilege.objects.filer(user=request.user):
514 if site_privilege.role.role_type in ['admin', 'pi']:
515 sites.append(site_privilege.site.login_base)
516 kwargs['queryset'] = Site.objects.filter(login_base__in(list(sites)))
517
518 return super(UserAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)
519
Scott Baker3de3e372013-05-10 16:50:44 -0700520class ServiceResourceInline(admin.TabularInline):
521 model = ServiceResource
522 extra = 0
523
524class ServiceClassAdmin(admin.ModelAdmin):
525 list_display = ('name', 'commitment', 'membershipFee')
526 inlines = [ServiceResourceInline]
527
Scott Baker133c9212013-05-17 09:09:11 -0700528class ReservedResourceInline(admin.TabularInline):
529 model = ReservedResource
530 extra = 0
531
532 def formfield_for_foreignkey(self, db_field, request=None, **kwargs):
533 field = super(ReservedResourceInline, self).formfield_for_foreignkey(db_field, request, **kwargs)
534
535 if db_field.name == 'resource':
536 # restrict resources to those that the slice's service class allows
537 if request._slice is not None:
538 field.queryset = field.queryset.filter(serviceClass = request._slice.serviceClass, calendarReservable=True)
539 if len(field.queryset) > 0:
540 field.initial = field.queryset.all()[0]
541 else:
542 field.queryset = field.queryset.none()
543 elif db_field.name == 'sliver':
544 # restrict slivers to those that belong to the slice
545 if request._slice is not None:
546 field.queryset = field.queryset.filter(slice = request._slice)
547 else:
548 field.queryset = field.queryset.none()
549
550 return field
551
552class ReservationChangeForm(forms.ModelForm):
553 class Meta:
554 model = Reservation
555
556class ReservationAddForm(forms.ModelForm):
557 slice = forms.ModelChoiceField(queryset=Slice.objects.all(), widget=forms.Select(attrs={"onChange":"document.getElementById('id_refresh').value=1; submit()"}))
558 refresh = forms.CharField(widget=forms.HiddenInput())
559
560 class Media:
561 css = {'all': ('planetstack.css',)} # .field-refresh { display: none; }
562
563 def clean_slice(self):
564 slice = self.cleaned_data.get("slice")
565 x = ServiceResource.objects.filter(serviceClass = slice.serviceClass, calendarReservable=True)
566 if len(x) == 0:
567 raise forms.ValidationError("The slice you selected does not have a service class that allows reservations")
568 return slice
569
570 class Meta:
571 model = Reservation
572
573class ReservationAddRefreshForm(ReservationAddForm):
574 """ This form is displayed when the Reservation Form receives an update
575 from the Slice dropdown onChange handler. It doesn't validate the
576 data and doesn't save the data. This will cause the form to be
577 redrawn.
578 """
579
Scott Baker8737e5f2013-05-17 09:35:32 -0700580 """ don't validate anything other than slice """
581 dont_validate_fields = ("startTime", "duration")
582
Scott Baker133c9212013-05-17 09:09:11 -0700583 def full_clean(self):
584 result = super(ReservationAddForm, self).full_clean()
Scott Baker8737e5f2013-05-17 09:35:32 -0700585
586 for fieldname in self.dont_validate_fields:
587 if fieldname in self._errors:
588 del self._errors[fieldname]
589
Scott Baker133c9212013-05-17 09:09:11 -0700590 return result
591
592 """ don't save anything """
593 def is_valid(self):
594 return False
595
596class ReservationAdmin(admin.ModelAdmin):
597 list_display = ('startTime', 'duration')
598 inlines = [ReservedResourceInline]
599 form = ReservationAddForm
600
601 def add_view(self, request, form_url='', extra_context=None):
Scott Bakeracd45142013-05-19 16:19:16 -0700602 timezone.activate(request.user.timezone)
Scott Baker133c9212013-05-17 09:09:11 -0700603 request._refresh = False
604 request._slice = None
605 if request.method == 'POST':
Scott Baker8737e5f2013-05-17 09:35:32 -0700606 # "refresh" will be set to "1" if the form was submitted due to
607 # a change in the Slice dropdown.
Scott Baker133c9212013-05-17 09:09:11 -0700608 if request.POST.get("refresh","1") == "1":
609 request._refresh = True
610 request.POST["refresh"] = "0"
Scott Baker8737e5f2013-05-17 09:35:32 -0700611
612 # Keep track of the slice that was selected, so the
613 # reservedResource inline can filter items for the slice.
Scott Baker133c9212013-05-17 09:09:11 -0700614 request._slice = request.POST.get("slice",None)
615 if (request._slice is not None):
616 request._slice = Slice.objects.get(id=request._slice)
617
618 result = super(ReservationAdmin, self).add_view(request, form_url, extra_context)
619 return result
620
Scott Bakeracd45142013-05-19 16:19:16 -0700621 def changelist_view(self, request, extra_context = None):
622 timezone.activate(request.user.timezone)
623 return super(ReservationAdmin, self).changelist_view(request, extra_context)
624
Scott Baker133c9212013-05-17 09:09:11 -0700625 def get_form(self, request, obj=None, **kwargs):
626 request._obj_ = obj
627 if obj is not None:
Scott Baker8737e5f2013-05-17 09:35:32 -0700628 # For changes, set request._slice to the slice already set in the
629 # object.
Scott Baker133c9212013-05-17 09:09:11 -0700630 request._slice = obj.slice
631 self.form = ReservationChangeForm
632 else:
633 if getattr(request, "_refresh", False):
634 self.form = ReservationAddRefreshForm
635 else:
636 self.form = ReservationAddForm
637 return super(ReservationAdmin, self).get_form(request, obj, **kwargs)
638
639 def get_readonly_fields(self, request, obj=None):
640 if (obj is not None):
641 # Prevent slice from being changed after the reservation has been
642 # created.
643 return ['slice']
644 else:
645 return []
Scott Baker3de3e372013-05-10 16:50:44 -0700646
Tony Mack31c2b8f2013-04-26 20:01:42 -0400647# register a signal that caches the user's credentials when they log in
648def cache_credentials(sender, user, request, **kwds):
649 auth = {'username': request.POST['username'],
650 'password': request.POST['password']}
651 request.session['auth'] = auth
652user_logged_in.connect(cache_credentials)
653
Siobhan Tully53437282013-04-26 19:30:27 -0400654# Now register the new UserAdmin...
Siobhan Tully30fd4292013-05-10 08:59:56 -0400655admin.site.register(User, UserAdmin)
Siobhan Tully53437282013-04-26 19:30:27 -0400656# ... and, since we're not using Django's builtin permissions,
657# unregister the Group model from admin.
658admin.site.unregister(Group)
659
Siobhan Tullybf1153a2013-05-27 20:53:48 -0400660#Do not show django evolution in the admin interface
661from django_evolution.models import Version, Evolution
662admin.site.unregister(Version)
663admin.site.unregister(Evolution)
664
665
666# When debugging it is often easier to see all the classes, but for regular use
667# only the top-levels should be displayed
668showAll = False
669
670admin.site.register(Deployment, DeploymentAdmin)
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400671admin.site.register(Site, SiteAdmin)
Siobhan Tully4bc09f22013-04-10 21:15:21 -0400672admin.site.register(Slice, SliceAdmin)
Siobhan Tullyaa1bcd52013-05-10 12:43:09 -0400673#admin.site.register(Subnet)
Siobhan Tullybf1153a2013-05-27 20:53:48 -0400674
675
676if showAll:
677 admin.site.register(Node, NodeAdmin)
678 admin.site.register(SliceMembership, SliceMembershipAdmin)
679 admin.site.register(SitePrivilege, SitePrivilegeAdmin)
680 admin.site.register(Role, RoleAdmin)
681 admin.site.register(Sliver, SliverAdmin)
682 admin.site.register(ServiceClass, ServiceClassAdmin)
683 admin.site.register(Reservation, ReservationAdmin)
684 admin.site.register(Image, ImageAdmin)
Tony Mack7130ac32013-03-22 21:58:00 -0400685