1 from plstackapi.core.models import Site
2 from plstackapi.core.models import *
3 from plstackapi.openstack.manager import OpenStackManager
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
15 class ReadonlyTabularInline(admin.TabularInline):
20 def get_readonly_fields(self, request, obj=None):
22 for field in self.model._meta.get_all_field_names():
23 if (not field == 'id'):
24 if (field not in self.editable_fields):
28 def has_add_permission(self, request):
31 class SliverInline(admin.TabularInline):
33 fields = ['ip', 'name', 'slice', 'numberCores', 'image', 'key', 'node', 'deploymentNetwork']
36 class SiteInline(admin.TabularInline):
40 class SliceInline(admin.TabularInline):
44 class UserInline(admin.TabularInline):
48 class RoleInline(admin.TabularInline):
52 class NodeInline(admin.TabularInline):
56 class PlainTextWidget(forms.HiddenInput):
59 def render(self, name, value, attrs=None):
62 return mark_safe(str(value) + super(PlainTextWidget, self).render(name, value, attrs))
64 class PlanetStackBaseAdmin(admin.ModelAdmin):
67 class OSModelAdmin(PlanetStackBaseAdmin):
68 """Attach client connection to openstack on delete() and save()"""
70 def save_model(self, request, obj, form, change):
72 auth = request.session.get('auth', {})
73 auth['tenant'] = request.user.site.login_base
74 obj.os_manager = OpenStackManager(auth=auth, caller=request.user)
77 def delete_model(self, request, obj):
79 auth = request.session.get('auth', {})
80 auth['tenant'] = request.user.site.login_base
81 obj.os_manager = OpenStackManager(auth=auth, caller=request.user)
84 class RoleAdmin(OSModelAdmin):
86 ('Role', {'fields': ['role_type']})
88 list_display = ('role_type',)
91 class DeploymentNetworkAdminForm(forms.ModelForm):
92 sites = forms.ModelMultipleChoiceField(
93 queryset=Site.objects.all(),
95 widget=FilteredSelectMultiple(
96 verbose_name=('Sites'), is_stacked=False
100 model = DeploymentNetwork
102 def __init__(self, *args, **kwargs):
103 super(DeploymentNetworkAdminForm, self).__init__(*args, **kwargs)
105 if self.instance and self.instance.pk:
106 self.fields['sites'].initial = self.instance.sites.all()
108 def save(self, commit=True):
109 deploymentNetwork = super(DeploymentNetworkAdminForm, self).save(commit=False)
111 deploymentNetwork.save()
113 if deploymentNetwork.pk:
114 deploymentNetwork.sites = self.cleaned_data['sites']
117 return deploymentNetwork
119 class DeploymentNetworkAdmin(PlanetStackBaseAdmin):
120 form = DeploymentNetworkAdminForm
121 inlines = [NodeInline,]
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
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)
134 class SiteAdmin(OSModelAdmin):
136 (None, {'fields': ['name', 'site_url', 'enabled', 'is_public', 'login_base']}),
137 ('Location', {'fields': ['latitude', 'longitude']}),
138 ('Deployment Networks', {'fields': ['deployments']})
140 list_display = ('name', 'login_base','site_url', 'enabled')
141 filter_horizontal = ('deployments',)
142 inlines = [NodeInline,]
143 search_fields = ['name']
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
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)
156 class SitePrivilegeAdmin(PlanetStackBaseAdmin):
158 (None, {'fields': ['user', 'site', 'role']})
160 list_display = ('user', 'site', 'role')
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)
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)
176 class KeyAdmin(OSModelAdmin):
178 ('Key', {'fields': ['name', 'key', 'type', 'blacklisted', 'user']})
180 list_display = ['name', 'key', 'type', 'blacklisted', 'user']
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:
187 # users can only see their own keys
188 return qs.filter(user=request.user)
190 class SliceAdmin(OSModelAdmin):
191 fields = ['name', 'site', 'serviceClass', 'description', 'slice_url']
192 list_display = ('name', 'site','serviceClass', 'slice_url')
193 inlines = [SliverInline]
195 def get_formsets(self, request, obj=None):
196 for inline in self.get_inline_instances(request, obj):
197 # hide MyInline in the add view
200 # give inline object access to driver and caller
201 auth = request.session.get('auth', {})
202 auth['tenant'] = obj.name # meed to connect using slice's tenant
203 inline.model.os_manager = OpenStackManager(auth=auth, caller=request.user)
204 yield inline.get_formset(request, obj)
206 def get_queryset(self, request):
207 qs = super(SliceAdmin, self).get_queryset(request)
208 if request.user.is_superuser:
210 # users can only see slices at their site
211 return qs.filter(site=request.user.site)
213 class SliceMembershipAdmin(PlanetStackBaseAdmin):
215 (None, {'fields': ['user', 'slice', 'role']})
217 list_display = ('user', 'slice', 'role')
219 def save_model(self, request, obj, form, change):
220 # update openstack connection to use this site/tenant
221 auth = request.session.get('auth', {})
222 auth['tenant'] = obj.slice.name
223 obj.os_manager = OpenStackManager(auth=auth, caller=request.user)
226 def delete_model(self, request, obj):
227 # update openstack connection to use this site/tenant
228 auth = request.session.get('auth', {})
229 auth['tenant'] = obj.slice.name
230 obj.os_manager = OpenStackManager(auth=auth, caller=request.user)
234 class ImageAdmin(admin.ModelAdmin):
235 fields = ['image_id', 'name', 'disk_format', 'container_format']
237 class NodeAdmin(admin.ModelAdmin):
238 list_display = ('name', 'site', 'deploymentNetwork')
239 list_filter = ('deploymentNetwork',)
242 class SliverForm(forms.ModelForm):
245 ip = forms.CharField(widget=PlainTextWidget)
246 instance_name = forms.CharField(widget=PlainTextWidget)
248 'ip': PlainTextWidget(),
249 'instance_name': PlainTextWidget(),
252 class SliverAdmin(PlanetStackBaseAdmin):
255 ('Sliver', {'fields': ['ip', 'instance_name', 'slice', 'numberCores', 'image', 'key', 'node', 'deploymentNetwork']})
257 list_display = ['ip', 'instance_name', 'slice', 'numberCores', 'image', 'key', 'node', 'deploymentNetwork']
259 def get_formsets(self, request, obj=None):
260 # make some fields read only if we are updating an existing record
262 #self.readonly_fields = ('ip', 'instance_name')
263 self.readonly_fields = ()
265 self.readonly_fields = ('ip', 'instance_name', 'slice', 'image', 'key')
267 for inline in self.get_inline_instances(request, obj):
268 # hide MyInline in the add view
271 # give inline object access to driver and caller
272 auth = request.session.get('auth', {})
273 auth['tenant'] = obj.name # meed to connect using slice's tenant
274 inline.model.os_manager = OpenStackManager(auth=auth, caller=request.user)
275 yield inline.get_formset(request, obj)
277 def save_model(self, request, obj, form, change):
278 # update openstack connection to use this site/tenant
279 auth = request.session.get('auth', {})
280 auth['tenant'] = obj.slice.name
281 obj.os_manager = OpenStackManager(auth=auth, caller=request.user)
284 def delete_model(self, request, obj):
285 # update openstack connection to use this site/tenant
286 auth = request.session.get('auth', {})
287 auth['tenant'] = obj.slice.name
288 obj.os_manager = OpenStackManager(auth=auth, caller=request.user)
291 class UserCreationForm(forms.ModelForm):
292 """A form for creating new users. Includes all the required
293 fields, plus a repeated password."""
294 password1 = forms.CharField(label='Password', widget=forms.PasswordInput)
295 password2 = forms.CharField(label='Password confirmation', widget=forms.PasswordInput)
299 fields = ('email', 'firstname', 'lastname', 'phone', 'site')
301 def clean_password2(self):
302 # Check that the two password entries match
303 password1 = self.cleaned_data.get("password1")
304 password2 = self.cleaned_data.get("password2")
305 if password1 and password2 and password1 != password2:
306 raise forms.ValidationError("Passwords don't match")
309 def save(self, commit=True):
310 # Save the provided password in hashed format
311 user = super(UserCreationForm, self).save(commit=False)
312 user.password = self.cleaned_data["password1"]
313 #user.set_password(self.cleaned_data["password1"])
319 class UserChangeForm(forms.ModelForm):
320 """A form for updating users. Includes all the fields on
321 the user, but replaces the password field with admin's
322 password hash display field.
324 password = ReadOnlyPasswordHashField()
329 def clean_password(self):
330 # Regardless of what the user provides, return the initial value.
331 # This is done here, rather than on the field, because the
332 # field does not have access to the initial value
333 return self.initial["password"]
336 class PLUserAdmin(UserAdmin, OSModelAdmin):
340 # The forms to add and change user instances
341 form = UserChangeForm
342 add_form = UserCreationForm
344 # The fields to be used in displaying the User model.
345 # These override the definitions on the base UserAdmin
346 # that reference specific fields on auth.User.
347 list_display = ('email', 'site', 'firstname', 'lastname', 'last_login')
348 list_filter = ('site',)
350 (None, {'fields': ('email', 'password')}),
351 ('Personal info', {'fields': ('firstname','lastname','phone','site')}),
352 #('Important dates', {'fields': ('last_login',)}),
356 'classes': ('wide',),
357 'fields': ('email', 'firstname', 'lastname', 'phone', 'site', 'password1', 'password2')}
360 search_fields = ('email',)
361 ordering = ('email',)
362 filter_horizontal = ()
364 # register a signal that caches the user's credentials when they log in
365 def cache_credentials(sender, user, request, **kwds):
366 auth = {'username': request.POST['username'],
367 'password': request.POST['password']}
368 request.session['auth'] = auth
369 user_logged_in.connect(cache_credentials)
371 # Now register the new UserAdmin...
372 admin.site.register(PLUser, PLUserAdmin)
373 # ... and, since we're not using Django's builtin permissions,
374 # unregister the Group model from admin.
375 admin.site.unregister(Group)
377 admin.site.register(Site, SiteAdmin)
378 admin.site.register(SitePrivilege, SitePrivilegeAdmin)
379 admin.site.register(Slice, SliceAdmin)
380 admin.site.register(SliceMembership, SliceMembershipAdmin)
381 admin.site.register(Image, ImageAdmin)
382 admin.site.register(Node, NodeAdmin)
383 admin.site.register(Sliver, SliverAdmin)
384 admin.site.register(Key, KeyAdmin)
385 admin.site.register(Role, RoleAdmin)
386 admin.site.register(DeploymentNetwork, DeploymentNetworkAdmin)