<commit_before>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
from django.utils import timezone
from django.contrib.contenttypes import generic
from suit.widgets import LinkedSelect
from django.core.exceptions import PermissionDenied
from django.core.urlresolvers import reverse, NoReverseMatch

import django_evolution

def backend_icon(obj): # backend_status, enacted, updated):
    #return "%s %s %s" % (str(obj.updated), str(obj.enacted), str(obj.backend_status))
    if (obj.enacted is not None) and obj.enacted >= obj.updated:
        return '<span style="min-width:16px;"><img src="/static/admin/img/icon_success.gif"></span>'
    else:
        if obj.backend_status == "Provisioning in progress" or obj.backend_status=="":
            return '<span style="min-width:16px;" title="%s"><img src="/static/admin/img/icon_clock.gif"></span>' % obj.backend_status
        else:
            return '<span style="min-width:16px;" title="%s"><img src="/static/admin/img/icon_error.gif"></span>' % obj.backend_status

def backend_text(obj):
    icon = backend_icon(obj)
    if (obj.enacted is not None) and obj.enacted >= obj.updated:
        return "%s %s" % (icon, "successfully enacted") # enacted on %s" % str(obj.enacted))
    else:
        return "%s %s" % (icon, obj.backend_status)

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 ReadOnlyAwareAdmin(admin.ModelAdmin):

    def has_add_permission(self, request, obj=None):
        return (not self.__user_is_readonly(request))

    def has_delete_permission(self, request, obj=None):
        return (not self.__user_is_readonly(request))

    def save_model(self, request, obj, form, change):
        if self.__user_is_readonly(request):
            raise PermissionDenied
            #pass
        else:
            return super(ReadOnlyAwareAdmin, self).save_model(request, obj, form, change)

    def get_actions(self,request):
        actions = super(ReadOnlyAwareAdmin,self).get_actions(request)

        if self.__user_is_readonly(request):
            if 'delete_selected' in actions:
                del actions['delete_selected']

        return actions

    def change_view(self,request,object_id, extra_context=None):
        if self.__user_is_readonly(request):
            if not hasattr(self, "readonly_save"):
                # save the original readonly fields
                self.readonly_save = self.readonly_fields
                self.inlines_save = self.inlines
            if hasattr(self, "user_readonly_fields"):
                self.readonly_fields=self.user_readonly_fields
            if hasattr(self, "user_readonly_inlines"):
                self.inlines = self.user_readonly_inlines
        else:
            if hasattr(self, "readonly_save"):
                # restore the original readonly fields
                self.readonly_fields = self.readonly_save
            if hasattr(self, "inlines_save"):
                self.inlines = self.inlines_save

        try:
            return super(ReadOnlyAwareAdmin, self).change_view(request, object_id, extra_context=extra_context)
        except PermissionDenied:
            pass
        if request.method == 'POST':
            raise PermissionDenied
        request.readonly = True
        return super(ReadOnlyAwareAdmin, self).change_view(request, object_id, extra_context=extra_context)

    def __user_is_readonly(self, request):
        return request.user.isReadOnlyUser()

    def backend_status_text(self, obj):
        return mark_safe(backend_text(obj))

    def backend_status_icon(self, obj):
        return mark_safe(backend_icon(obj))
    backend_status_icon.short_description = ""


class SingletonAdmin (ReadOnlyAwareAdmin):
    def has_add_permission(self, request):
        if not super(SingletonAdmin, self).has_add_permission(request):
            return False

        num_objects = self.model.objects.count()
        if num_objects >= 1:
            return False
        else:
            return True


class PlStackTabularInline(admin.TabularInline):
    def __init__(self, *args, **kwargs):
        super(PlStackTabularInline, self).__init__(*args, **kwargs)

        # InlineModelAdmin as no get_fields() method, so in order to add
        # the selflink field, we override __init__ to modify self.fields and
        # self.readonly_fields.

        self.setup_selflink()

    def get_change_url(self, model, id):
        """ Get the URL to a change form in the admin for this model """
        reverse_path = "admin:%s_change" % (model._meta.db_table)
        try:
            url = reverse(reverse_path, args=(id,))
        except NoReverseMatch:
            return None

        return url

    def setup_selflink(self):
        if hasattr(self, "selflink_fieldname"):
            """ self.selflink_model can be defined to punch through a relation
                to its target object. For example, in SliceNetworkInline, set
                selflink_model = "network", and the URL will lead to the Network
                object instead of trying to bring up a change view of the
                SliceNetwork object.
            """
            self.selflink_model = getattr(self.model,self.selflink_fieldname).field.rel.to
        else:
            self.selflink_model = self.model

        url = self.get_change_url(self.selflink_model, 0)

        # We don't have an admin for this object, so don't create the
        # selflink.
        if (url == None):
            return

        # Since we need to add "selflink" to the field list, we need to create
        # self.fields if it is None.
        if (self.fields is None):
            self.fields = []
            for f in self.model._meta.fields:
                if f.editable and f.name != "id":
                    self.fields.append(f.name)

        self.fields = tuple(self.fields) + ("selflink", )

        if self.readonly_fields is None:
            self.readonly_fields = ()

        self.readonly_fields = tuple(self.readonly_fields) + ("selflink", )

    def selflink(self, obj):
        if hasattr(self, "selflink_fieldname"):
            obj = getattr(obj, self.selflink_fieldname)

        if obj.id:
            url = self.get_change_url(self.selflink_model, obj.id)
            return "<a href='%s'>Details</a>" % str(url)
        else:
            return "Not present"

    selflink.allow_tags = True
    selflink.short_description = "Details"

    def has_add_permission(self, request):
        return not request.user.isReadOnlyUser()

    def get_readonly_fields(self, request, obj=None):
        readonly_fields = list(self.readonly_fields)[:]
        if request.user.isReadOnlyUser():
            for field in self.fields:
                if not field in readonly_fields:
                    readonly_fields.append(field)
        return readonly_fields

    def backend_status_icon(self, obj):
        return mark_safe(backend_icon(obj))
    backend_status_icon.short_description = ""

class PlStackGenericTabularInline(generic.GenericTabularInline):
    def has_add_permission(self, request):
        return not request.user.isReadOnlyUser()

    def get_readonly_fields(self, request, obj=None):
        readonly_fields = list(self.readonly_fields)[:]
        if request.user.isReadOnlyUser():
            for field in self.fields:
                if not field in readonly_fields:
                    readonly_fields.append(field)
        return readonly_fields

    def backend_status_icon(self, obj):
        return mark_safe(backend_icon(obj))
    backend_status_icon.short_description = ""

class ReservationInline(PlStackTabularInline):
    model = Reservation
    extra = 0
    suit_classes = 'suit-tab suit-tab-reservations'

    def queryset(self, request):
        return Reservation.select_by_user(request.user)

class TagInline(PlStackGenericTabularInline):
    model = Tag
    extra = 0
    suit_classes = 'suit-tab suit-tab-tags'
    fields = ['service', 'name', 'value']

    def queryset(self, request):
        return Tag.select_by_user(request.user)

class NetworkLookerUpper:
    """ This is a callable that looks up a network name in a sliver and returns
        the ip address for that network.
    """

    byNetworkName = {}    # class variable

    def __init__(self, name):
        self.short_description = name
        self.__name__ = name
        self.network_name = name

    def __call__(self, obj):
        if obj is not None:
            for nbs in obj.networksliver_set.all():
                if (nbs.network.name == self.network_name):
                    return nbs.ip
        return ""

    def __str__(self):
        return self.network_name

    @staticmethod
    def get(network_name):
        """ We want to make sure we alwars return the same NetworkLookerUpper
            because sometimes django will cause them to be instantiated multiple
            times (and we don't want different ones in form.fields vs
            SliverInline.readonly_fields).
        """
        if network_name not in NetworkLookerUpper.byNetworkName:
            NetworkLookerUpper.byNetworkName[network_name] = NetworkLookerUpper(network_name)
        return NetworkLookerUpper.byNetworkName[network_name]

class SliverInline(PlStackTabularInline):
    model = Sliver
    fields = ['backend_status_icon', 'all_ips_string', 'instance_name', 'slice', 'deploymentNetwork', 'flavor', 'image', 'node']
    extra = 0
    readonly_fields = ['backend_status_icon', 'all_ips_string', 'instance_name']
    suit_classes = 'suit-tab suit-tab-slivers'

    def queryset(self, request):
        return Sliver.select_by_user(request.user)

    def formfield_for_foreignkey(self, db_field, request=None, **kwargs):
        if db_field.name == 'deploymentNetwork':
           kwargs['queryset'] = Deployment.select_by_acl(request.user)
           kwargs['widget'] = forms.Select(attrs={'onChange': "sliver_deployment_changed(this);"})
        elif db_field.name == 'flavor':
           kwargs['widget'] = forms.Select(attrs={'onChange': "sliver_flavor_changed(this);"})

        field = super(SliverInline, self).formfield_for_foreignkey(db_field, request, **kwargs)

        return field

class SiteInline(PlStackTabularInline):
    model = Site
    extra = 0
    suit_classes = 'suit-tab suit-tab-sites'

    def queryset(self, request):
        return Site.select_by_user(request.user)

class UserInline(PlStackTabularInline):
    model = User
    fields = ['backend_status_icon', 'email', 'firstname', 'lastname']
    readonly_fields = ('backend_status_icon', )
    extra = 0
    suit_classes = 'suit-tab suit-tab-users'

    def queryset(self, request):
        return User.select_by_user(request.user)

class SliceInline(PlStackTabularInline):
    model = Slice
    fields = ['backend_status_icon', 'name', 'site', 'serviceClass', 'service']
    readonly_fields = ('backend_status_icon', )
    extra = 0
    suit_classes = 'suit-tab suit-tab-slices'

    def queryset(self, request):
        return Slice.select_by_user(request.user)

class NodeInline(PlStackTabularInline):
    model = Node
    extra = 0
    suit_classes = 'suit-tab suit-tab-nodes'
    fields = ['backend_status_icon', 'name','deployment','site']
    readonly_fields = ('backend_status_icon', )

class DeploymentPrivilegeInline(PlStackTabularInline):
    model = DeploymentPrivilege
    extra = 0
    suit_classes = 'suit-tab suit-tab-deploymentprivileges'
    fields = ['backend_status_icon', 'user','role','deployment']
    readonly_fields = ('backend_status_icon', )

    def queryset(self, request):
        return DeploymentPrivilege.select_by_user(request.user)

class SitePrivilegeInline(PlStackTabularInline):
    model = SitePrivilege
    extra = 0
    suit_classes = 'suit-tab suit-tab-siteprivileges'
    fields = ['backend_status_icon', 'user','site', 'role']
    readonly_fields = ('backend_status_icon', )

    def formfield_for_foreignkey(self, db_field, request, **kwargs):
        if db_field.name == 'site':
            kwargs['queryset'] = Site.select_by_user(request.user)

        if db_field.name == 'user':
            kwargs['queryset'] = User.select_by_user(request.user)
        return super(SitePrivilegeInline, self).formfield_for_foreignkey(db_field, request, **kwargs)

    def queryset(self, request):
        return SitePrivilege.select_by_user(request.user)

class SiteDeploymentInline(PlStackTabularInline):
    model = SiteDeployments
    extra = 0
    suit_classes = 'suit-tab suit-tab-deployments'
    fields = ['backend_status_icon', 'deployment','site']
    readonly_fields = ('backend_status_icon', )

    def formfield_for_foreignkey(self, db_field, request, **kwargs):
        if db_field.name == 'site':
            kwargs['queryset'] = Site.select_by_user(request.user)

        if db_field.name == 'deployment':
            kwargs['queryset'] = Deployment.select_by_user(request.user)
        return super(SiteDeploymentInline, self).formfield_for_foreignkey(db_field, request, **kwargs)

    def queryset(self, request):
        return SiteDeployments.select_by_user(request.user)


class SlicePrivilegeInline(PlStackTabularInline):
    model = SlicePrivilege
    suit_classes = 'suit-tab suit-tab-sliceprivileges'
    extra = 0
    fields = ('backend_status_icon', 'user', 'slice', 'role')
    readonly_fields = ('backend_status_icon', )

    def formfield_for_foreignkey(self, db_field, request, **kwargs):
        if db_field.name == 'slice':
           kwargs['queryset'] = Slice.select_by_user(request.user)
        if db_field.name == 'user':
           kwargs['queryset'] = User.select_by_user(request.user)

        return super(SlicePrivilegeInline, self).formfield_for_foreignkey(db_field, request, **kwargs)

    def queryset(self, request):
        return SlicePrivilege.select_by_user(request.user)

class SliceNetworkInline(PlStackTabularInline):
    model = Network.slices.through
    selflink_fieldname = "network"
    extra = 0
    verbose_name = "Network Connection"
    verbose_name_plural = "Network Connections"
    suit_classes = 'suit-tab suit-tab-slicenetworks'
    fields = ['backend_status_icon', 'network']
    readonly_fields = ('backend_status_icon', )

class ImageDeploymentsInline(PlStackTabularInline):
    model = ImageDeployments
    extra = 0
    verbose_name = "Image Deployments"
    verbose_name_plural = "Image Deployments"
    suit_classes = 'suit-tab suit-tab-imagedeployments'
    fields = ['backend_status_icon', 'image', 'deployment', 'glance_image_id']
    readonly_fields = ['backend_status_icon', 'glance_image_id']

class PlanetStackBaseAdmin(ReadOnlyAwareAdmin):
    save_on_top = False

    def save_model(self, request, obj, form, change):
        obj.caller = request.user
        # update openstack connection to use this site/tenant
        obj.save_by_user(request.user)

    def delete_model(self, request, obj):
        obj.delete_by_user(request.user)

    def save_formset(self, request, form, formset, change):
        instances = formset.save(commit=False)
        for instance in instances:
            instance.save_by_user(request.user)
        formset.save_m2m()

class SliceRoleAdmin(PlanetStackBaseAdmin):
    model = SliceRole
    pass

class SiteRoleAdmin(PlanetStackBaseAdmin):
    model = SiteRole
    pass

class DeploymentAdminForm(forms.ModelForm):
    sites = forms.ModelMultipleChoiceField(
        queryset=Site.objects.all(),
        required=False,
        help_text="Select which sites are allowed to host nodes in this deployment",
        widget=FilteredSelectMultiple(
            verbose_name=('Sites'), is_stacked=False
        )<commit_msg>check-in fix for checkbox deletion not working in django 1.7<commit_after>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
from django.utils import timezone
from django.contrib.contenttypes import generic
from suit.widgets import LinkedSelect
from django.core.exceptions import PermissionDenied
from django.core.urlresolvers import reverse, NoReverseMatch

import django_evolution

def backend_icon(obj): # backend_status, enacted, updated):
    #return "%s %s %s" % (str(obj.updated), str(obj.enacted), str(obj.backend_status))
    if (obj.enacted is not None) and obj.enacted >= obj.updated:
        return '<span style="min-width:16px;"><img src="/static/admin/img/icon_success.gif"></span>'
    else:
        if obj.backend_status == "Provisioning in progress" or obj.backend_status=="":
            return '<span style="min-width:16px;" title="%s"><img src="/static/admin/img/icon_clock.gif"></span>' % obj.backend_status
        else:
            return '<span style="min-width:16px;" title="%s"><img src="/static/admin/img/icon_error.gif"></span>' % obj.backend_status

def backend_text(obj):
    icon = backend_icon(obj)
    if (obj.enacted is not None) and obj.enacted >= obj.updated:
        return "%s %s" % (icon, "successfully enacted") # enacted on %s" % str(obj.enacted))
    else:
        return "%s %s" % (icon, obj.backend_status)

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 ReadOnlyAwareAdmin(admin.ModelAdmin):

    def has_add_permission(self, request, obj=None):
        return (not self.__user_is_readonly(request))

    def has_delete_permission(self, request, obj=None):
        return (not self.__user_is_readonly(request))

    def save_model(self, request, obj, form, change):
        if self.__user_is_readonly(request):
            raise PermissionDenied
            #pass
        else:
            return super(ReadOnlyAwareAdmin, self).save_model(request, obj, form, change)

    def get_actions(self,request):
        actions = super(ReadOnlyAwareAdmin,self).get_actions(request)

        if self.__user_is_readonly(request):
            if 'delete_selected' in actions:
                del actions['delete_selected']

        return actions

    def change_view(self,request,object_id, extra_context=None):
        if self.__user_is_readonly(request):
            if not hasattr(self, "readonly_save"):
                # save the original readonly fields
                self.readonly_save = self.readonly_fields
                self.inlines_save = self.inlines
            if hasattr(self, "user_readonly_fields"):
                self.readonly_fields=self.user_readonly_fields
            if hasattr(self, "user_readonly_inlines"):
                self.inlines = self.user_readonly_inlines
        else:
            if hasattr(self, "readonly_save"):
                # restore the original readonly fields
                self.readonly_fields = self.readonly_save
            if hasattr(self, "inlines_save"):
                self.inlines = self.inlines_save

        try:
            return super(ReadOnlyAwareAdmin, self).change_view(request, object_id, extra_context=extra_context)
        except PermissionDenied:
            pass
        if request.method == 'POST':
            raise PermissionDenied
        request.readonly = True
        return super(ReadOnlyAwareAdmin, self).change_view(request, object_id, extra_context=extra_context)

    def __user_is_readonly(self, request):
        return request.user.isReadOnlyUser()

    def backend_status_text(self, obj):
        return mark_safe(backend_text(obj))

    def backend_status_icon(self, obj):
        return mark_safe(backend_icon(obj))
    backend_status_icon.short_description = ""


class SingletonAdmin (ReadOnlyAwareAdmin):
    def has_add_permission(self, request):
        if not super(SingletonAdmin, self).has_add_permission(request):
            return False

        num_objects = self.model.objects.count()
        if num_objects >= 1:
            return False
        else:
            return True


class PlStackTabularInline(admin.TabularInline):
    def __init__(self, *args, **kwargs):
        super(PlStackTabularInline, self).__init__(*args, **kwargs)

        # InlineModelAdmin as no get_fields() method, so in order to add
        # the selflink field, we override __init__ to modify self.fields and
        # self.readonly_fields.

        self.setup_selflink()

    def get_change_url(self, model, id):
        """ Get the URL to a change form in the admin for this model """
        reverse_path = "admin:%s_change" % (model._meta.db_table)
        try:
            url = reverse(reverse_path, args=(id,))
        except NoReverseMatch:
            return None

        return url

    def setup_selflink(self):
        if hasattr(self, "selflink_fieldname"):
            """ self.selflink_model can be defined to punch through a relation
                to its target object. For example, in SliceNetworkInline, set
                selflink_model = "network", and the URL will lead to the Network
                object instead of trying to bring up a change view of the
                SliceNetwork object.
            """
            self.selflink_model = getattr(self.model,self.selflink_fieldname).field.rel.to
        else:
            self.selflink_model = self.model

        url = self.get_change_url(self.selflink_model, 0)

        # We don't have an admin for this object, so don't create the
        # selflink.
        if (url == None):
            return

        # Since we need to add "selflink" to the field list, we need to create
        # self.fields if it is None.
        if (self.fields is None):
            self.fields = []
            for f in self.model._meta.fields:
                if f.editable and f.name != "id":
                    self.fields.append(f.name)

        self.fields = tuple(self.fields) + ("selflink", )

        if self.readonly_fields is None:
            self.readonly_fields = ()

        self.readonly_fields = tuple(self.readonly_fields) + ("selflink", )

    def selflink(self, obj):
        if hasattr(self, "selflink_fieldname"):
            obj = getattr(obj, self.selflink_fieldname)

        if obj.id:
            url = self.get_change_url(self.selflink_model, obj.id)
            return "<a href='%s'>Details</a>" % str(url)
        else:
            return "Not present"

    selflink.allow_tags = True
    selflink.short_description = "Details"

    def has_add_permission(self, request):
        return not request.user.isReadOnlyUser()

    def get_readonly_fields(self, request, obj=None):
        readonly_fields = list(self.readonly_fields)[:]
        if request.user.isReadOnlyUser():
            for field in self.fields:
                if not field in readonly_fields:
                    readonly_fields.append(field)
        return readonly_fields

    def backend_status_icon(self, obj):
        return mark_safe(backend_icon(obj))
    backend_status_icon.short_description = ""

class PlStackGenericTabularInline(generic.GenericTabularInline):
    def has_add_permission(self, request):
        return not request.user.isReadOnlyUser()

    def get_readonly_fields(self, request, obj=None):
        readonly_fields = list(self.readonly_fields)[:]
        if request.user.isReadOnlyUser():
            for field in self.fields:
                if not field in readonly_fields:
                    readonly_fields.append(field)
        return readonly_fields

    def backend_status_icon(self, obj):
        return mark_safe(backend_icon(obj))
    backend_status_icon.short_description = ""

class ReservationInline(PlStackTabularInline):
    model = Reservation
    extra = 0
    suit_classes = 'suit-tab suit-tab-reservations'

    def queryset(self, request):
        return Reservation.select_by_user(request.user)

class TagInline(PlStackGenericTabularInline):
    model = Tag
    extra = 0
    suit_classes = 'suit-tab suit-tab-tags'
    fields = ['service', 'name', 'value']

    def queryset(self, request):
        return Tag.select_by_user(request.user)

class NetworkLookerUpper:
    """ This is a callable that looks up a network name in a sliver and returns
        the ip address for that network.
    """

    byNetworkName = {}    # class variable

    def __init__(self, name):
        self.short_description = name
        self.__name__ = name
        self.network_name = name

    def __call__(self, obj):
        if obj is not None:
            for nbs in obj.networksliver_set.all():
                if (nbs.network.name == self.network_name):
                    return nbs.ip
        return ""

    def __str__(self):
        return self.network_name

    @staticmethod
    def get(network_name):
        """ We want to make sure we alwars return the same NetworkLookerUpper
            because sometimes django will cause them to be instantiated multiple
            times (and we don't want different ones in form.fields vs
            SliverInline.readonly_fields).
        """
        if network_name not in NetworkLookerUpper.byNetworkName:
            NetworkLookerUpper.byNetworkName[network_name] = NetworkLookerUpper(network_name)
        return NetworkLookerUpper.byNetworkName[network_name]

class SliverInline(PlStackTabularInline):
    model = Sliver
    fields = ['backend_status_icon', 'all_ips_string', 'instance_name', 'slice', 'deploymentNetwork', 'flavor', 'image', 'node']
    extra = 0
    readonly_fields = ['backend_status_icon', 'all_ips_string', 'instance_name']
    suit_classes = 'suit-tab suit-tab-slivers'

    def queryset(self, request):
        return Sliver.select_by_user(request.user)

    def formfield_for_foreignkey(self, db_field, request=None, **kwargs):
        if db_field.name == 'deploymentNetwork':
           kwargs['queryset'] = Deployment.select_by_acl(request.user)
           kwargs['widget'] = forms.Select(attrs={'onChange': "sliver_deployment_changed(this);"})
        elif db_field.name == 'flavor':
           kwargs['widget'] = forms.Select(attrs={'onChange': "sliver_flavor_changed(this);"})

        field = super(SliverInline, self).formfield_for_foreignkey(db_field, request, **kwargs)

        return field

class SiteInline(PlStackTabularInline):
    model = Site
    extra = 0
    suit_classes = 'suit-tab suit-tab-sites'

    def queryset(self, request):
        return Site.select_by_user(request.user)

class UserInline(PlStackTabularInline):
    model = User
    fields = ['backend_status_icon', 'email', 'firstname', 'lastname']
    readonly_fields = ('backend_status_icon', )
    extra = 0
    suit_classes = 'suit-tab suit-tab-users'

    def queryset(self, request):
        return User.select_by_user(request.user)

class SliceInline(PlStackTabularInline):
    model = Slice
    fields = ['backend_status_icon', 'name', 'site', 'serviceClass', 'service']
    readonly_fields = ('backend_status_icon', )
    extra = 0
    suit_classes = 'suit-tab suit-tab-slices'

    def queryset(self, request):
        return Slice.select_by_user(request.user)

class NodeInline(PlStackTabularInline):
    model = Node
    extra = 0
    suit_classes = 'suit-tab suit-tab-nodes'
    fields = ['backend_status_icon', 'name','deployment','site']
    readonly_fields = ('backend_status_icon', )

class DeploymentPrivilegeInline(PlStackTabularInline):
    model = DeploymentPrivilege
    extra = 0
    suit_classes = 'suit-tab suit-tab-deploymentprivileges'
    fields = ['backend_status_icon', 'user','role','deployment']
    readonly_fields = ('backend_status_icon', )

    def queryset(self, request):
        return DeploymentPrivilege.select_by_user(request.user)

class SitePrivilegeInline(PlStackTabularInline):
    model = SitePrivilege
    extra = 0
    suit_classes = 'suit-tab suit-tab-siteprivileges'
    fields = ['backend_status_icon', 'user','site', 'role']
    readonly_fields = ('backend_status_icon', )

    def formfield_for_foreignkey(self, db_field, request, **kwargs):
        if db_field.name == 'site':
            kwargs['queryset'] = Site.select_by_user(request.user)

        if db_field.name == 'user':
            kwargs['queryset'] = User.select_by_user(request.user)
        return super(SitePrivilegeInline, self).formfield_for_foreignkey(db_field, request, **kwargs)

    def queryset(self, request):
        return SitePrivilege.select_by_user(request.user)

class SiteDeploymentInline(PlStackTabularInline):
    model = SiteDeployments
    extra = 0
    suit_classes = 'suit-tab suit-tab-deployments'
    fields = ['backend_status_icon', 'deployment','site']
    readonly_fields = ('backend_status_icon', )

    def formfield_for_foreignkey(self, db_field, request, **kwargs):
        if db_field.name == 'site':
            kwargs['queryset'] = Site.select_by_user(request.user)

        if db_field.name == 'deployment':
            kwargs['queryset'] = Deployment.select_by_user(request.user)
        return super(SiteDeploymentInline, self).formfield_for_foreignkey(db_field, request, **kwargs)

    def queryset(self, request):
        return SiteDeployments.select_by_user(request.user)


class SlicePrivilegeInline(PlStackTabularInline):
    model = SlicePrivilege
    suit_classes = 'suit-tab suit-tab-sliceprivileges'
    extra = 0
    fields = ('backend_status_icon', 'user', 'slice', 'role')
    readonly_fields = ('backend_status_icon', )

    def formfield_for_foreignkey(self, db_field, request, **kwargs):
        if db_field.name == 'slice':
           kwargs['queryset'] = Slice.select_by_user(request.user)
        if db_field.name == 'user':
           kwargs['queryset'] = User.select_by_user(request.user)

        return super(SlicePrivilegeInline, self).formfield_for_foreignkey(db_field, request, **kwargs)

    def queryset(self, request):
        return SlicePrivilege.select_by_user(request.user)

class SliceNetworkInline(PlStackTabularInline):
    model = Network.slices.through
    selflink_fieldname = "network"
    extra = 0
    verbose_name = "Network Connection"
    verbose_name_plural = "Network Connections"
    suit_classes = 'suit-tab suit-tab-slicenetworks'
    fields = ['backend_status_icon', 'network']
    readonly_fields = ('backend_status_icon', )

class ImageDeploymentsInline(PlStackTabularInline):
    model = ImageDeployments
    extra = 0
    verbose_name = "Image Deployments"
    verbose_name_plural = "Image Deployments"
    suit_classes = 'suit-tab suit-tab-imagedeployments'
    fields = ['backend_status_icon', 'image', 'deployment', 'glance_image_id']
    readonly_fields = ['backend_status_icon', 'glance_image_id']

class PlanetStackBaseAdmin(ReadOnlyAwareAdmin):
    save_on_top = False

    def save_model(self, request, obj, form, change):
        obj.caller = request.user
        # update openstack connection to use this site/tenant
        obj.save_by_user(request.user)

    def delete_model(self, request, obj):
        obj.delete_by_user(request.user)

    def save_formset(self, request, form, formset, change):
        instances = formset.save(commit=False)
        for instance in instances:
            instance.save_by_user(request.user)

        # BUG in django 1.7? Objects are not deleted by formset.save if
        # commit is False. So let's delete them ourselves.
        #
        # code from forms/models.py save_existing_objects()
        try:
            forms_to_delete = formset.deleted_forms
        except AttributeError:
            forms_to_delete = []
        if formset.initial_forms:
            for form in formset.initial_forms:
                obj = form.instance
                if form in forms_to_delete:
                    if obj.pk is None:
                        continue
                    formset.deleted_objects.append(obj)
                    obj.delete()

        formset.save_m2m()

class SliceRoleAdmin(PlanetStackBaseAdmin):
    model = SliceRole
    pass

class SiteRoleAdmin(PlanetStackBaseAdmin):
    model = SiteRole
    pass

class DeploymentAdminForm(forms.ModelForm):
    sites = forms.ModelMultipleChoiceField(
        queryset=Site.objects.all(),
        required=False,
        help_text="Select which sites are allowed to host nodes in this deployment",
        widget=FilteredSelectMultiple(
            verbose_name=('Sites'), is_stacked=False
        )
{'fraction_non_alphanumeric': 0.09844309934652333, 'fraction_numerical': 0.001445478362995754, 'mean_word_length': 3.025212121212121, 'pattern_counts': {'":': 4, '<': 25, '<?xml version=': 0, '>': 31, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3188047', 'n_tokens_mistral': 9824, 'n_tokens_neox': 9580, 'n_words': 2235}