1 from django.contrib import admin
3 from syndicate_storage.models import *
4 from django import forms
5 from django.utils.safestring import mark_safe
6 from django.contrib.auth.admin import UserAdmin
7 from django.contrib.admin.widgets import FilteredSelectMultiple
8 from django.contrib.auth.forms import ReadOnlyPasswordHashField
9 from django.contrib.auth.signals import user_logged_in
10 from django.utils import timezone
11 from django.contrib.contenttypes import generic
12 from suit.widgets import LinkedSelect
13 from core.admin import ReadOnlyTabularInline,ReadOnlyAwareAdmin,SingletonAdmin,SliceInline,ServiceAttrAsTabInline,PlanetStackBaseAdmin, PlStackTabularInline,SliceROInline,ServiceAttrAsTabROInline
14 from suit.widgets import LinkedSelect
15 from django.core.exceptions import ValidationError, ObjectDoesNotExist
17 class SyndicateServiceAdmin(SingletonAdmin,ReadOnlyAwareAdmin):
18 model = SyndicateService
19 verbose_name = "Syndicate Storage"
20 verbose_name_plural = "Syndicate Storage"
21 list_display = ("name","enabled")
22 fieldsets = [(None, {'fields': ['name','enabled','versionNumber', 'description',], 'classes':['suit-tab suit-tab-general']})]
23 inlines = [SliceInline,ServiceAttrAsTabInline]
25 user_readonly_fields = ['name','enabled','versionNumber','description']
26 user_readonly_inlines = [SliceROInline, ServiceAttrAsTabROInline]
28 suit_form_tabs =(('general', 'Syndicate Storage Details'),
30 ('serviceattrs','Additional Attributes'),
34 class VolumeAccessRightForUserROInline(ReadOnlyTabularInline):
35 model = VolumeAccessRight
37 suit_classes = 'suit-tab suit-tab-volumeAccessRights'
38 fields = ['volume','cap_read_data', 'cap_write_data', 'cap_host_data']
40 class VolumeAccessRightROInline(ReadOnlyTabularInline):
41 model = VolumeAccessRight
43 suit_classes = 'suit-tab suit-tab-volumeAccessRights'
44 fields = ['owner_id','cap_read_data', 'cap_write_data', 'cap_host_data']
46 class VolumeAccessRightInline(PlStackTabularInline):
47 model = VolumeAccessRight
49 suit_classes = 'suit-tab suit-tab-volumeAccessRights'
52 class VolumeSliceFormSet( forms.models.BaseInlineFormSet ):
53 # verify that our VolumeSlice is valid
56 def verify_unchanged( cls, volume_pk, slice_pk, field_name, new_value ):
59 vs = VolumeSlice.objects.get( volume_id=volume_pk, slice_id=slice_pk )
60 except ObjectDoesNotExist, dne:
63 old_value = getattr( vs, field_name )
64 if old_value != new_value:
65 return False, old_value
71 for form in self.forms:
72 # check each inline's cleaned data, if it's valid
76 cleaned_data = form.cleaned_data
77 except AttributeError:
80 # verify that the ports haven't changed
81 volume_pk = cleaned_data['volume_id'].pk
82 slice_pk = cleaned_data['slice_id'].pk
84 if not cleaned_data.has_key('UG_portnum'):
85 raise ValidationError("Missing UG port number")
87 if not cleaned_data.has_key('RG_portnum'):
88 raise ValidationError("Missing RG port number")
90 rc1, old_peer_port = VolumeSliceFormSet.verify_unchanged( volume_pk, slice_pk, 'UG_portnum', cleaned_data['UG_portnum'] )
91 rc2, old_replicate_port = VolumeSliceFormSet.verify_unchanged( volume_pk, slice_pk, 'RG_portnum', cleaned_data['RG_portnum'] )
96 err1str = "change %s back to %s" % (cleaned_data['UG_portnum'], old_peer_port)
98 err2str = " and change %s back to %s" % (cleaned_data['RG_portnum'], old_replicate_port )
100 if not rc1 or not rc2:
101 raise ValidationError("At this time, port numbers cannot be changed once they are set. Please %s %s" % (err1str, err2str))
105 class VolumeSliceInline(PlStackTabularInline):
108 suit_classes = 'suit-tab suit-tab-volumeSlices'
109 fields = ['volume_id', 'slice_id', 'cap_read_data', 'cap_write_data', 'cap_host_data', 'UG_portnum', 'RG_portnum']
111 formset = VolumeSliceFormSet
113 readonly_fields = ['credentials_blob']
116 class VolumeSliceROInline(ReadOnlyTabularInline):
119 suit_classes = 'suit-tab suit-tab-volumeSlices'
120 fields = ['volume_id', 'slice_id', 'cap_read_data', 'cap_write_data', 'cap_host_data', 'UG_portnum', 'RG_portnum']
122 formset = VolumeSliceFormSet
124 readonly_fields = ['credentials_blob']
127 class VolumeAdmin(ReadOnlyAwareAdmin):
130 def get_readonly_fields(self, request, obj=None ):
133 # all fields are editable on add
134 return always_readonly
137 # can't change owner, slice id, or block size on update
138 return ['blocksize', 'owner_id'] + always_readonly
141 list_display = ['name', 'owner_id']
143 detailsFieldList = ['name', 'owner_id', 'description','blocksize', 'private','archive', 'cap_read_data', 'cap_write_data', 'cap_host_data' ]
146 (None, {'fields': detailsFieldList, 'classes':['suit-tab suit-tab-general']}),
149 inlines = [VolumeAccessRightInline, VolumeSliceInline]
151 user_readonly_fields = ['name','owner_id','description','blocksize','private', 'archive', 'cap_read_data', 'cap_write_data', 'cap_host_data']
153 user_readonly_inlines = [VolumeAccessRightROInline, VolumeSliceROInline]
155 suit_form_tabs =(('general', 'Volume Details'),
156 ('volumeSlices', 'Slices'),
157 ('volumeAccessRights', 'Volume Access Rights'))
159 def queryset(self, request):
160 # only show volumes that are public, or owned by the caller
161 return Volume.select_by_user(request.user)
165 admin.site.register(SyndicateService, SyndicateServiceAdmin)
166 admin.site.register(Volume, VolumeAdmin)