blob: fd306a286903a6db1742416a0593d8cf1c2ffb95 [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 }
Siobhan Tullycf04fb62014-01-11 11:25:57 -050055
56class VolumeInline(PlStackTabularInline):
57 model = Volume
58 extra = 0
59 suit_classes = 'suit-tab suit-tab-volumes'
60 fields = ['name', 'owner_id']
61
62class VolumeROInline(ReadOnlyTabularInline):
63 model = Volume
64 extra = 0
65 suit_classes = 'suit-tab suit-tab-volumes'
66 fields = ['name', 'owner_id']
67
Scott Baker65a670a2014-05-08 22:14:13 -070068
69class VolumeSliceFormSet( forms.models.BaseInlineFormSet ):
70 # verify that our VolumeSlice is valid
71
72 @classmethod
73 def verify_unchanged( cls, volume_pk, slice_pk, field_name, new_value ):
74 vs = None
75 try:
76 vs = VolumeSlice.objects.get( volume_id=volume_pk, slice_id=slice_pk )
77 except ObjectDoesNotExist, dne:
78 return True, None
79
80 old_value = getattr( vs, field_name )
81 if old_value != new_value:
82 return False, old_value
83 else:
84 return True, None
85
86
87 def clean( self ):
88 for form in self.forms:
89 # check each inline's cleaned data, if it's valid
90 cleaned_data = None
91 try:
92 if form.cleaned_data:
93 cleaned_data = form.cleaned_data
94 except AttributeError:
95 continue
96
97 # verify that the ports haven't changed
98 volume_pk = cleaned_data['volume_id'].pk
99 slice_pk = cleaned_data['slice_id'].pk
100
101 if not cleaned_data.has_key('peer_portnum'):
102 raise ValidationError("Missing client peer-to-peer cache port number")
103
104 if not cleaned_data.has_key('replicate_portnum'):
105 raise ValidationError("Missing replication service port number")
106
107 rc1, old_peer_port = VolumeSliceFormSet.verify_unchanged( volume_pk, slice_pk, 'peer_portnum', cleaned_data['peer_portnum'] )
108 rc2, old_replicate_port = VolumeSliceFormSet.verify_unchanged( volume_pk, slice_pk, 'replicate_portnum', cleaned_data['replicate_portnum'] )
109
110 err1str = ""
111 err2str = ""
112 if not rc1:
113 err1str = "change %s back to %s" % (cleaned_data['peer_portnum'], old_peer_port)
114 if not rc2:
115 err2str = " and change %s back to %s" % (cleaned_data['replicate_portnum'], old_replicate_port )
116
117 if not rc1 or not rc2:
118 raise ValidationError("Port numbers cannot be changed once they are set. Please %s %s" % (err1str, err2str))
119
120
121
122class VolumeSliceInline(PlStackTabularInline):
123 model = VolumeSlice
124 extra = 0
125 suit_classes = 'suit-tab suit-tab-volumeSlices'
126 fields = ['volume_id', 'slice_id', 'gateway_caps', 'peer_portnum', 'replicate_portnum']
127 formfield_overrides = { BitField: {'widget': BitFieldCheckboxSelectMultiple},}
128
129 formset = VolumeSliceFormSet
130
131 readonly_fields = ['credentials_blob']
132
133
134class VolumeSliceROInline(ReadOnlyTabularInline):
135 model = VolumeSlice
136 extra = 0
137 suit_classes = 'suit-tab suit-tab-volumeSlices'
138 fields = ['volume_id', 'slice_id', 'gateway_caps', 'peer_portnum', 'replicate_portnum']
139 formfield_overrides = { BitField: {'widget': BitFieldCheckboxSelectMultiple},}
140
141 formset = VolumeSliceFormSet
142
143 readonly_fields = ['credentials_blob']
144
145
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500146class VolumeAdmin(ReadOnlyAwareAdmin):
147 model = Volume
Scott Baker65a670a2014-05-08 22:14:13 -0700148
149 def get_readonly_fields(self, request, obj=None ):
150 always_readonly = []
151 if obj == None:
152 # all fields are editable on add
153 return always_readonly
154
155 else:
156 # can't change owner, slice id, or block size on update
157 return ['blocksize', 'owner_id'] + always_readonly
158
159
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500160 list_display = ['name', 'owner_id']
161
162 formfield_overrides = { BitField: {'widget': BitFieldCheckboxSelectMultiple},}
163
Scott Baker65a670a2014-05-08 22:14:13 -0700164 #detailsFieldList = ['name', 'owner_id', 'description','file_quota','blocksize', 'private','archive', 'default_gateway_caps' ]
165 detailsFieldList = ['name', 'owner_id', 'description','blocksize', 'private','archive', 'default_gateway_caps' ]
166
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500167 fieldsets = [
168 (None, {'fields': detailsFieldList, 'classes':['suit-tab suit-tab-general']}),
Scott Baker65a670a2014-05-08 22:14:13 -0700169 #(None, {'fields': keyList, 'classes':['suit-tab suit-tab-volumeKeys']}),
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500170 ]
171
Scott Baker65a670a2014-05-08 22:14:13 -0700172 inlines = [VolumeAccessRightInline, VolumeSliceInline]
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500173
Scott Baker65a670a2014-05-08 22:14:13 -0700174 user_readonly_fields = ['name','owner_id','description','blocksize','private','default_gateway_caps']
175
176 user_readonly_inlines = [VolumeAccessRightROInline, VolumeSliceROInline]
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500177
178 suit_form_tabs =(('general', 'Volume Details'),
Scott Baker65a670a2014-05-08 22:14:13 -0700179 #('volumeKeys', 'Access Keys'),
180 ('volumeSlices', 'Slices'),
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500181 ('volumeAccessRights', 'Volume Access Rights'),
182 )
183
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500184
Scott Baker65a670a2014-05-08 22:14:13 -0700185# left panel:
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500186admin.site.register(SyndicateService, SyndicateServiceAdmin)
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500187admin.site.register(Volume, VolumeAdmin)