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