blob: 134b6884a722c8e7cb0aa6ae2746dffd18159da9 [file] [log] [blame]
from core.models import Site
from core.models import *
from openstack.manager import OpenStackManager
from django.contrib import admin
from django.contrib.auth.models import Group
from django import forms
from django.utils.safestring import mark_safe
from django.contrib.auth.admin import UserAdmin
from django.contrib.admin.widgets import FilteredSelectMultiple
from django.contrib.auth.forms import ReadOnlyPasswordHashField
from django.contrib.auth.signals import user_logged_in
class ReadonlyTabularInline(admin.TabularInline):
can_delete = False
extra = 0
editable_fields = []
def get_readonly_fields(self, request, obj=None):
fields = []
for field in self.model._meta.get_all_field_names():
if (not field == 'id'):
if (field not in self.editable_fields):
fields.append(field)
return fields
def has_add_permission(self, request):
return False
class SliverInline(admin.TabularInline):
model = Sliver
fields = ['ip', 'instance_name', 'slice', 'numberCores', 'image', 'key', 'node', 'deploymentNetwork']
extra = 0
#readonly_fields = ['ip', 'instance_name', 'image']
readonly_fields = ['ip', 'instance_name']
class SiteInline(admin.TabularInline):
model = Site
extra = 0
class UserInline(admin.TabularInline):
model = User
fields = ['email', 'firstname', 'lastname']
extra = 0
class SliceInline(admin.TabularInline):
model = Slice
extra = 0
class RoleInline(admin.TabularInline):
model = Role
extra = 0
class NodeInline(admin.TabularInline):
model = Node
extra = 0
class SitePrivilegeInline(admin.TabularInline):
model = SitePrivilege
extra = 0
class SliceMembershipInline(admin.TabularInline):
model = SliceMembership
extra = 0
class PlainTextWidget(forms.HiddenInput):
input_type = 'hidden'
def render(self, name, value, attrs=None):
if value is None:
value = ''
return mark_safe(str(value) + super(PlainTextWidget, self).render(name, value, attrs))
class PlanetStackBaseAdmin(admin.ModelAdmin):
save_on_top = False
class OSModelAdmin(PlanetStackBaseAdmin):
"""Attach client connection to openstack on delete() and save()"""
def save_model(self, request, obj, form, change):
if request.user.site:
auth = request.session.get('auth', {})
auth['tenant'] = request.user.site.login_base
obj.os_manager = OpenStackManager(auth=auth, caller=request.user)
obj.save()
def delete_model(self, request, obj):
if request.user.site:
auth = request.session.get('auth', {})
auth['tenant'] = request.user.site.login_base
obj.os_manager = OpenStackManager(auth=auth, caller=request.user)
obj.delete()
class RoleAdmin(OSModelAdmin):
fieldsets = [
('Role', {'fields': ['role_type']})
]
list_display = ('role_type',)
class DeploymentNetworkAdminForm(forms.ModelForm):
sites = forms.ModelMultipleChoiceField(
queryset=Site.objects.all(),
required=False,
widget=FilteredSelectMultiple(
verbose_name=('Sites'), is_stacked=False
)
)
class Meta:
model = DeploymentNetwork
def __init__(self, *args, **kwargs):
super(DeploymentNetworkAdminForm, self).__init__(*args, **kwargs)
if self.instance and self.instance.pk:
self.fields['sites'].initial = self.instance.sites.all()
def save(self, commit=True):
deploymentNetwork = super(DeploymentNetworkAdminForm, self).save(commit=False)
if commit:
deploymentNetwork.save()
if deploymentNetwork.pk:
deploymentNetwork.sites = self.cleaned_data['sites']
self.save_m2m()
return deploymentNetwork
class DeploymentNetworkAdmin(PlanetStackBaseAdmin):
form = DeploymentNetworkAdminForm
inlines = [NodeInline,SliverInline]
def get_formsets(self, request, obj=None):
for inline in self.get_inline_instances(request, obj):
# hide MyInline in the add view
if obj is None:
continue
# give inline object access to driver and caller
auth = request.session.get('auth', {})
if request.user.site:
auth['tenant'] = request.user.site.login_base
inline.model.os_manager = OpenStackManager(auth=auth, caller=request.user)
yield inline.get_formset(request, obj)
class SiteAdmin(OSModelAdmin):
fieldsets = [
(None, {'fields': ['name', 'site_url', 'enabled', 'is_public', 'login_base']}),
('Location', {'fields': ['latitude', 'longitude']}),
('Deployment Networks', {'fields': ['deployments']})
]
list_display = ('name', 'login_base','site_url', 'enabled')
filter_horizontal = ('deployments',)
inlines = [NodeInline, UserInline, SitePrivilegeInline]
search_fields = ['name']
def queryset(self, request):
# admins can see all keys. Users can only see sites they belong to.
qs = super(SiteAdmin, self).queryset(request)
if not request.user.is_admin:
valid_sites = [request.user.site.login_base]
roles = request.user.get_roles()
for tenant_list in roles.values():
valid_sites.extend(tenant_list)
qs = qs.filter(login_base__in=valid_sites)
return qs
def get_formsets(self, request, obj=None):
for inline in self.get_inline_instances(request, obj):
# hide MyInline in the add view
if obj is None:
continue
# give inline object access to driver and caller
auth = request.session.get('auth', {})
#auth['tenant'] = request.user.site.login_base
inline.model.os_manager = OpenStackManager(auth=auth, caller=request.user)
yield inline.get_formset(request, obj)
class SitePrivilegeAdmin(PlanetStackBaseAdmin):
fieldsets = [
(None, {'fields': ['user', 'site', 'role']})
]
list_display = ('user', 'site', 'role')
def queryset(self, request):
# admins can see all privileges. Users can only see privileges at sites
# where they have the admin role.
qs = super(SitePrivilegeAdmin, self).queryset(request)
if not request.user.is_admin:
roles = request.user.get_roles()
tenants = []
for (role, tenant_list) in roles:
if role == 'admin':
tenants.extend(tenant_list)
valid_sites = Sites.objects.filter(login_base__in=tenants)
qs = qs.filter(site__in=valid_sites)
return qs
def save_model(self, request, obj, form, change):
# update openstack connection to use this site/tenant
auth = request.session.get('auth', {})
#auth['tenant'] = obj.site.login_base
obj.os_manager = OpenStackManager(auth=auth, caller=request.user)
obj.save()
def delete_model(self, request, obj):
# update openstack connection to use this site/tenant
auth = request.session.get('auth', {})
#auth['tenant'] = obj.site.login_base
obj.os_manager = OpenStackManager(auth=auth, caller=request.user)
obj.delete()
class KeyAdmin(OSModelAdmin):
fieldsets = [
('Key', {'fields': ['key', 'type', 'blacklisted']})
]
list_display = ['key', 'type', 'blacklisted']
#def queryset(self, request):
# admins can see all keys. Users can only see their own key.
#if request.user.is_admin:
# qs = super(KeyAdmin, self).queryset(request)
#else:
# qs = Key.objects.filter(user=request.user)
#return qs
class SliceAdmin(OSModelAdmin):
fields = ['name', 'site', 'serviceClass', 'description', 'slice_url']
list_display = ('name', 'site','serviceClass', 'slice_url')
inlines = [SliverInline, SliceMembershipInline]
def queryset(self, request):
# admins can see all keys. Users can only see slices they belong to.
qs = super(SliceAdmin, self).queryset(request)
if not request.user.is_admin:
valid_slices = []
roles = request.user.get_roles()
for tenant_list in roles.values():
valid_slices.extend(tenant_list)
qs = qs.filter(name__in=valid_slices)
return qs
def get_formsets(self, request, obj=None):
for inline in self.get_inline_instances(request, obj):
# hide MyInline in the add view
if obj is None:
continue
# give inline object access to driver and caller
auth = request.session.get('auth', {})
auth['tenant'] = obj.name # meed to connect using slice's tenant
inline.model.os_manager = OpenStackManager(auth=auth, caller=request.user)
yield inline.get_formset(request, obj)
def get_queryset(self, request):
qs = super(SliceAdmin, self).get_queryset(request)
if request.user.is_superuser:
return qs
# users can only see slices at their site
return qs.filter(site=request.user.site)
class SliceMembershipAdmin(PlanetStackBaseAdmin):
fieldsets = [
(None, {'fields': ['user', 'slice', 'role']})
]
list_display = ('user', 'slice', 'role')
def queryset(self, request):
# admins can see all memberships. Users can only see memberships of
# slices where they have the admin role.
qs = super(SliceMembershipAdmin, self).queryset(request)
if not request.user.is_admin:
roles = request.user.get_roles()
tenants = []
for (role, tenant_list) in roles:
if role == 'admin':
tenants.extend(tenant_list)
valid_slices = Slice.objects.filter(name__in=tenants)
qs = qs.filter(slice__in=valid_slices)
return qs
def save_model(self, request, obj, form, change):
# update openstack connection to use this site/tenant
auth = request.session.get('auth', {})
auth['tenant'] = obj.slice.name
obj.os_manager = OpenStackManager(auth=auth, caller=request.user)
obj.save()
def delete_model(self, request, obj):
# update openstack connection to use this site/tenant
auth = request.session.get('auth', {})
auth['tenant'] = obj.slice.name
obj.os_manager = OpenStackManager(auth=auth, caller=request.user)
obj.delete()
class ImageAdmin(admin.ModelAdmin):
fields = ['image_id', 'name', 'disk_format', 'container_format']
class NodeAdmin(admin.ModelAdmin):
list_display = ('name', 'site', 'deploymentNetwork')
list_filter = ('deploymentNetwork',)
class SliverForm(forms.ModelForm):
class Meta:
model = Sliver
ip = forms.CharField(widget=PlainTextWidget)
instance_name = forms.CharField(widget=PlainTextWidget)
widgets = {
'ip': PlainTextWidget(),
'instance_name': PlainTextWidget(),
}
class SliverAdmin(PlanetStackBaseAdmin):
form = SliverForm
fieldsets = [
('Sliver', {'fields': ['ip', 'instance_name', 'slice', 'numberCores', 'image', 'key', 'node', 'deploymentNetwork']})
]
list_display = ['ip', 'instance_name', 'slice', 'numberCores', 'image', 'key', 'node', 'deploymentNetwork']
def queryset(self, request):
# admins can see all slivers. Users can only see slivers of
# the slices they belong to.
qs = super(SliverAdmin, self).queryset(request)
if not request.user.is_admin:
tenants = []
roles = request.user.get_roles()
for tenant_list in roles.values():
tenants.extend(tenant_list)
valid_slices = Slice.objects.filter(name__in=tenants)
qs = qs.filter(slice__in=valid_slices)
return qs
def get_formsets(self, request, obj=None):
# make some fields read only if we are updating an existing record
if obj == None:
#self.readonly_fields = ('ip', 'instance_name')
self.readonly_fields = ()
else:
self.readonly_fields = ()
#self.readonly_fields = ('ip', 'instance_name', 'slice', 'image', 'key')
for inline in self.get_inline_instances(request, obj):
# hide MyInline in the add view
if obj is None:
continue
# give inline object access to driver and caller
auth = request.session.get('auth', {})
auth['tenant'] = obj.name # meed to connect using slice's tenant
inline.model.os_manager = OpenStackManager(auth=auth, caller=request.user)
yield inline.get_formset(request, obj)
def save_model(self, request, obj, form, change):
# update openstack connection to use this site/tenant
auth = request.session.get('auth', {})
auth['tenant'] = obj.slice.name
obj.os_manager = OpenStackManager(auth=auth, caller=request.user)
obj.save()
def delete_model(self, request, obj):
# update openstack connection to use this site/tenant
auth = request.session.get('auth', {})
auth['tenant'] = obj.slice.name
obj.os_manager = OpenStackManager(auth=auth, caller=request.user)
obj.delete()
class UserCreationForm(forms.ModelForm):
"""A form for creating new users. Includes all the required
fields, plus a repeated password."""
password1 = forms.CharField(label='Password', widget=forms.PasswordInput)
password2 = forms.CharField(label='Password confirmation', widget=forms.PasswordInput)
class Meta:
model = User
fields = ('email', 'firstname', 'lastname', 'phone', 'key', 'site')
def clean_password2(self):
# Check that the two password entries match
password1 = self.cleaned_data.get("password1")
password2 = self.cleaned_data.get("password2")
if password1 and password2 and password1 != password2:
raise forms.ValidationError("Passwords don't match")
return password2
def save(self, commit=True):
# Save the provided password in hashed format
user = super(UserCreationForm, self).save(commit=False)
user.password = self.cleaned_data["password1"]
#user.set_password(self.cleaned_data["password1"])
if commit:
user.save()
return user
class UserChangeForm(forms.ModelForm):
"""A form for updating users. Includes all the fields on
the user, but replaces the password field with admin's
password hash display field.
"""
password = ReadOnlyPasswordHashField()
class Meta:
model = User
def clean_password(self):
# Regardless of what the user provides, return the initial value.
# This is done here, rather than on the field, because the
# field does not have access to the initial value
return self.initial["password"]
class UserAdmin(UserAdmin, OSModelAdmin):
class Meta:
app_label = "core"
# The forms to add and change user instances
form = UserChangeForm
add_form = UserCreationForm
# The fields to be used in displaying the User model.
# These override the definitions on the base UserAdmin
# that reference specific fields on auth.User.
list_display = ('email', 'site', 'firstname', 'lastname', 'is_admin', 'last_login')
list_filter = ('site',)
inlines = [SitePrivilegeInline, SliceMembershipInline]
fieldsets = (
(None, {'fields': ('email', 'password', 'site', 'is_admin')}),
('Personal info', {'fields': ('firstname','lastname','phone', 'key')}),
#('Important dates', {'fields': ('last_login',)}),
)
add_fieldsets = (
(None, {
'classes': ('wide',),
'fields': ('email', 'firstname', 'lastname', 'phone', 'site', 'key','password1', 'password2', 'is_admin')}
),
)
search_fields = ('email',)
ordering = ('email',)
filter_horizontal = ()
class ServiceResourceInline(admin.TabularInline):
model = ServiceResource
extra = 0
class ServiceClassAdmin(admin.ModelAdmin):
list_display = ('name', 'commitment', 'membershipFee')
inlines = [ServiceResourceInline]
class ServiceResourceAdmin(admin.ModelAdmin):
list_display = ('serviceClass', 'name', 'cost', 'calendarReservable', 'maxUnitsDeployment', 'maxUnitsNode')
# register a signal that caches the user's credentials when they log in
def cache_credentials(sender, user, request, **kwds):
auth = {'username': request.POST['username'],
'password': request.POST['password']}
request.session['auth'] = auth
user_logged_in.connect(cache_credentials)
# Now register the new UserAdmin...
admin.site.register(User, UserAdmin)
# ... and, since we're not using Django's builtin permissions,
# unregister the Group model from admin.
admin.site.unregister(Group)
admin.site.register(Site, SiteAdmin)
admin.site.register(SitePrivilege, SitePrivilegeAdmin)
admin.site.register(Slice, SliceAdmin)
admin.site.register(SliceMembership, SliceMembershipAdmin)
#admin.site.register(Subnet)
admin.site.register(Image, ImageAdmin)
admin.site.register(Node, NodeAdmin)
admin.site.register(Sliver, SliverAdmin)
admin.site.register(Key, KeyAdmin)
admin.site.register(Role, RoleAdmin)
admin.site.register(DeploymentNetwork, DeploymentNetworkAdmin)
admin.site.register(ServiceClass, ServiceClassAdmin)
admin.site.register(ServiceResource, ServiceResourceAdmin)