1 from plstackapi.core.models import Site
2 from plstackapi.core.models import *
3 from plstackapi.openstack.driver import OpenStackDriver
4 from plstackapi.openstack.client import OpenStackClient
6 from django.contrib import admin
7 from django.contrib.auth.models import Group
8 from django import forms
9 from django.utils.safestring import mark_safe
10 from django.contrib.auth.admin import UserAdmin
11 from django.contrib.admin.widgets import FilteredSelectMultiple
12 from django.contrib.auth.forms import ReadOnlyPasswordHashField
13 from django.contrib.auth.signals import user_logged_in
16 class ReadonlyTabularInline(admin.TabularInline):
21 def get_readonly_fields(self, request, obj=None):
23 for field in self.model._meta.get_all_field_names():
24 if (not field == 'id'):
25 if (field not in self.editable_fields):
29 def has_add_permission(self, request):
32 class SliverInline(admin.TabularInline):
34 fields = ['ip', 'name', 'slice', 'image', 'key', 'node', 'deploymentNetwork']
37 class SiteInline(admin.TabularInline):
41 class SliceInline(admin.TabularInline):
45 class UserInline(admin.TabularInline):
49 class RoleInline(admin.TabularInline):
53 class NodeInline(admin.TabularInline):
57 class PlainTextWidget(forms.Widget):
58 def render(self, _name, value, attrs):
59 return mark_safe(value) if value is not None else ''
61 class PlanetStackBaseAdmin(admin.ModelAdmin):
64 class OSModelAdmin(PlanetStackBaseAdmin):
65 """Attach client connection to openstack on delete() and save()"""
67 def save_model(self, request, obj, form, change):
68 client = OpenStackClient(tenant=request.user.site.login_base, **request.session.get('auth', {}))
69 obj.driver = OpenStackDriver(client=client)
70 obj.caller = request.user
73 def delete_model(self, request, obj):
74 client = OpenStackClient(tenant=request.user.site.login_base, **request.session.get('auth', {}))
75 obj.driver = OpenStackDriver(client=client)
76 obj.caller = request.user
79 class RoleAdmin(OSModelAdmin):
81 ('Role', {'fields': ['role_type']})
83 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 class SiteAdmin(OSModelAdmin):
119 (None, {'fields': ['name', 'site_url', 'enabled', 'is_public', 'login_base']}),
120 ('Location', {'fields': ['latitude', 'longitude']}),
121 ('Deployment Networks', {'fields': ['deployments']})
123 list_display = ('name', 'login_base','site_url', 'enabled')
124 filter_horizontal = ('deployments',)
125 inlines = [NodeInline,]
126 search_fields = ['name']
128 class SitePrivilegeAdmin(PlanetStackBaseAdmin):
130 (None, {'fields': ['user', 'site', 'role']})
132 list_display = ('user', 'site', 'role')
134 def save_model(self, request, obj, form, change):
135 # update openstack connection to use this site/tenant
136 client = OpenStackClient(tenant=obj.site.login_base, **request.session.get('auth', {}))
137 obj.driver = OpenStackDriver(client=client)
138 obj.caller = request.user
141 def delete_model(self, request, obj):
142 # update openstack connection to use this site/tenant
143 client = OpenStackClient(tenant=obj.site.login_base, **request.session.get('auth', {}))
144 obj.driver = OpenStackDriver(client=client)
145 obj.caller = request.user
148 class KeyAdmin(OSModelAdmin):
150 ('Key', {'fields': ['name', 'key', 'type', 'blacklisted', 'user']})
152 list_display = ['name', 'key', 'type', 'blacklisted', 'user']
154 def get_queryset(self, request):
155 # get keys user is allowed to see
156 qs = super(KeyAdmin, self).get_queryset(request)
157 if request.user.is_superuser:
159 # users can only see their own keys
160 return qs.filter(user=request.user)
163 class SliceAdmin(OSModelAdmin):
164 fields = ['name', 'site', 'instantiation', 'description', 'slice_url']
165 list_display = ('name', 'site','slice_url', 'instantiation')
166 inlines = [SliverInline]
168 def get_formsets(self, request, obj=None):
169 for inline in self.get_inline_instances(request, obj):
170 # hide MyInline in the add view
173 # give inline object access to driver and caller
174 client = OpenStackClient(tenant=obj.name, **request.session.get('auth', {}))
175 inline.model.driver = OpenStackDriver(client=client)
176 inline.model.caller = request.user
177 yield inline.get_formset(request, obj)
179 def get_queryset(self, request):
180 qs = super(SliceAdmin, self).get_queryset(request)
181 if request.user.is_superuser:
183 # users can only see slices at their site
184 return qs.filter(site=request.user.site)
186 class SliceMembershipAdmin(PlanetStackBaseAdmin):
188 (None, {'fields': ['user', 'slice', 'role']})
190 list_display = ('user', 'slice', 'role')
192 def save_model(self, request, obj, form, change):
193 # update openstack connection to use this slice/tenant
194 client = OpenStackClient(tenant=obj.slice.name, **request.session.get('auth', {}))
195 obj.driver = OpenStackDriver(client=client)
196 obj.caller = request.user
199 def delete_model(self, request, obj):
200 # update openstack connection to use this slice/tenant
201 client = OpenStackClient(tenant=obj.slice.name, **request.session.get('auth', {}))
202 obj.driver = OpenStackDriver(client=client)
203 obj.caller = request.user
206 class SubnetAdmin(PlanetStackBaseAdmin):
207 fields = ['cidr', 'ip_version', 'start', 'end', 'slice']
208 list_display = ('slice','cidr', 'start', 'end', 'ip_version')
210 def save_model(self, request, obj, form, change):
211 # update openstack connection to use this subnet's slice/tenant
212 client = OpenStackClient(tenant=obj.slice.name, **request.session.get('auth', {}))
213 obj.driver = OpenStackDriver(client=client)
214 obj.caller = request.user
217 def delete_model(self, request, obj):
218 # update openstack connection to use this subnet's slice/tenant
219 client = OpenStackClient(tenant=obj.slice.name, **request.session.get('auth', {}))
220 obj.driver = OpenStackDriver(client=client)
221 obj.caller = request.user
224 class ImageAdmin(admin.ModelAdmin):
225 fields = ['image_id', 'name', 'disk_format', 'container_format']
227 class NodeAdmin(admin.ModelAdmin):
228 list_display = ('name', 'site', 'deploymentNetwork')
229 list_filter = ('deploymentNetwork',)
232 class SliverForm(forms.ModelForm):
234 ip = forms.CharField(widget=PlainTextWidget)
237 'ip': PlainTextWidget(),
240 class SliverAdmin(PlanetStackBaseAdmin):
243 ('Sliver', {'fields': ['ip', 'name', 'slice', 'image', 'key', 'node', 'deploymentNetwork']})
245 list_display = ['ip', 'name', 'slice', 'image', 'key', 'node', 'deploymentNetwork']
247 def save_model(self, request, obj, form, change):
248 # update openstack connection to use this sliver's slice/tenant
249 client = OpenStackClient(tenant=obj.slice.name, **request.session.get('auth', {}))
250 obj.driver = OpenStackDriver(client=client)
251 obj.caller = request.user
254 def delete_model(self, request, obj):
255 # update openstack connection to use this sliver's slice/tenant
256 client = OpenStackClient(tenant=obj.slice.name, **request.session.get('auth', {}))
257 obj.driver = OpenStackDriver(client=client)
258 obj.caller = request.user
262 class UserCreationForm(forms.ModelForm):
263 """A form for creating new users. Includes all the required
264 fields, plus a repeated password."""
265 password1 = forms.CharField(label='Password', widget=forms.PasswordInput)
266 password2 = forms.CharField(label='Password confirmation', widget=forms.PasswordInput)
270 fields = ('email', 'firstname', 'lastname', 'phone', 'site')
272 def clean_password2(self):
273 # Check that the two password entries match
274 password1 = self.cleaned_data.get("password1")
275 password2 = self.cleaned_data.get("password2")
276 if password1 and password2 and password1 != password2:
277 raise forms.ValidationError("Passwords don't match")
280 def save(self, commit=True):
281 # Save the provided password in hashed format
282 user = super(UserCreationForm, self).save(commit=False)
283 user.password = self.cleaned_data["password1"]
284 #user.set_password(self.cleaned_data["password1"])
290 class UserChangeForm(forms.ModelForm):
291 """A form for updating users. Includes all the fields on
292 the user, but replaces the password field with admin's
293 password hash display field.
295 password = ReadOnlyPasswordHashField()
300 def clean_password(self):
301 # Regardless of what the user provides, return the initial value.
302 # This is done here, rather than on the field, because the
303 # field does not have access to the initial value
304 return self.initial["password"]
307 class PLUserAdmin(UserAdmin, OSModelAdmin):
311 # The forms to add and change user instances
312 form = UserChangeForm
313 add_form = UserCreationForm
315 # The fields to be used in displaying the User model.
316 # These override the definitions on the base UserAdmin
317 # that reference specific fields on auth.User.
318 list_display = ('email', 'site', 'firstname', 'lastname', 'last_login')
319 list_filter = ('site',)
321 (None, {'fields': ('email', 'password')}),
322 ('Personal info', {'fields': ('firstname','lastname','phone','site')}),
323 #('Important dates', {'fields': ('last_login',)}),
327 'classes': ('wide',),
328 'fields': ('email', 'firstname', 'lastname', 'phone', 'site', 'password1', 'password2')}
331 search_fields = ('email',)
332 ordering = ('email',)
333 filter_horizontal = ()
335 # register a signal that caches the user's credentials when they log in
336 def cache_credentials(sender, user, request, **kwds):
337 auth = {'username': request.POST['username'],
338 'password': request.POST['password']}
339 request.session['auth'] = auth
340 user_logged_in.connect(cache_credentials)
342 # Now register the new UserAdmin...
343 admin.site.register(PLUser, PLUserAdmin)
344 # ... and, since we're not using Django's builtin permissions,
345 # unregister the Group model from admin.
346 admin.site.unregister(Group)
348 admin.site.register(Site, SiteAdmin)
349 admin.site.register(SitePrivilege, SitePrivilegeAdmin)
350 admin.site.register(Slice, SliceAdmin)
351 admin.site.register(SliceMembership, SliceMembershipAdmin)
352 admin.site.register(Subnet, SubnetAdmin)
353 admin.site.register(Image, ImageAdmin)
354 admin.site.register(Node, NodeAdmin)
355 admin.site.register(Sliver, SliverAdmin)
356 admin.site.register(Key, KeyAdmin)
357 admin.site.register(Role, RoleAdmin)
358 admin.site.register(DeploymentNetwork, DeploymentNetworkAdmin)