blob: 6e36758519037eef9dc113478855bea5eb5773a1 [file] [log] [blame]
Siobhan Tullycf04fb62014-01-11 11:25:57 -05001from django.contrib import admin
2
jcnelson575a1352014-07-10 19:33:34 -04003from syndicate_storage.models import *
Siobhan Tullycf04fb62014-01-11 11:25:57 -05004from 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
Scott Baker022cdcd2015-02-18 15:50:11 -080013from core.admin import ReadOnlyAwareAdmin,SingletonAdmin,SliceInline,ServiceAttrAsTabInline,XOSBaseAdmin, XOSTabularInline
Siobhan Tullycf04fb62014-01-11 11:25:57 -050014from suit.widgets import LinkedSelect
Scott Baker65a670a2014-05-08 22:14:13 -070015from django.core.exceptions import ValidationError, ObjectDoesNotExist
Siobhan Tullycf04fb62014-01-11 11:25:57 -050016
17class SyndicateServiceAdmin(SingletonAdmin,ReadOnlyAwareAdmin):
18 model = SyndicateService
jcnelson575a1352014-07-10 19:33:34 -040019 verbose_name = "Syndicate Storage"
20 verbose_name_plural = "Syndicate Storage"
Siobhan Tullycf04fb62014-01-11 11:25:57 -050021 list_display = ("name","enabled")
22 fieldsets = [(None, {'fields': ['name','enabled','versionNumber', 'description',], 'classes':['suit-tab suit-tab-general']})]
23 inlines = [SliceInline,ServiceAttrAsTabInline]
24
25 user_readonly_fields = ['name','enabled','versionNumber','description']
Siobhan Tullycf04fb62014-01-11 11:25:57 -050026
jcnelson575a1352014-07-10 19:33:34 -040027 suit_form_tabs =(('general', 'Syndicate Storage Details'),
Siobhan Tullycf04fb62014-01-11 11:25:57 -050028 ('slices','Slices'),
29 ('serviceattrs','Additional Attributes'),
30 )
31
Scott Baker65a670a2014-05-08 22:14:13 -070032
Scott Baker022cdcd2015-02-18 15:50:11 -080033class VolumeAccessRightInline(XOSTabularInline):
Siobhan Tullycf04fb62014-01-11 11:25:57 -050034 model = VolumeAccessRight
35 extra = 0
36 suit_classes = 'suit-tab suit-tab-volumeAccessRights'
Siobhan Tullycf04fb62014-01-11 11:25:57 -050037
Scott Baker65a670a2014-05-08 22:14:13 -070038
39class VolumeSliceFormSet( forms.models.BaseInlineFormSet ):
40 # verify that our VolumeSlice is valid
41
42 @classmethod
43 def verify_unchanged( cls, volume_pk, slice_pk, field_name, new_value ):
44 vs = None
45 try:
46 vs = VolumeSlice.objects.get( volume_id=volume_pk, slice_id=slice_pk )
47 except ObjectDoesNotExist, dne:
48 return True, None
49
50 old_value = getattr( vs, field_name )
51 if old_value != new_value:
52 return False, old_value
53 else:
54 return True, None
55
56
57 def clean( self ):
58 for form in self.forms:
59 # check each inline's cleaned data, if it's valid
60 cleaned_data = None
61 try:
62 if form.cleaned_data:
63 cleaned_data = form.cleaned_data
64 except AttributeError:
65 continue
jcnelson575a1352014-07-10 19:33:34 -040066
Scott Baker65a670a2014-05-08 22:14:13 -070067 # verify that the ports haven't changed
68 volume_pk = cleaned_data['volume_id'].pk
69 slice_pk = cleaned_data['slice_id'].pk
70
jcnelson575a1352014-07-10 19:33:34 -040071 if not cleaned_data.has_key('UG_portnum'):
72 raise ValidationError("Missing UG port number")
Scott Baker65a670a2014-05-08 22:14:13 -070073
jcnelson575a1352014-07-10 19:33:34 -040074 if not cleaned_data.has_key('RG_portnum'):
75 raise ValidationError("Missing RG port number")
Scott Baker65a670a2014-05-08 22:14:13 -070076
jcnelson575a1352014-07-10 19:33:34 -040077 rc1, old_peer_port = VolumeSliceFormSet.verify_unchanged( volume_pk, slice_pk, 'UG_portnum', cleaned_data['UG_portnum'] )
78 rc2, old_replicate_port = VolumeSliceFormSet.verify_unchanged( volume_pk, slice_pk, 'RG_portnum', cleaned_data['RG_portnum'] )
Scott Baker65a670a2014-05-08 22:14:13 -070079
80 err1str = ""
81 err2str = ""
82 if not rc1:
jcnelson575a1352014-07-10 19:33:34 -040083 err1str = "change %s back to %s" % (cleaned_data['UG_portnum'], old_peer_port)
Scott Baker65a670a2014-05-08 22:14:13 -070084 if not rc2:
jcnelson575a1352014-07-10 19:33:34 -040085 err2str = " and change %s back to %s" % (cleaned_data['RG_portnum'], old_replicate_port )
Scott Baker65a670a2014-05-08 22:14:13 -070086
87 if not rc1 or not rc2:
jcnelson575a1352014-07-10 19:33:34 -040088 raise ValidationError("At this time, port numbers cannot be changed once they are set. Please %s %s" % (err1str, err2str))
Scott Baker65a670a2014-05-08 22:14:13 -070089
90
91
Scott Baker022cdcd2015-02-18 15:50:11 -080092class VolumeSliceInline(XOSTabularInline):
Scott Baker65a670a2014-05-08 22:14:13 -070093 model = VolumeSlice
94 extra = 0
95 suit_classes = 'suit-tab suit-tab-volumeSlices'
jcnelson575a1352014-07-10 19:33:34 -040096 fields = ['volume_id', 'slice_id', 'cap_read_data', 'cap_write_data', 'cap_host_data', 'UG_portnum', 'RG_portnum']
Scott Baker65a670a2014-05-08 22:14:13 -070097
98 formset = VolumeSliceFormSet
99
100 readonly_fields = ['credentials_blob']
101
102
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500103class VolumeAdmin(ReadOnlyAwareAdmin):
104 model = Volume
Scott Baker65a670a2014-05-08 22:14:13 -0700105
106 def get_readonly_fields(self, request, obj=None ):
jcnelson575a1352014-07-10 19:33:34 -0400107 always_readonly = []
Scott Baker65a670a2014-05-08 22:14:13 -0700108 if obj == None:
109 # all fields are editable on add
110 return always_readonly
111
112 else:
113 # can't change owner, slice id, or block size on update
114 return ['blocksize', 'owner_id'] + always_readonly
115
116
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500117 list_display = ['name', 'owner_id']
118
jcnelson575a1352014-07-10 19:33:34 -0400119 detailsFieldList = ['name', 'owner_id', 'description','blocksize', 'private','archive', 'cap_read_data', 'cap_write_data', 'cap_host_data' ]
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500120
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500121 fieldsets = [
122 (None, {'fields': detailsFieldList, 'classes':['suit-tab suit-tab-general']}),
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500123 ]
124
Scott Baker65a670a2014-05-08 22:14:13 -0700125 inlines = [VolumeAccessRightInline, VolumeSliceInline]
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500126
jcnelson575a1352014-07-10 19:33:34 -0400127 user_readonly_fields = ['name','owner_id','description','blocksize','private', 'archive', 'cap_read_data', 'cap_write_data', 'cap_host_data']
Scott Baker65a670a2014-05-08 22:14:13 -0700128
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500129 suit_form_tabs =(('general', 'Volume Details'),
Scott Baker65a670a2014-05-08 22:14:13 -0700130 ('volumeSlices', 'Slices'),
jcnelson575a1352014-07-10 19:33:34 -0400131 ('volumeAccessRights', 'Volume Access Rights'))
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500132
jcnelson575a1352014-07-10 19:33:34 -0400133 def queryset(self, request):
134 # only show volumes that are public, or owned by the caller
135 return Volume.select_by_user(request.user)
136
137
Scott Baker65a670a2014-05-08 22:14:13 -0700138# left panel:
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500139admin.site.register(SyndicateService, SyndicateServiceAdmin)
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500140admin.site.register(Volume, VolumeAdmin)