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):
71 auth = request.session.get('auth', {})
72 auth['tenant'] = request.user.site.login_base
73 obj.os_manager = OpenStackManager(auth=auth, caller=request.user)
76 def delete_model(self, request, obj):
77 auth = request.session.get('auth', {})
78 auth['tenant'] = request.user.site.login_base
79 obj.os_manager = OpenStackManager(auth=auth, caller=request.user)
82 class RoleAdmin(OSModelAdmin):
84 ('Role', {'fields': ['role_type']})
86 list_display = ('role_type',)
89 class DeploymentNetworkAdminForm(forms.ModelForm):
90 sites = forms.ModelMultipleChoiceField(
91 queryset=Site.objects.all(),
93 widget=FilteredSelectMultiple(
94 verbose_name=('Sites'), is_stacked=False
98 model = DeploymentNetwork
100 def __init__(self, *args, **kwargs):
101 super(DeploymentNetworkAdminForm, self).__init__(*args, **kwargs)
103 if self.instance and self.instance.pk:
104 self.fields['sites'].initial = self.instance.sites.all()
106 def save(self, commit=True):
107 deploymentNetwork = super(DeploymentNetworkAdminForm, self).save(commit=False)
109 deploymentNetwork.save()
111 if deploymentNetwork.pk:
112 deploymentNetwork.sites = self.cleaned_data['sites']
115 return deploymentNetwork
117 class DeploymentNetworkAdmin(PlanetStackBaseAdmin):
118 form = DeploymentNetworkAdminForm
119 inlines = [NodeInline,]
121 def get_formsets(self, request, obj=None):
122 for inline in self.get_inline_instances(request, obj):
123 # hide MyInline in the add view
126 # give inline object access to driver and caller
127 auth = request.session.get('auth', {})
128 auth['tenant'] = request.user.site.login_base
129 inline.model.os_manager = OpenStackManager(auth=auth, caller=request.user)
130 yield inline.get_formset(request, obj)
132 class SiteAdmin(OSModelAdmin):
134 (None, {'fields': ['name', 'site_url', 'enabled', 'is_public', 'login_base']}),
135 ('Location', {'fields': ['latitude', 'longitude']}),
136 ('Deployment Networks', {'fields': ['deployments']})
138 list_display = ('name', 'login_base','site_url', 'enabled')
139 filter_horizontal = ('deployments',)
140 inlines = [NodeInline,]
141 search_fields = ['name']
143 def get_formsets(self, request, obj=None):
144 for inline in self.get_inline_instances(request, obj):
145 # hide MyInline in the add view
148 # give inline object access to driver and caller
149 auth = request.session.get('auth', {})
150 auth['tenant'] = request.user.site.login_base
151 inline.model.os_manager = OpenStackManager(auth=auth, caller=request.user)
152 yield inline.get_formset(request, obj)
154 class SitePrivilegeAdmin(PlanetStackBaseAdmin):
156 (None, {'fields': ['user', 'site', 'role']})
158 list_display = ('user', 'site', 'role')
160 def save_model(self, request, obj, form, change):
161 # update openstack connection to use this site/tenant
162 auth = request.session.get('auth', {})
163 auth['tenant'] = obj.site.login_base
164 obj.os_manager = OpenStackManager(auth=auth, caller=request.user)
167 def delete_model(self, request, obj):
168 # update openstack connection to use this site/tenant
169 auth = request.session.get('auth', {})
170 auth['tenant'] = obj.site.login_base
171 obj.os_manager = OpenStackManager(auth=auth, caller=request.user)
174 class KeyAdmin(OSModelAdmin):
176 ('Key', {'fields': ['name', 'key', 'type', 'blacklisted', 'user']})
178 list_display = ['name', 'key', 'type', 'blacklisted', 'user']
180 def get_queryset(self, request):
181 # get keys user is allowed to see
182 qs = super(KeyAdmin, self).get_queryset(request)
183 if request.user.is_superuser:
185 # users can only see their own keys
186 return qs.filter(user=request.user)
189 class SliceAdmin(OSModelAdmin):
190 fields = ['name', 'site', 'serviceClass', 'instantiation', 'description', 'slice_url']
191 list_display = ('name', 'site','serviceClass', 'slice_url', 'instantiation')
192 inlines = [SliverInline]
194 def get_formsets(self, request, obj=None):
195 for inline in self.get_inline_instances(request, obj):
196 # hide MyInline in the add view
199 # give inline object access to driver and caller
200 auth = request.session.get('auth', {})
201 auth['tenant'] = obj.name # meed to connect using slice's tenant
202 inline.model.os_manager = OpenStackManager(auth=auth, caller=request.user)
203 yield inline.get_formset(request, obj)
205 def get_queryset(self, request):
206 qs = super(SliceAdmin, self).get_queryset(request)
207 if request.user.is_superuser:
209 # users can only see slices at their site
210 return qs.filter(site=request.user.site)
212 class SliceMembershipAdmin(PlanetStackBaseAdmin):
214 (None, {'fields': ['user', 'slice', 'role']})
216 list_display = ('user', 'slice', 'role')
218 def save_model(self, request, obj, form, change):
219 # update openstack connection to use this site/tenant
220 auth = request.session.get('auth', {})
221 auth['tenant'] = obj.slice.name
222 obj.os_manager = OpenStackManager(auth=auth, caller=request.user)
225 def delete_model(self, request, obj):
226 # update openstack connection to use this site/tenant
227 auth = request.session.get('auth', {})
228 auth['tenant'] = obj.slice.name
229 obj.os_manager = OpenStackManager(auth=auth, caller=request.user)
233 class SubnetAdmin(PlanetStackBaseAdmin):
234 fields = ['cidr', 'ip_version', 'start', 'end', 'slice']
235 list_display = ('slice','cidr', 'start', 'end', 'ip_version')
237 def save_model(self, request, obj, form, change):
238 # update openstack connection to use this site/tenant
239 auth = request.session.get('auth', {})
240 auth['tenant'] = obj.slice.name
241 obj.os_manager = OpenStackManager(auth=auth, caller=request.user)
244 def delete_model(self, request, obj):
245 # update openstack connection to use this site/tenant
246 auth = request.session.get('auth', {})
247 auth['tenant'] = obj.slice.name
248 obj.os_manager = OpenStackManager(auth=auth, caller=request.user)
251 class ImageAdmin(admin.ModelAdmin):
252 fields = ['image_id', 'name', 'disk_format', 'container_format']
254 class NodeAdmin(admin.ModelAdmin):
255 list_display = ('name', 'site', 'deploymentNetwork')
256 list_filter = ('deploymentNetwork',)
259 class SliverForm(forms.ModelForm):
261 ip = forms.CharField(widget=PlainTextWidget)
262 instance_name = forms.CharField(widget=PlainTextWidget)
265 'ip': PlainTextWidget(),
266 'instance_name': PlainTextWidget(),
269 class SliverAdmin(PlanetStackBaseAdmin):
272 ('Sliver', {'fields': ['ip', 'instance_name', 'name', 'slice', 'numberCores', 'image', 'key', 'node', 'deploymentNetwork']})
274 list_display = ['ip', 'instance_name', 'name', 'slice', 'numberCores', 'image', 'key', 'node', 'deploymentNetwork']
276 def save_model(self, request, obj, form, change):
277 # update openstack connection to use this site/tenant
278 auth = request.session.get('auth', {})
279 auth['tenant'] = obj.slice.name
280 obj.os_manager = OpenStackManager(auth=auth, caller=request.user)
283 def delete_model(self, request, obj):
284 # update openstack connection to use this site/tenant
285 auth = request.session.get('auth', {})
286 auth['tenant'] = obj.slice.name
287 obj.os_manager = OpenStackManager(auth=auth, caller=request.user)
290 class UserCreationForm(forms.ModelForm):
291 """A form for creating new users. Includes all the required
292 fields, plus a repeated password."""
293 password1 = forms.CharField(label='Password', widget=forms.PasswordInput)
294 password2 = forms.CharField(label='Password confirmation', widget=forms.PasswordInput)
298 fields = ('email', 'firstname', 'lastname', 'phone', 'site')
300 def clean_password2(self):
301 # Check that the two password entries match
302 password1 = self.cleaned_data.get("password1")
303 password2 = self.cleaned_data.get("password2")
304 if password1 and password2 and password1 != password2:
305 raise forms.ValidationError("Passwords don't match")
308 def save(self, commit=True):
309 # Save the provided password in hashed format
310 user = super(UserCreationForm, self).save(commit=False)
311 user.password = self.cleaned_data["password1"]
312 #user.set_password(self.cleaned_data["password1"])
318 class UserChangeForm(forms.ModelForm):
319 """A form for updating users. Includes all the fields on
320 the user, but replaces the password field with admin's
321 password hash display field.
323 password = ReadOnlyPasswordHashField()
328 def clean_password(self):
329 # Regardless of what the user provides, return the initial value.
330 # This is done here, rather than on the field, because the
331 # field does not have access to the initial value
332 return self.initial["password"]
335 class PLUserAdmin(UserAdmin, OSModelAdmin):
339 # The forms to add and change user instances
340 form = UserChangeForm
341 add_form = UserCreationForm
343 # The fields to be used in displaying the User model.
344 # These override the definitions on the base UserAdmin
345 # that reference specific fields on auth.User.
346 list_display = ('email', 'site', 'firstname', 'lastname', 'last_login')
347 list_filter = ('site',)
349 (None, {'fields': ('email', 'password')}),
350 ('Personal info', {'fields': ('firstname','lastname','phone','site')}),
351 #('Important dates', {'fields': ('last_login',)}),
355 'classes': ('wide',),
356 'fields': ('email', 'firstname', 'lastname', 'phone', 'site', 'password1', 'password2')}
359 search_fields = ('email',)
360 ordering = ('email',)
361 filter_horizontal = ()
363 # register a signal that caches the user's credentials when they log in
364 def cache_credentials(sender, user, request, **kwds):
365 auth = {'username': request.POST['username'],
366 'password': request.POST['password']}
367 request.session['auth'] = auth
368 user_logged_in.connect(cache_credentials)
370 # Now register the new UserAdmin...
371 admin.site.register(PLUser, PLUserAdmin)
372 # ... and, since we're not using Django's builtin permissions,
373 # unregister the Group model from admin.
374 admin.site.unregister(Group)
376 admin.site.register(Site, SiteAdmin)
377 admin.site.register(SitePrivilege, SitePrivilegeAdmin)
378 admin.site.register(Slice, SliceAdmin)
379 admin.site.register(SliceMembership, SliceMembershipAdmin)
380 admin.site.register(Subnet, SubnetAdmin)
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)