remove Slice.instantiation field
[plstackapi.git] / plstackapi / core / admin.py
1 from plstackapi.core.models import Site
2 from plstackapi.core.models import *
3 from plstackapi.openstack.manager import OpenStackManager
4
5 from django.contrib import admin
6 from django.contrib.auth.models import Group
7 from django import forms
8 from django.utils.safestring import mark_safe
9 from django.contrib.auth.admin import UserAdmin
10 from django.contrib.admin.widgets import FilteredSelectMultiple
11 from django.contrib.auth.forms import ReadOnlyPasswordHashField
12 from django.contrib.auth.signals import user_logged_in 
13
14
15 class ReadonlyTabularInline(admin.TabularInline):
16     can_delete = False
17     extra = 0
18     editable_fields = []
19
20     def get_readonly_fields(self, request, obj=None):
21         fields = []
22         for field in self.model._meta.get_all_field_names():
23             if (not field == 'id'):
24                 if (field not in self.editable_fields):
25                     fields.append(field)
26         return fields
27
28     def has_add_permission(self, request):
29         return False
30
31 class SliverInline(admin.TabularInline):
32     model = Sliver
33     fields = ['ip', 'name', 'slice', 'numberCores', 'image', 'key', 'node', 'deploymentNetwork']
34     extra = 0
35
36 class SiteInline(admin.TabularInline):
37     model = Site
38     extra = 0
39
40 class SliceInline(admin.TabularInline):
41     model = Slice
42     extra = 0
43
44 class UserInline(admin.TabularInline):
45     model = PLUser
46     extra = 0
47
48 class RoleInline(admin.TabularInline):
49     model = Role
50     extra = 0 
51
52 class NodeInline(admin.TabularInline):
53     model = Node
54     extra = 0
55
56 class PlainTextWidget(forms.HiddenInput):
57     input_type = 'hidden'
58
59     def render(self, name, value, attrs=None):
60         if value is None:
61             value = ''
62         return mark_safe(value + super(PlainTextWidget, self).render(name, value, attrs))
63
64 class PlanetStackBaseAdmin(admin.ModelAdmin):
65     save_on_top = False
66
67 class OSModelAdmin(PlanetStackBaseAdmin):
68     """Attach client connection to openstack on delete() and save()"""
69
70     def save_model(self, request, obj, form, change):
71         if request.user.site:
72             auth = request.session.get('auth', {})
73             auth['tenant'] = request.user.site.login_base
74             obj.os_manager = OpenStackManager(auth=auth, caller=request.user)
75         obj.save()
76
77     def delete_model(self, request, obj):
78         if request.user.site:
79             auth = request.session.get('auth', {})
80             auth['tenant'] = request.user.site.login_base
81             obj.os_manager = OpenStackManager(auth=auth, caller=request.user)
82         obj.delete() 
83
84 class RoleAdmin(OSModelAdmin):
85     fieldsets = [
86         ('Role', {'fields': ['role_type']})
87     ]
88     list_display = ('role_type',)
89
90
91 class DeploymentNetworkAdminForm(forms.ModelForm):
92     sites = forms.ModelMultipleChoiceField(
93         queryset=Site.objects.all(),
94         required=False,
95         widget=FilteredSelectMultiple(
96             verbose_name=('Sites'), is_stacked=False
97         )
98     )
99     class Meta:
100         model = DeploymentNetwork
101
102     def __init__(self, *args, **kwargs):
103         super(DeploymentNetworkAdminForm, self).__init__(*args, **kwargs)
104
105         if self.instance and self.instance.pk:
106             self.fields['sites'].initial = self.instance.sites.all()
107
108     def save(self, commit=True):
109         deploymentNetwork = super(DeploymentNetworkAdminForm, self).save(commit=False)
110         if commit:
111             deploymentNetwork.save()
112
113         if deploymentNetwork.pk:
114             deploymentNetwork.sites = self.cleaned_data['sites']
115             self.save_m2m()
116
117         return deploymentNetwork
118
119 class DeploymentNetworkAdmin(PlanetStackBaseAdmin):
120     form = DeploymentNetworkAdminForm
121     inlines = [NodeInline,]
122
123     def get_formsets(self, request, obj=None):
124         for inline in self.get_inline_instances(request, obj):
125             # hide MyInline in the add view
126             if obj is None:
127                 continue
128             # give inline object access to driver and caller
129             auth = request.session.get('auth', {})
130             auth['tenant'] = request.user.site.login_base
131             inline.model.os_manager = OpenStackManager(auth=auth, caller=request.user)
132             yield inline.get_formset(request, obj)
133
134 class SiteAdmin(OSModelAdmin):
135     fieldsets = [
136         (None, {'fields': ['name', 'site_url', 'enabled', 'is_public', 'login_base']}),
137         ('Location', {'fields': ['latitude', 'longitude']}),
138         ('Deployment Networks', {'fields': ['deployments']})
139     ]
140     list_display = ('name', 'login_base','site_url', 'enabled')
141     filter_horizontal = ('deployments',)
142     inlines = [NodeInline,]
143     search_fields = ['name']
144
145     def get_formsets(self, request, obj=None):
146         for inline in self.get_inline_instances(request, obj):
147             # hide MyInline in the add view
148             if obj is None:
149                 continue
150             # give inline object access to driver and caller
151             auth = request.session.get('auth', {})
152             auth['tenant'] = request.user.site.login_base
153             inline.model.os_manager = OpenStackManager(auth=auth, caller=request.user)
154             yield inline.get_formset(request, obj)
155
156 class SitePrivilegeAdmin(PlanetStackBaseAdmin):
157     fieldsets = [
158         (None, {'fields': ['user', 'site', 'role']})
159     ]
160     list_display = ('user', 'site', 'role')
161
162     def save_model(self, request, obj, form, change):
163         # update openstack connection to use this site/tenant   
164         auth = request.session.get('auth', {})
165         auth['tenant'] = obj.site.login_base
166         obj.os_manager = OpenStackManager(auth=auth, caller=request.user)
167         obj.save()
168
169     def delete_model(self, request, obj):
170         # update openstack connection to use this site/tenant   
171         auth = request.session.get('auth', {})
172         auth['tenant'] = obj.site.login_base
173         obj.os_manager = OpenStackManager(auth=auth, caller=request.user)
174         obj.delete()
175
176 class KeyAdmin(OSModelAdmin):
177     fieldsets = [
178         ('Key', {'fields': ['name', 'key', 'type', 'blacklisted', 'user']})
179     ]
180     list_display = ['name', 'key', 'type', 'blacklisted', 'user']
181
182     def get_queryset(self, request):
183         # get keys user is allowed to see
184         qs = super(KeyAdmin, self).get_queryset(request)
185         if request.user.is_superuser:
186             return qs
187         # users can only see their own keys
188         return qs.filter(user=request.user)  
189         
190
191 class SliceAdmin(OSModelAdmin):
192     fields = ['name', 'site', 'serviceClass', 'description', 'slice_url']
193     list_display = ('name', 'site','serviceClass', 'slice_url')
194     inlines = [SliverInline]
195
196     def get_formsets(self, request, obj=None):
197         for inline in self.get_inline_instances(request, obj):
198             # hide MyInline in the add view
199             if obj is None:
200                 continue
201             # give inline object access to driver and caller
202             auth = request.session.get('auth', {})
203             auth['tenant'] = obj.name       # meed to connect using slice's tenant
204             inline.model.os_manager = OpenStackManager(auth=auth, caller=request.user)
205             yield inline.get_formset(request, obj)
206
207     def get_queryset(self, request):
208         qs = super(SliceAdmin, self).get_queryset(request)
209         if request.user.is_superuser:
210             return qs
211         # users can only see slices at their site
212         return qs.filter(site=request.user.site) 
213
214 class SliceMembershipAdmin(PlanetStackBaseAdmin):
215     fieldsets = [
216         (None, {'fields': ['user', 'slice', 'role']})
217     ]
218     list_display = ('user', 'slice', 'role')
219
220     def save_model(self, request, obj, form, change):
221         # update openstack connection to use this site/tenant
222         auth = request.session.get('auth', {})
223         auth['tenant'] = obj.slice.name
224         obj.os_manager = OpenStackManager(auth=auth, caller=request.user)
225         obj.save()
226
227     def delete_model(self, request, obj):
228         # update openstack connection to use this site/tenant
229         auth = request.session.get('auth', {})
230         auth['tenant'] = obj.slice.name
231         obj.os_manager = OpenStackManager(auth=auth, caller=request.user)
232         obj.delete()
233
234
235 class SubnetAdmin(PlanetStackBaseAdmin):
236     fields = ['cidr', 'ip_version', 'start', 'end', 'slice']
237     list_display = ('slice','cidr', 'start', 'end', 'ip_version')
238
239     def save_model(self, request, obj, form, change):
240         # update openstack connection to use this site/tenant
241         auth = request.session.get('auth', {})
242         auth['tenant'] = obj.slice.name
243         obj.os_manager = OpenStackManager(auth=auth, caller=request.user)
244         obj.save()
245
246     def delete_model(self, request, obj):
247         # update openstack connection to use this site/tenant
248         auth = request.session.get('auth', {})
249         auth['tenant'] = obj.slice.name
250         obj.os_manager = OpenStackManager(auth=auth, caller=request.user)
251         obj.delete()
252
253 class ImageAdmin(admin.ModelAdmin):
254     fields = ['image_id', 'name', 'disk_format', 'container_format']
255
256 class NodeAdmin(admin.ModelAdmin):
257     list_display = ('name', 'site', 'deploymentNetwork')
258     list_filter = ('deploymentNetwork',)
259
260
261 class SliverForm(forms.ModelForm):
262     class Meta:
263         ip = forms.CharField(widget=PlainTextWidget)
264         instance_name = forms.CharField(widget=PlainTextWidget)
265         model = Sliver
266         widgets = {
267             'ip': PlainTextWidget(),
268             'instance_name': PlainTextWidget(),
269         }
270
271 class SliverAdmin(PlanetStackBaseAdmin):
272     form = SliverForm
273     fieldsets = [
274         ('Sliver', {'fields': ['ip', 'instance_name', 'name', 'slice', 'numberCores', 'image', 'key', 'node', 'deploymentNetwork']})
275     ]
276     list_display = ['ip', 'instance_name', 'name', 'slice', 'numberCores', 'image', 'key', 'node', 'deploymentNetwork']
277
278     def save_model(self, request, obj, form, change):
279         # update openstack connection to use this site/tenant
280         auth = request.session.get('auth', {})
281         auth['tenant'] = obj.slice.name
282         obj.os_manager = OpenStackManager(auth=auth, caller=request.user)
283         obj.save()
284
285     def delete_model(self, request, obj):
286         # update openstack connection to use this site/tenant
287         auth = request.session.get('auth', {})
288         auth['tenant'] = obj.slice.name
289         obj.os_manager = OpenStackManager(auth=auth, caller=request.user)
290         obj.delete()
291
292 class UserCreationForm(forms.ModelForm):
293     """A form for creating new users. Includes all the required
294     fields, plus a repeated password."""
295     password1 = forms.CharField(label='Password', widget=forms.PasswordInput)
296     password2 = forms.CharField(label='Password confirmation', widget=forms.PasswordInput)
297
298     class Meta:
299         model = PLUser
300         fields = ('email', 'firstname', 'lastname', 'phone', 'site')
301
302     def clean_password2(self):
303         # Check that the two password entries match
304         password1 = self.cleaned_data.get("password1")
305         password2 = self.cleaned_data.get("password2")
306         if password1 and password2 and password1 != password2:
307             raise forms.ValidationError("Passwords don't match")
308         return password2
309
310     def save(self, commit=True):
311         # Save the provided password in hashed format
312         user = super(UserCreationForm, self).save(commit=False)
313         user.password = self.cleaned_data["password1"]
314         #user.set_password(self.cleaned_data["password1"])
315         if commit:
316             user.save()
317         return user
318
319
320 class UserChangeForm(forms.ModelForm):
321     """A form for updating users. Includes all the fields on
322     the user, but replaces the password field with admin's
323     password hash display field.
324     """
325     password = ReadOnlyPasswordHashField()
326
327     class Meta:
328         model = PLUser
329
330     def clean_password(self):
331         # Regardless of what the user provides, return the initial value.
332         # This is done here, rather than on the field, because the
333         # field does not have access to the initial value
334         return self.initial["password"]
335
336
337 class PLUserAdmin(UserAdmin, OSModelAdmin):
338     class Meta:
339         app_label = "core"
340
341     # The forms to add and change user instances
342     form = UserChangeForm
343     add_form = UserCreationForm
344
345     # The fields to be used in displaying the User model.
346     # These override the definitions on the base UserAdmin
347     # that reference specific fields on auth.User.
348     list_display = ('email', 'site', 'firstname', 'lastname', 'last_login')
349     list_filter = ('site',)
350     fieldsets = (
351         (None, {'fields': ('email', 'password')}),
352         ('Personal info', {'fields': ('firstname','lastname','phone','site')}),
353         #('Important dates', {'fields': ('last_login',)}),
354     )
355     add_fieldsets = (
356         (None, {
357             'classes': ('wide',),
358             'fields': ('email', 'firstname', 'lastname', 'phone', 'site', 'password1', 'password2')}
359         ),
360     )
361     search_fields = ('email',)
362     ordering = ('email',)
363     filter_horizontal = ()
364
365 # register a signal that caches the user's credentials when they log in
366 def cache_credentials(sender, user, request, **kwds):
367     auth = {'username': request.POST['username'],
368             'password': request.POST['password']}
369     request.session['auth'] = auth
370 user_logged_in.connect(cache_credentials)
371
372 # Now register the new UserAdmin...
373 admin.site.register(PLUser, PLUserAdmin)
374 # ... and, since we're not using Django's builtin permissions,
375 # unregister the Group model from admin.
376 admin.site.unregister(Group)
377
378 admin.site.register(Site, SiteAdmin)
379 admin.site.register(SitePrivilege, SitePrivilegeAdmin)
380 admin.site.register(Slice, SliceAdmin)
381 admin.site.register(SliceMembership, SliceMembershipAdmin)
382 admin.site.register(Subnet, SubnetAdmin)
383 admin.site.register(Image, ImageAdmin)
384 admin.site.register(Node, NodeAdmin)
385 admin.site.register(Sliver, SliverAdmin)
386 admin.site.register(Key, KeyAdmin)
387 admin.site.register(Role, RoleAdmin)
388 admin.site.register(DeploymentNetwork, DeploymentNetworkAdmin)
389