blob: e9f499c260b94cc560452fcc13c3e4f7327fb887 [file] [log] [blame]
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001from django.contrib import admin
2
3from syndicate.models import *
4from django import forms
5from django.utils.safestring import mark_safe
6from django.contrib.auth.admin import UserAdmin
7from django.contrib.admin.widgets import FilteredSelectMultiple
8from django.contrib.auth.forms import ReadOnlyPasswordHashField
9from django.contrib.auth.signals import user_logged_in
10from django.utils import timezone
11from django.contrib.contenttypes import generic
12from suit.widgets import LinkedSelect
13from core.admin import ReadOnlyTabularInline,ReadOnlyAwareAdmin,SingletonAdmin,SliceInline,ServiceAttrAsTabInline,PlanetStackBaseAdmin, PlStackTabularInline,SliceROInline,ServiceAttrAsTabROInline
14from suit.widgets import LinkedSelect
15from bitfield import BitField
16from bitfield.forms import BitFieldCheckboxSelectMultiple
Scott Baker65a670a2014-05-08 22:14:13 -070017from django.core.exceptions import ValidationError, ObjectDoesNotExist
Siobhan Tullycf04fb62014-01-11 11:25:57 -050018
19class SyndicateServiceAdmin(SingletonAdmin,ReadOnlyAwareAdmin):
20 model = SyndicateService
21 verbose_name = "Syndicate Service"
22 verbose_name_plural = "Syndicate Service"
23 list_display = ("name","enabled")
24 fieldsets = [(None, {'fields': ['name','enabled','versionNumber', 'description',], 'classes':['suit-tab suit-tab-general']})]
25 inlines = [SliceInline,ServiceAttrAsTabInline]
26
27 user_readonly_fields = ['name','enabled','versionNumber','description']
28 user_readonly_inlines = [SliceROInline, ServiceAttrAsTabROInline]
29
30 suit_form_tabs =(('general', 'Syndicate Service Details'),
31 ('slices','Slices'),
32 ('serviceattrs','Additional Attributes'),
33 )
34
Scott Baker65a670a2014-05-08 22:14:13 -070035
Siobhan Tullycf04fb62014-01-11 11:25:57 -050036class VolumeAccessRightForUserROInline(ReadOnlyTabularInline):
37 model = VolumeAccessRight
38 extra = 0
39 suit_classes = 'suit-tab suit-tab-volumeAccessRights'
40 fields = ['volume','gateway_caps']
41
42class VolumeAccessRightROInline(ReadOnlyTabularInline):
43 model = VolumeAccessRight
44 extra = 0
45 suit_classes = 'suit-tab suit-tab-volumeAccessRights'
46 fields = ['owner_id','gateway_caps']
47
48class VolumeAccessRightInline(PlStackTabularInline):
49 model = VolumeAccessRight
50 extra = 0
51 suit_classes = 'suit-tab suit-tab-volumeAccessRights'
Scott Baker65a670a2014-05-08 22:14:13 -070052 formfield_overrides = {
53 BitField: {'widget': BitFieldCheckboxSelectMultiple}
54 }
Scott Baker2a21ba12014-06-03 12:25:40 -070055 fields = ('owner_id', 'gateway_caps')
Siobhan Tullycf04fb62014-01-11 11:25:57 -050056
57class VolumeInline(PlStackTabularInline):
58 model = Volume
59 extra = 0
60 suit_classes = 'suit-tab suit-tab-volumes'
61 fields = ['name', 'owner_id']
62
63class VolumeROInline(ReadOnlyTabularInline):
64 model = Volume
65 extra = 0
66 suit_classes = 'suit-tab suit-tab-volumes'
67 fields = ['name', 'owner_id']
68
Scott Baker65a670a2014-05-08 22:14:13 -070069
70class VolumeSliceFormSet( forms.models.BaseInlineFormSet ):
71 # verify that our VolumeSlice is valid
72
73 @classmethod
74 def verify_unchanged( cls, volume_pk, slice_pk, field_name, new_value ):
75 vs = None
76 try:
77 vs = VolumeSlice.objects.get( volume_id=volume_pk, slice_id=slice_pk )
78 except ObjectDoesNotExist, dne:
79 return True, None
80
81 old_value = getattr( vs, field_name )
82 if old_value != new_value:
83 return False, old_value
84 else:
85 return True, None
86
87
88 def clean( self ):
89 for form in self.forms:
90 # check each inline's cleaned data, if it's valid
91 cleaned_data = None
92 try:
93 if form.cleaned_data:
94 cleaned_data = form.cleaned_data
95 except AttributeError:
96 continue
97
98 # verify that the ports haven't changed
99 volume_pk = cleaned_data['volume_id'].pk
100 slice_pk = cleaned_data['slice_id'].pk
101
102 if not cleaned_data.has_key('peer_portnum'):
103 raise ValidationError("Missing client peer-to-peer cache port number")
104
105 if not cleaned_data.has_key('replicate_portnum'):
106 raise ValidationError("Missing replication service port number")
107
108 rc1, old_peer_port = VolumeSliceFormSet.verify_unchanged( volume_pk, slice_pk, 'peer_portnum', cleaned_data['peer_portnum'] )
109 rc2, old_replicate_port = VolumeSliceFormSet.verify_unchanged( volume_pk, slice_pk, 'replicate_portnum', cleaned_data['replicate_portnum'] )
110
111 err1str = ""
112 err2str = ""
113 if not rc1:
114 err1str = "change %s back to %s" % (cleaned_data['peer_portnum'], old_peer_port)
115 if not rc2:
116 err2str = " and change %s back to %s" % (cleaned_data['replicate_portnum'], old_replicate_port )
117
118 if not rc1 or not rc2:
119 raise ValidationError("Port numbers cannot be changed once they are set. Please %s %s" % (err1str, err2str))
120
121
122
123class VolumeSliceInline(PlStackTabularInline):
124 model = VolumeSlice
125 extra = 0
126 suit_classes = 'suit-tab suit-tab-volumeSlices'
127 fields = ['volume_id', 'slice_id', 'gateway_caps', 'peer_portnum', 'replicate_portnum']
128 formfield_overrides = { BitField: {'widget': BitFieldCheckboxSelectMultiple},}
129
130 formset = VolumeSliceFormSet
131
132 readonly_fields = ['credentials_blob']
133
134
135class VolumeSliceROInline(ReadOnlyTabularInline):
136 model = VolumeSlice
137 extra = 0
138 suit_classes = 'suit-tab suit-tab-volumeSlices'
139 fields = ['volume_id', 'slice_id', 'gateway_caps', 'peer_portnum', 'replicate_portnum']
140 formfield_overrides = { BitField: {'widget': BitFieldCheckboxSelectMultiple},}
141
142 formset = VolumeSliceFormSet
143
144 readonly_fields = ['credentials_blob']
145
146
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500147class VolumeAdmin(ReadOnlyAwareAdmin):
148 model = Volume
Scott Baker65a670a2014-05-08 22:14:13 -0700149
150 def get_readonly_fields(self, request, obj=None ):
Scott Baker2b230c62014-06-03 12:34:18 -0700151 always_readonly = list(super(VolumeAdmin, self).get_readonly_fields(request, obj))
Scott Baker65a670a2014-05-08 22:14:13 -0700152 if obj == None:
153 # all fields are editable on add
154 return always_readonly
155
156 else:
157 # can't change owner, slice id, or block size on update
158 return ['blocksize', 'owner_id'] + always_readonly
159
160
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500161 list_display = ['name', 'owner_id']
162
163 formfield_overrides = { BitField: {'widget': BitFieldCheckboxSelectMultiple},}
164
Scott Baker65a670a2014-05-08 22:14:13 -0700165 #detailsFieldList = ['name', 'owner_id', 'description','file_quota','blocksize', 'private','archive', 'default_gateway_caps' ]
166 detailsFieldList = ['name', 'owner_id', 'description','blocksize', 'private','archive', 'default_gateway_caps' ]
167
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500168 fieldsets = [
169 (None, {'fields': detailsFieldList, 'classes':['suit-tab suit-tab-general']}),
Scott Baker65a670a2014-05-08 22:14:13 -0700170 #(None, {'fields': keyList, 'classes':['suit-tab suit-tab-volumeKeys']}),
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500171 ]
172
Scott Baker65a670a2014-05-08 22:14:13 -0700173 inlines = [VolumeAccessRightInline, VolumeSliceInline]
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500174
Scott Baker65a670a2014-05-08 22:14:13 -0700175 user_readonly_fields = ['name','owner_id','description','blocksize','private','default_gateway_caps']
176
177 user_readonly_inlines = [VolumeAccessRightROInline, VolumeSliceROInline]
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500178
179 suit_form_tabs =(('general', 'Volume Details'),
Scott Baker65a670a2014-05-08 22:14:13 -0700180 #('volumeKeys', 'Access Keys'),
181 ('volumeSlices', 'Slices'),
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500182 ('volumeAccessRights', 'Volume Access Rights'),
183 )
184
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500185
Scott Baker65a670a2014-05-08 22:14:13 -0700186# left panel:
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500187admin.site.register(SyndicateService, SyndicateServiceAdmin)
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500188admin.site.register(Volume, VolumeAdmin)