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.Widget):
57 def render(self, _name, value, attrs):
58 return mark_safe(value) if value is not None else ''
60 class PlanetStackBaseAdmin(admin.ModelAdmin):
63 class OSModelAdmin(PlanetStackBaseAdmin):
64 """Attach client connection to openstack on delete() and save()"""
66 def save_model(self, request, obj, form, change):
67 auth = request.session.get('auth', {})
68 auth['tenant'] = request.user.site.login_base
69 obj.os_manager = OpenStackManager(auth=auth, caller=request.user)
72 def delete_model(self, request, obj):
73 auth = request.session.get('auth', {})
74 auth['tenant'] = request.user.site.login_base
75 obj.os_manager = OpenStackManager(auth=auth, caller=request.user)
78 class RoleAdmin(OSModelAdmin):
80 ('Role', {'fields': ['role_type']})
82 list_display = ('role_type',)
85 class DeploymentNetworkAdminForm(forms.ModelForm):
86 sites = forms.ModelMultipleChoiceField(
87 queryset=Site.objects.all(),
89 widget=FilteredSelectMultiple(
90 verbose_name=('Sites'), is_stacked=False
94 model = DeploymentNetwork
96 def __init__(self, *args, **kwargs):
97 super(DeploymentNetworkAdminForm, self).__init__(*args, **kwargs)
99 if self.instance and self.instance.pk:
100 self.fields['sites'].initial = self.instance.sites.all()
102 def save(self, commit=True):
103 deploymentNetwork = super(DeploymentNetworkAdminForm, self).save(commit=False)
105 deploymentNetwork.save()
107 if deploymentNetwork.pk:
108 deploymentNetwork.sites = self.cleaned_data['sites']
111 return deploymentNetwork
113 class DeploymentNetworkAdmin(PlanetStackBaseAdmin):
114 form = DeploymentNetworkAdminForm
115 inlines = [NodeInline,]
117 def get_formsets(self, request, obj=None):
118 for inline in self.get_inline_instances(request, obj):
119 # hide MyInline in the add view
122 # give inline object access to driver and caller
123 auth = request.session.get('auth', {})
124 auth['tenant'] = request.user.site.login_base
125 inline.model.os_manager = OpenStackManager(auth=auth, caller=request.user)
126 yield inline.get_formset(request, obj)
128 class SiteAdmin(OSModelAdmin):
130 (None, {'fields': ['name', 'site_url', 'enabled', 'is_public', 'login_base']}),
131 ('Location', {'fields': ['latitude', 'longitude']}),
132 ('Deployment Networks', {'fields': ['deployments']})
134 list_display = ('name', 'login_base','site_url', 'enabled')
135 filter_horizontal = ('deployments',)
136 inlines = [NodeInline,]
137 search_fields = ['name']
139 def get_formsets(self, request, obj=None):
140 for inline in self.get_inline_instances(request, obj):
141 # hide MyInline in the add view
144 # give inline object access to driver and caller
145 auth = request.session.get('auth', {})
146 auth['tenant'] = request.user.site.login_base
147 inline.model.os_manager = OpenStackManager(auth=auth, caller=request.user)
148 yield inline.get_formset(request, obj)
150 class SitePrivilegeAdmin(PlanetStackBaseAdmin):
152 (None, {'fields': ['user', 'site', 'role']})
154 list_display = ('user', 'site', 'role')
156 def save_model(self, request, obj, form, change):
157 # update openstack connection to use this site/tenant
158 auth = request.session.get('auth', {})
159 auth['tenant'] = obj.site.login_base
160 obj.os_manager = OpenStackManager(auth=auth, caller=request.user)
163 def delete_model(self, request, obj):
164 # update openstack connection to use this site/tenant
165 auth = request.session.get('auth', {})
166 auth['tenant'] = obj.site.login_base
167 obj.os_manager = OpenStackManager(auth=auth, caller=request.user)
170 class KeyAdmin(OSModelAdmin):
172 ('Key', {'fields': ['name', 'key', 'type', 'blacklisted', 'user']})
174 list_display = ['name', 'key', 'type', 'blacklisted', 'user']
176 def get_queryset(self, request):
177 # get keys user is allowed to see
178 qs = super(KeyAdmin, self).get_queryset(request)
179 if request.user.is_superuser:
181 # users can only see their own keys
182 return qs.filter(user=request.user)
185 class SliceAdmin(OSModelAdmin):
186 fields = ['name', 'site', 'serviceClass', 'instantiation', 'description', 'slice_url']
187 list_display = ('name', 'site','serviceClass', 'slice_url', 'instantiation')
188 inlines = [SliverInline]
190 def get_formsets(self, request, obj=None):
191 for inline in self.get_inline_instances(request, obj):
192 # hide MyInline in the add view
195 # give inline object access to driver and caller
196 auth = request.session.get('auth', {})
197 auth['tenant'] = obj.name # meed to connect using slice's tenant
198 inline.model.os_manager = OpenStackManager(auth=auth, caller=request.user)
199 yield inline.get_formset(request, obj)
201 def get_queryset(self, request):
202 qs = super(SliceAdmin, self).get_queryset(request)
203 if request.user.is_superuser:
205 # users can only see slices at their site
206 return qs.filter(site=request.user.site)
208 class SliceMembershipAdmin(PlanetStackBaseAdmin):
210 (None, {'fields': ['user', 'slice', 'role']})
212 list_display = ('user', 'slice', 'role')
214 def save_model(self, request, obj, form, change):
215 # update openstack connection to use this site/tenant
216 auth = request.session.get('auth', {})
217 auth['tenant'] = obj.slice.name
218 obj.os_manager = OpenStackManager(auth=auth, caller=request.user)
221 def delete_model(self, request, obj):
222 # update openstack connection to use this site/tenant
223 auth = request.session.get('auth', {})
224 auth['tenant'] = obj.slice.name
225 obj.os_manager = OpenStackManager(auth=auth, caller=request.user)
229 class SubnetAdmin(PlanetStackBaseAdmin):
230 fields = ['cidr', 'ip_version', 'start', 'end', 'slice']
231 list_display = ('slice','cidr', 'start', 'end', 'ip_version')
233 def save_model(self, request, obj, form, change):
234 # update openstack connection to use this site/tenant
235 auth = request.session.get('auth', {})
236 auth['tenant'] = obj.slice.name
237 obj.os_manager = OpenStackManager(auth=auth, caller=request.user)
240 def delete_model(self, request, obj):
241 # update openstack connection to use this site/tenant
242 auth = request.session.get('auth', {})
243 auth['tenant'] = obj.slice.name
244 obj.os_manager = OpenStackManager(auth=auth, caller=request.user)
247 class ImageAdmin(admin.ModelAdmin):
248 fields = ['image_id', 'name', 'disk_format', 'container_format']
250 class NodeAdmin(admin.ModelAdmin):
251 list_display = ('name', 'site', 'deploymentNetwork')
252 list_filter = ('deploymentNetwork',)
255 class SliverForm(forms.ModelForm):
257 ip = forms.CharField(widget=PlainTextWidget)
258 instance_name = forms.CharField(widget=PlainTextWidget)
261 'ip': PlainTextWidget(),
262 'instance_name': PlainTextWidget(),
265 class SliverAdmin(PlanetStackBaseAdmin):
268 ('Sliver', {'fields': ['ip', 'instance_name', 'name', 'slice', 'numberCores', 'image', 'key', 'node', 'deploymentNetwork']})
270 list_display = ['ip', 'instance_name', 'name', 'slice', 'numberCores', 'image', 'key', 'node', 'deploymentNetwork']
272 def save_model(self, request, obj, form, change):
273 # update openstack connection to use this site/tenant
274 auth = request.session.get('auth', {})
275 auth['tenant'] = obj.slice.name
276 obj.os_manager = OpenStackManager(auth=auth, caller=request.user)
279 def delete_model(self, request, obj):
280 # update openstack connection to use this site/tenant
281 auth = request.session.get('auth', {})
282 auth['tenant'] = obj.slice.name
283 obj.os_manager = OpenStackManager(auth=auth, caller=request.user)
286 class UserCreationForm(forms.ModelForm):
287 """A form for creating new users. Includes all the required
288 fields, plus a repeated password."""
289 password1 = forms.CharField(label='Password', widget=forms.PasswordInput)
290 password2 = forms.CharField(label='Password confirmation', widget=forms.PasswordInput)
294 fields = ('email', 'firstname', 'lastname', 'phone', 'site')
296 def clean_password2(self):
297 # Check that the two password entries match
298 password1 = self.cleaned_data.get("password1")
299 password2 = self.cleaned_data.get("password2")
300 if password1 and password2 and password1 != password2:
301 raise forms.ValidationError("Passwords don't match")
304 def save(self, commit=True):
305 # Save the provided password in hashed format
306 user = super(UserCreationForm, self).save(commit=False)
307 user.password = self.cleaned_data["password1"]
308 #user.set_password(self.cleaned_data["password1"])
314 class UserChangeForm(forms.ModelForm):
315 """A form for updating users. Includes all the fields on
316 the user, but replaces the password field with admin's
317 password hash display field.
319 password = ReadOnlyPasswordHashField()
324 def clean_password(self):
325 # Regardless of what the user provides, return the initial value.
326 # This is done here, rather than on the field, because the
327 # field does not have access to the initial value
328 return self.initial["password"]
331 class PLUserAdmin(UserAdmin, OSModelAdmin):
335 # The forms to add and change user instances
336 form = UserChangeForm
337 add_form = UserCreationForm
339 # The fields to be used in displaying the User model.
340 # These override the definitions on the base UserAdmin
341 # that reference specific fields on auth.User.
342 list_display = ('email', 'site', 'firstname', 'lastname', 'last_login')
343 list_filter = ('site',)
345 (None, {'fields': ('email', 'password')}),
346 ('Personal info', {'fields': ('firstname','lastname','phone','site')}),
347 #('Important dates', {'fields': ('last_login',)}),
351 'classes': ('wide',),
352 'fields': ('email', 'firstname', 'lastname', 'phone', 'site', 'password1', 'password2')}
355 search_fields = ('email',)
356 ordering = ('email',)
357 filter_horizontal = ()
359 # register a signal that caches the user's credentials when they log in
360 def cache_credentials(sender, user, request, **kwds):
361 auth = {'username': request.POST['username'],
362 'password': request.POST['password']}
363 request.session['auth'] = auth
364 user_logged_in.connect(cache_credentials)
366 # Now register the new UserAdmin...
367 admin.site.register(PLUser, PLUserAdmin)
368 # ... and, since we're not using Django's builtin permissions,
369 # unregister the Group model from admin.
370 admin.site.unregister(Group)
372 admin.site.register(Site, SiteAdmin)
373 admin.site.register(SitePrivilege, SitePrivilegeAdmin)
374 admin.site.register(Slice, SliceAdmin)
375 admin.site.register(SliceMembership, SliceMembershipAdmin)
376 admin.site.register(Subnet, SubnetAdmin)
377 admin.site.register(Image, ImageAdmin)
378 admin.site.register(Node, NodeAdmin)
379 admin.site.register(Sliver, SliverAdmin)
380 admin.site.register(Key, KeyAdmin)
381 admin.site.register(Role, RoleAdmin)
382 admin.site.register(DeploymentNetwork, DeploymentNetworkAdmin)