blob: 66e07dd164d82fc87e6337b2405c26bb5b291be4 [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 Bakera9b8f612015-02-26 20:42:11 -080013from core.admin import ReadOnlyAwareAdmin,ServiceAppAdmin,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
Scott Baker43f2d672015-02-27 12:17:38 -080017class SyndicateAdmin(ReadOnlyAwareAdmin):
18 # Change the application breadcrumb to point to an RR Service if one is
19 # defined
20
21 change_form_template = "admin/change_form_bc.html"
22 change_list_template = "admin/change_list_bc.html"
23 custom_app_breadcrumb_name = "Syndicate_Storage"
24 @property
25 def custom_app_breadcrumb_url(self):
26 services = SyndicateService.objects.all()
27 if len(services)==1:
28 return "/admin/syndicate_storage/syndicateservice/%s/" % services[0].id
29 else:
30 return "/admin/syncdicate_storage/syndicateservice/"
31
Scott Bakera9b8f612015-02-26 20:42:11 -080032class SyndicateServiceAdmin(ServiceAppAdmin):
Siobhan Tullycf04fb62014-01-11 11:25:57 -050033 model = SyndicateService
jcnelson575a1352014-07-10 19:33:34 -040034 verbose_name = "Syndicate Storage"
35 verbose_name_plural = "Syndicate Storage"
Siobhan Tullycf04fb62014-01-11 11:25:57 -050036 list_display = ("name","enabled")
37 fieldsets = [(None, {'fields': ['name','enabled','versionNumber', 'description',], 'classes':['suit-tab suit-tab-general']})]
38 inlines = [SliceInline,ServiceAttrAsTabInline]
39
40 user_readonly_fields = ['name','enabled','versionNumber','description']
Siobhan Tullycf04fb62014-01-11 11:25:57 -050041
jcnelson575a1352014-07-10 19:33:34 -040042 suit_form_tabs =(('general', 'Syndicate Storage Details'),
Scott Bakerb0057432015-02-26 17:16:25 -080043 ('administration', 'Administration'),
Siobhan Tullycf04fb62014-01-11 11:25:57 -050044 ('slices','Slices'),
45 ('serviceattrs','Additional Attributes'),
46 )
47
Scott Bakerb0057432015-02-26 17:16:25 -080048 suit_form_includes = (('syndicateadmin.html', 'top', 'administration'),)
49
Scott Baker65a670a2014-05-08 22:14:13 -070050
Scott Baker67db95f2015-02-18 15:50:11 -080051class VolumeAccessRightInline(XOSTabularInline):
Siobhan Tullycf04fb62014-01-11 11:25:57 -050052 model = VolumeAccessRight
53 extra = 0
54 suit_classes = 'suit-tab suit-tab-volumeAccessRights'
Siobhan Tullycf04fb62014-01-11 11:25:57 -050055
Scott Baker65a670a2014-05-08 22:14:13 -070056
57class VolumeSliceFormSet( forms.models.BaseInlineFormSet ):
58 # verify that our VolumeSlice is valid
59
60 @classmethod
61 def verify_unchanged( cls, volume_pk, slice_pk, field_name, new_value ):
62 vs = None
63 try:
64 vs = VolumeSlice.objects.get( volume_id=volume_pk, slice_id=slice_pk )
65 except ObjectDoesNotExist, dne:
66 return True, None
67
68 old_value = getattr( vs, field_name )
69 if old_value != new_value:
70 return False, old_value
71 else:
72 return True, None
73
74
75 def clean( self ):
76 for form in self.forms:
77 # check each inline's cleaned data, if it's valid
78 cleaned_data = None
79 try:
80 if form.cleaned_data:
81 cleaned_data = form.cleaned_data
82 except AttributeError:
83 continue
jcnelson575a1352014-07-10 19:33:34 -040084
Scott Baker65a670a2014-05-08 22:14:13 -070085 # verify that the ports haven't changed
86 volume_pk = cleaned_data['volume_id'].pk
87 slice_pk = cleaned_data['slice_id'].pk
88
jcnelson575a1352014-07-10 19:33:34 -040089 if not cleaned_data.has_key('UG_portnum'):
90 raise ValidationError("Missing UG port number")
Scott Baker65a670a2014-05-08 22:14:13 -070091
jcnelson575a1352014-07-10 19:33:34 -040092 if not cleaned_data.has_key('RG_portnum'):
93 raise ValidationError("Missing RG port number")
Scott Baker65a670a2014-05-08 22:14:13 -070094
jcnelson575a1352014-07-10 19:33:34 -040095 rc1, old_peer_port = VolumeSliceFormSet.verify_unchanged( volume_pk, slice_pk, 'UG_portnum', cleaned_data['UG_portnum'] )
96 rc2, old_replicate_port = VolumeSliceFormSet.verify_unchanged( volume_pk, slice_pk, 'RG_portnum', cleaned_data['RG_portnum'] )
Scott Baker65a670a2014-05-08 22:14:13 -070097
98 err1str = ""
99 err2str = ""
100 if not rc1:
jcnelson575a1352014-07-10 19:33:34 -0400101 err1str = "change %s back to %s" % (cleaned_data['UG_portnum'], old_peer_port)
Scott Baker65a670a2014-05-08 22:14:13 -0700102 if not rc2:
jcnelson575a1352014-07-10 19:33:34 -0400103 err2str = " and change %s back to %s" % (cleaned_data['RG_portnum'], old_replicate_port )
Scott Baker65a670a2014-05-08 22:14:13 -0700104
105 if not rc1 or not rc2:
jcnelson575a1352014-07-10 19:33:34 -0400106 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 -0700107
108
109
Scott Baker67db95f2015-02-18 15:50:11 -0800110class VolumeSliceInline(XOSTabularInline):
Scott Baker65a670a2014-05-08 22:14:13 -0700111 model = VolumeSlice
112 extra = 0
113 suit_classes = 'suit-tab suit-tab-volumeSlices'
jcnelson575a1352014-07-10 19:33:34 -0400114 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 -0700115
116 formset = VolumeSliceFormSet
117
118 readonly_fields = ['credentials_blob']
119
120
Scott Baker43f2d672015-02-27 12:17:38 -0800121class VolumeAdmin(SyndicateAdmin):
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500122 model = Volume
Scott Baker65a670a2014-05-08 22:14:13 -0700123
124 def get_readonly_fields(self, request, obj=None ):
jcnelson575a1352014-07-10 19:33:34 -0400125 always_readonly = []
Scott Baker65a670a2014-05-08 22:14:13 -0700126 if obj == None:
127 # all fields are editable on add
128 return always_readonly
129
130 else:
131 # can't change owner, slice id, or block size on update
132 return ['blocksize', 'owner_id'] + always_readonly
133
134
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500135 list_display = ['name', 'owner_id']
136
jcnelson575a1352014-07-10 19:33:34 -0400137 detailsFieldList = ['name', 'owner_id', 'description','blocksize', 'private','archive', 'cap_read_data', 'cap_write_data', 'cap_host_data' ]
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500138
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500139 fieldsets = [
140 (None, {'fields': detailsFieldList, 'classes':['suit-tab suit-tab-general']}),
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500141 ]
142
Scott Baker65a670a2014-05-08 22:14:13 -0700143 inlines = [VolumeAccessRightInline, VolumeSliceInline]
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500144
jcnelson575a1352014-07-10 19:33:34 -0400145 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 -0700146
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500147 suit_form_tabs =(('general', 'Volume Details'),
Scott Baker65a670a2014-05-08 22:14:13 -0700148 ('volumeSlices', 'Slices'),
jcnelson575a1352014-07-10 19:33:34 -0400149 ('volumeAccessRights', 'Volume Access Rights'))
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500150
jcnelson575a1352014-07-10 19:33:34 -0400151 def queryset(self, request):
152 # only show volumes that are public, or owned by the caller
153 return Volume.select_by_user(request.user)
154
155
Scott Baker65a670a2014-05-08 22:14:13 -0700156# left panel:
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500157admin.site.register(SyndicateService, SyndicateServiceAdmin)
Siobhan Tullycf04fb62014-01-11 11:25:57 -0500158admin.site.register(Volume, VolumeAdmin)