update SitePrivilegeAdmin and SliceMembershipAdmin
[plstackapi.git] / plstackapi / core / admin.py
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
5
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 
14
15
16 class ReadonlyTabularInline(admin.TabularInline):
17     can_delete = False
18     extra = 0
19     editable_fields = []
20
21     def get_readonly_fields(self, request, obj=None):
22         fields = []
23         for field in self.model._meta.get_all_field_names():
24             if (not field == 'id'):
25                 if (field not in self.editable_fields):
26                     fields.append(field)
27         return fields
28
29     def has_add_permission(self, request):
30         return False
31
32 class SliverInline(admin.TabularInline):
33     model = Sliver
34     fields = ['ip', 'name', 'slice', 'flavor', 'image', 'key', 'node', 'deploymentNetwork']
35     extra = 0
36
37 class SiteInline(admin.TabularInline):
38     model = Site
39     extra = 0
40
41 class SliceInline(admin.TabularInline):
42     model = Slice
43     extra = 0
44
45 class UserInline(admin.TabularInline):
46     model = PLUser
47     extra = 0
48
49 class RoleInline(admin.TabularInline):
50     model = Role
51     extra = 0 
52
53 class NodeInline(admin.TabularInline):
54     model = Node
55     extra = 0
56
57 class PlanetStackBaseAdmin(admin.ModelAdmin):
58     save_on_top = False
59
60 class OSModelAdmin(PlanetStackBaseAdmin):
61     """Attach client connection to openstack on delete() and save()""" 
62     def save_model(self, request, obj, form, change):
63         client = OpenStackClient(tenant=request.user.site.login_base, **request.session.get('auth', {}))
64         obj.driver = OpenStackDriver(client=client)
65         obj.save()
66
67     def delete_model(self, request, obj):
68         client = OpenStackClient(tenant=request.user.site.login_base, **request.session.get('auth', {}))
69         obj.driver = OpenStackDriver(client=client)
70         obj.delete()
71     
72
73 class DeploymentNetworkAdminForm(forms.ModelForm):
74     sites = forms.ModelMultipleChoiceField(
75         queryset=Site.objects.all(),
76         required=False,
77         widget=FilteredSelectMultiple(
78             verbose_name=('Sites'), is_stacked=False
79         )
80     )
81     class Meta:
82         model = DeploymentNetwork
83
84     def __init__(self, *args, **kwargs):
85         super(DeploymentNetworkAdminForm, self).__init__(*args, **kwargs)
86
87         if self.instance and self.instance.pk:
88             self.fields['sites'].initial = self.instance.sites.all()
89
90     def save(self, commit=True):
91         deploymentNetwork = super(DeploymentNetworkAdminForm, self).save(commit=False)
92         if commit:
93             deploymentNetwork.save()
94
95         if deploymentNetwork.pk:
96             deploymentNetwork.sites = self.cleaned_data['sites']
97             self.save_m2m()
98
99         return deploymentNetwork
100
101 class DeploymentNetworkAdmin(PlanetStackBaseAdmin):
102     form = DeploymentNetworkAdminForm
103     inlines = [NodeInline,]
104
105 class SiteAdmin(OSModelAdmin):
106     fieldsets = [
107         (None, {'fields': ['name', 'site_url', 'enabled', 'is_public', 'login_base']}),
108         ('Location', {'fields': ['latitude', 'longitude']}),
109         ('Deployment Networks', {'fields': ['deployments']})
110     ]
111     list_display = ('name', 'login_base','site_url', 'enabled')
112     filter_horizontal = ('deployments',)
113     inlines = [NodeInline,]
114     search_fields = ['name']
115
116 class SitePrivilegeAdmin(OSModelAdmin):
117     fieldsets = [
118         (None, {'fields': ['user', 'site', 'role']})
119     ]
120     list_display = ('user', 'site', 'role')
121
122 class KeyAdmin(OSModelAdmin):
123     fieldsets = [
124         ('Key', {'fields': ['name', 'key', 'type', 'blacklisted', 'user']})
125     ]
126     list_display = ['name', 'key', 'type', 'blacklisted', 'user']
127
128     def get_queryset(self, request):
129         # get keys user is allowed to see
130         qs = super(KeyAdmin, self).get_queryset(request)
131         if request.user.is_superuser:
132             return qs
133         # users can only see their own keys
134         return qs.filter(user=request.user)  
135         
136
137 class SliceAdmin(OSModelAdmin):
138     fields = ['name', 'site', 'instantiation', 'description', 'slice_url']
139     list_display = ('name', 'site','slice_url', 'instantiation')
140     inlines = [SliverInline]
141
142     def get_queryset(self, request):
143         qs = super(SliceAdmin, self).get_queryset(request)
144         if request.user.is_superuser:
145             return qs
146         # users can only see slices at their site
147         return qs.filter(site=request.user.site) 
148
149 class SliceMembershipAdmin(OSModelAdmin):
150     fieldsets = [
151         (None, {'fields': ['user', 'slice', 'role']})
152     ]
153     list_display = ('user', 'slice', 'role')
154     inlines = [UserInline, SliceInline, RoleInline]
155
156 class SubnetAdmin(OSModelAdmin):
157     fields = ['cidr', 'ip_version', 'start', 'end', 'slice']
158     list_display = ('slice','cidr', 'start', 'end', 'ip_version')
159
160 class ImageAdmin(admin.ModelAdmin):
161     fields = ['image_id', 'name', 'disk_format', 'container_format']
162
163 class NodeAdmin(admin.ModelAdmin):
164     list_display = ('name', 'site', 'deploymentNetwork')
165     list_filter = ('deploymentNetwork',)
166
167 class RoleAdmin(OSModelAdmin):
168     fieldsets = [
169         ('Role', {'fields': ['role_type']})
170     ]
171     list_display = ('role_type',)
172
173 class PlainTextWidget(forms.Widget):
174     def render(self, _name, value, attrs):
175         return mark_safe(value) if value is not None else ''
176
177 class SliverForm(forms.ModelForm):
178     class Meta:
179         ip = forms.CharField(widget=PlainTextWidget)
180         model = Sliver
181         widgets = {
182             'ip': PlainTextWidget(),
183         }
184
185 class SliverAdmin(OSModelAdmin):
186     form = SliverForm
187     fieldsets = [
188         ('Sliver', {'fields': ['ip', 'name', 'slice', 'flavor', 'image', 'key', 'node', 'deploymentNetwork']})
189     ]
190     list_display = ['ip', 'name', 'slice', 'flavor', 'image', 'key', 'node', 'deploymentNetwork']
191
192     def save_model(self, request, obj, form, change):
193         client = OpenStackClient(tenant=obj.slice.name, **request.session.get('auth', {}))
194         obj.driver = OpenStackDriver(client=client)
195         obj.save()
196
197     def delete_model(self, request, obj):
198         client = OpenStackClient(tenant=obj.slice.name, **request.session.get('auth', {}))
199         obj.driver = OpenStackDriver(client=client)
200         obj.delete()
201      
202
203 class UserCreationForm(forms.ModelForm):
204     """A form for creating new users. Includes all the required
205     fields, plus a repeated password."""
206     password1 = forms.CharField(label='Password', widget=forms.PasswordInput)
207     password2 = forms.CharField(label='Password confirmation', widget=forms.PasswordInput)
208
209     class Meta:
210         model = PLUser
211         fields = ('email', 'firstname', 'lastname', 'phone', 'site')
212
213     def clean_password2(self):
214         # Check that the two password entries match
215         password1 = self.cleaned_data.get("password1")
216         password2 = self.cleaned_data.get("password2")
217         if password1 and password2 and password1 != password2:
218             raise forms.ValidationError("Passwords don't match")
219         return password2
220
221     def save(self, commit=True):
222         # Save the provided password in hashed format
223         user = super(UserCreationForm, self).save(commit=False)
224         user.set_password(self.cleaned_data["password1"])
225         if commit:
226             user.save()
227         return user
228
229
230 class UserChangeForm(forms.ModelForm):
231     """A form for updating users. Includes all the fields on
232     the user, but replaces the password field with admin's
233     password hash display field.
234     """
235     password = ReadOnlyPasswordHashField()
236
237     class Meta:
238         model = PLUser
239
240     def clean_password(self):
241         # Regardless of what the user provides, return the initial value.
242         # This is done here, rather than on the field, because the
243         # field does not have access to the initial value
244         return self.initial["password"]
245
246
247 class PLUserAdmin(UserAdmin, OSModelAdmin):
248     class Meta:
249         app_label = "core"
250
251     # The forms to add and change user instances
252     form = UserChangeForm
253     add_form = UserCreationForm
254
255     # The fields to be used in displaying the User model.
256     # These override the definitions on the base UserAdmin
257     # that reference specific fields on auth.User.
258     list_display = ('email', 'site', 'firstname', 'lastname', 'last_login')
259     list_filter = ('site',)
260     fieldsets = (
261         (None, {'fields': ('email', 'password')}),
262         ('Personal info', {'fields': ('firstname','lastname','phone','site')}),
263         #('Important dates', {'fields': ('last_login',)}),
264     )
265     add_fieldsets = (
266         (None, {
267             'classes': ('wide',),
268             'fields': ('email', 'firstname', 'lastname', 'phone', 'site', 'password1', 'password2')}
269         ),
270     )
271     search_fields = ('email',)
272     ordering = ('email',)
273     filter_horizontal = ()
274
275 # register a signal that caches the user's credentials when they log in
276 def cache_credentials(sender, user, request, **kwds):
277     auth = {'username': request.POST['username'],
278             'password': request.POST['password']}
279     request.session['auth'] = auth
280 user_logged_in.connect(cache_credentials)
281
282 # Now register the new UserAdmin...
283 admin.site.register(PLUser, PLUserAdmin)
284 # ... and, since we're not using Django's builtin permissions,
285 # unregister the Group model from admin.
286 admin.site.unregister(Group)
287
288 admin.site.register(Site, SiteAdmin)
289 admin.site.register(SitePrivilege, SitePrivilegeAdmin)
290 admin.site.register(Slice, SliceAdmin)
291 admin.site.register(SliceMembership, SliceMembershipAdmin)
292 admin.site.register(Subnet, SubnetAdmin)
293 admin.site.register(Image, ImageAdmin)
294 admin.site.register(Node, NodeAdmin)
295 admin.site.register(Sliver, SliverAdmin)
296 admin.site.register(Flavor)
297 admin.site.register(Key, KeyAdmin)
298 admin.site.register(Role, RoleAdmin)
299 admin.site.register(DeploymentNetwork, DeploymentNetworkAdmin)
300