--- /dev/null
+from django.contrib import admin
+
+from syndicate_storage.models import *
+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 core.admin import ReadOnlyTabularInline,ReadOnlyAwareAdmin,SingletonAdmin,SliceInline,ServiceAttrAsTabInline,PlanetStackBaseAdmin, PlStackTabularInline,SliceROInline,ServiceAttrAsTabROInline
+from suit.widgets import LinkedSelect
+from django.core.exceptions import ValidationError, ObjectDoesNotExist
+
+class SyndicateServiceAdmin(SingletonAdmin,ReadOnlyAwareAdmin):
+ model = SyndicateService
+ verbose_name = "Syndicate Storage"
+ verbose_name_plural = "Syndicate Storage"
+ list_display = ("name","enabled")
+ fieldsets = [(None, {'fields': ['name','enabled','versionNumber', 'description',], 'classes':['suit-tab suit-tab-general']})]
+ inlines = [SliceInline,ServiceAttrAsTabInline]
+
+ user_readonly_fields = ['name','enabled','versionNumber','description']
+ user_readonly_inlines = [SliceROInline, ServiceAttrAsTabROInline]
+
+ suit_form_tabs =(('general', 'Syndicate Storage Details'),
+ ('slices','Slices'),
+ ('serviceattrs','Additional Attributes'),
+ )
+
+
+class VolumeAccessRightForUserROInline(ReadOnlyTabularInline):
+ model = VolumeAccessRight
+ extra = 0
+ suit_classes = 'suit-tab suit-tab-volumeAccessRights'
+ fields = ['volume','cap_read_data', 'cap_write_data', 'cap_host_data']
+
+class VolumeAccessRightROInline(ReadOnlyTabularInline):
+ model = VolumeAccessRight
+ extra = 0
+ suit_classes = 'suit-tab suit-tab-volumeAccessRights'
+ fields = ['owner_id','cap_read_data', 'cap_write_data', 'cap_host_data']
+
+class VolumeAccessRightInline(PlStackTabularInline):
+ model = VolumeAccessRight
+ extra = 0
+ suit_classes = 'suit-tab suit-tab-volumeAccessRights'
+
+
+class VolumeSliceFormSet( forms.models.BaseInlineFormSet ):
+ # verify that our VolumeSlice is valid
+
+ @classmethod
+ def verify_unchanged( cls, volume_pk, slice_pk, field_name, new_value ):
+ vs = None
+ try:
+ vs = VolumeSlice.objects.get( volume_id=volume_pk, slice_id=slice_pk )
+ except ObjectDoesNotExist, dne:
+ return True, None
+
+ old_value = getattr( vs, field_name )
+ if old_value != new_value:
+ return False, old_value
+ else:
+ return True, None
+
+
+ def clean( self ):
+ for form in self.forms:
+ # check each inline's cleaned data, if it's valid
+ cleaned_data = None
+ try:
+ if form.cleaned_data:
+ cleaned_data = form.cleaned_data
+ except AttributeError:
+ continue
+
+ # verify that the ports haven't changed
+ volume_pk = cleaned_data['volume_id'].pk
+ slice_pk = cleaned_data['slice_id'].pk
+
+ if not cleaned_data.has_key('UG_portnum'):
+ raise ValidationError("Missing UG port number")
+
+ if not cleaned_data.has_key('RG_portnum'):
+ raise ValidationError("Missing RG port number")
+
+ rc1, old_peer_port = VolumeSliceFormSet.verify_unchanged( volume_pk, slice_pk, 'UG_portnum', cleaned_data['UG_portnum'] )
+ rc2, old_replicate_port = VolumeSliceFormSet.verify_unchanged( volume_pk, slice_pk, 'RG_portnum', cleaned_data['RG_portnum'] )
+
+ err1str = ""
+ err2str = ""
+ if not rc1:
+ err1str = "change %s back to %s" % (cleaned_data['UG_portnum'], old_peer_port)
+ if not rc2:
+ err2str = " and change %s back to %s" % (cleaned_data['RG_portnum'], old_replicate_port )
+
+ if not rc1 or not rc2:
+ raise ValidationError("At this time, port numbers cannot be changed once they are set. Please %s %s" % (err1str, err2str))
+
+
+
+class VolumeSliceInline(PlStackTabularInline):
+ model = VolumeSlice
+ extra = 0
+ suit_classes = 'suit-tab suit-tab-volumeSlices'
+ fields = ['volume_id', 'slice_id', 'cap_read_data', 'cap_write_data', 'cap_host_data', 'UG_portnum', 'RG_portnum']
+
+ formset = VolumeSliceFormSet
+
+ readonly_fields = ['credentials_blob']
+
+
+class VolumeSliceROInline(ReadOnlyTabularInline):
+ model = VolumeSlice
+ extra = 0
+ suit_classes = 'suit-tab suit-tab-volumeSlices'
+ fields = ['volume_id', 'slice_id', 'cap_read_data', 'cap_write_data', 'cap_host_data', 'UG_portnum', 'RG_portnum']
+
+ formset = VolumeSliceFormSet
+
+ readonly_fields = ['credentials_blob']
+
+
+class VolumeAdmin(ReadOnlyAwareAdmin):
+ model = Volume
+
+ def get_readonly_fields(self, request, obj=None ):
+ always_readonly = []
+ if obj == None:
+ # all fields are editable on add
+ return always_readonly
+
+ else:
+ # can't change owner, slice id, or block size on update
+ return ['blocksize', 'owner_id'] + always_readonly
+
+
+ list_display = ['name', 'owner_id']
+
+ detailsFieldList = ['name', 'owner_id', 'description','blocksize', 'private','archive', 'cap_read_data', 'cap_write_data', 'cap_host_data' ]
+
+ fieldsets = [
+ (None, {'fields': detailsFieldList, 'classes':['suit-tab suit-tab-general']}),
+ ]
+
+ inlines = [VolumeAccessRightInline, VolumeSliceInline]
+
+ user_readonly_fields = ['name','owner_id','description','blocksize','private', 'archive', 'cap_read_data', 'cap_write_data', 'cap_host_data']
+
+ user_readonly_inlines = [VolumeAccessRightROInline, VolumeSliceROInline]
+
+ suit_form_tabs =(('general', 'Volume Details'),
+ ('volumeSlices', 'Slices'),
+ ('volumeAccessRights', 'Volume Access Rights'))
+
+ def queryset(self, request):
+ # only show volumes that are public, or owned by the caller
+ return Volume.select_by_user(request.user)
+
+
+# left panel:
+admin.site.register(SyndicateService, SyndicateServiceAdmin)
+admin.site.register(Volume, VolumeAdmin)