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(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)
191 class SliceAdmin(OSModelAdmin):
192 fields = ['name', 'site', 'serviceClass', 'description', 'slice_url']
193 list_display = ('name', 'site','serviceClass', 'slice_url')
194 inlines = [SliverInline]
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
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)
207 def get_queryset(self, request):
208 qs = super(SliceAdmin, self).get_queryset(request)
209 if request.user.is_superuser:
211 # users can only see slices at their site
212 return qs.filter(site=request.user.site)
214 class SliceMembershipAdmin(PlanetStackBaseAdmin):
216 (None, {'fields': ['user', 'slice', 'role']})
218 list_display = ('user', 'slice', 'role')
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)
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)
235 class SubnetAdmin(PlanetStackBaseAdmin):
236 fields = ['cidr', 'ip_version', 'start', 'end', 'slice']
237 list_display = ('slice','cidr', 'start', 'end', 'ip_version')
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)
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)
253 class ImageAdmin(admin.ModelAdmin):
254 fields = ['image_id', 'name', 'disk_format', 'container_format']
256 class NodeAdmin(admin.ModelAdmin):
257 list_display = ('name', 'site', 'deploymentNetwork')
258 list_filter = ('deploymentNetwork',)
261 class SliverForm(forms.ModelForm):
263 ip = forms.CharField(widget=PlainTextWidget)
264 instance_name = forms.CharField(widget=PlainTextWidget)
267 'ip': PlainTextWidget(),
268 'instance_name': PlainTextWidget(),
271 class SliverAdmin(PlanetStackBaseAdmin):
274 ('Sliver', {'fields': ['ip', 'instance_name', 'name', 'slice', 'numberCores', 'image', 'key', 'node', 'deploymentNetwork']})
276 list_display = ['ip', 'instance_name', 'name', 'slice', 'numberCores', 'image', 'key', 'node', 'deploymentNetwork']
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)
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)
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)
300 fields = ('email', 'firstname', 'lastname', 'phone', 'site')
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")
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"])
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.
325 password = ReadOnlyPasswordHashField()
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"]
337 class PLUserAdmin(UserAdmin, OSModelAdmin):
341 # The forms to add and change user instances
342 form = UserChangeForm
343 add_form = UserCreationForm
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',)
351 (None, {'fields': ('email', 'password')}),
352 ('Personal info', {'fields': ('firstname','lastname','phone','site')}),
353 #('Important dates', {'fields': ('last_login',)}),
357 'classes': ('wide',),
358 'fields': ('email', 'firstname', 'lastname', 'phone', 'site', 'password1', 'password2')}
361 search_fields = ('email',)
362 ordering = ('email',)
363 filter_horizontal = ()
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)
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)
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)