selflink.allow_tags = True
selflink.short_description = "Details"
-class ReadOnlyTabularInline(PlStackTabularInline):
- can_delete = False
+ def has_add_permission(self, request):
+ return not request.user.isReadOnlyUser()
def get_readonly_fields(self, request, obj=None):
- return self.fields
+ readonly_fields = list(self.readonly_fields)[:]
+ if request.user.isReadOnlyUser():
+ for field in self.fields:
+ if not field in readonly_fields:
+ readonly_fields.append(field)
+ return readonly_fields
+class PlStackGenericTabularInline(generic.GenericTabularInline):
def has_add_permission(self, request):
- return False
+ return not request.user.isReadOnlyUser()
-class ReservationROInline(ReadOnlyTabularInline):
- model = Reservation
- extra = 0
- suit_classes = 'suit-tab suit-tab-reservations'
- fields = ['startTime','slice','duration']
+ def get_readonly_fields(self, request, obj=None):
+ readonly_fields = list(self.readonly_fields)[:]
+ if request.user.isReadOnlyUser():
+ for field in self.fields:
+ if not field in readonly_fields:
+ readonly_fields.append(field)
+ return readonly_fields
class ReservationInline(PlStackTabularInline):
model = Reservation
def queryset(self, request):
return Reservation.select_by_user(request.user)
-class TagROInline(generic.GenericTabularInline):
- model = Tag
- extra = 0
- suit_classes = 'suit-tab suit-tab-tags'
- can_delete = False
- fields = ['service', 'name', 'value']
-
- def get_readonly_fields(self, request, obj=None):
- return self.fields
-
- def has_add_permission(self, request):
- return False
-
-
-class TagInline(generic.GenericTabularInline):
+class TagInline(PlStackGenericTabularInline):
model = Tag
extra = 0
suit_classes = 'suit-tab suit-tab-tags'
the ip address for that network.
"""
+ byNetworkName = {} # class variable
+
def __init__(self, name):
self.short_description = name
self.__name__ = name
def __str__(self):
return self.network_name
-class SliverROInline(ReadOnlyTabularInline):
- model = Sliver
- fields = ['ip', 'instance_name', 'slice', 'numberCores', 'image', 'node', 'deploymentNetwork']
- suit_classes = 'suit-tab suit-tab-slivers'
+ @staticmethod
+ def get(network_name):
+ """ We want to make sure we alwars return the same NetworkLookerUpper
+ because sometimes django will cause them to be instantiated multiple
+ times (and we don't want different ones in form.fields vs
+ SliverInline.readonly_fields).
+ """
+ if network_name not in NetworkLookerUpper.byNetworkName:
+ NetworkLookerUpper.byNetworkName[network_name] = NetworkLookerUpper(network_name)
+ return NetworkLookerUpper.byNetworkName[network_name]
class SliverInline(PlStackTabularInline):
model = Sliver
- fields = ['ip', 'instance_name', 'slice', 'numberCores', 'image', 'node', 'deploymentNetwork']
+ fields = ['all_ips_string', 'instance_name', 'slice', 'numberCores', 'deploymentNetwork', 'image', 'node']
extra = 0
- readonly_fields = ['ip', 'instance_name']
+ readonly_fields = ['all_ips_string', 'instance_name']
suit_classes = 'suit-tab suit-tab-slivers'
def queryset(self, request):
return Sliver.select_by_user(request.user)
-# Note this is breaking in the admin.py when trying to use an inline to add a node/image
-# def _declared_fieldsets(self):
-# # Return None so django will call get_fieldsets and we can insert our
-# # dynamic fields
-# return None
-#
-# def get_readonly_fields(self, request, obj=None):
-# readonly_fields = super(SliverInline, self).get_readonly_fields(request, obj)
-#
-# # Lookup the networks that are bound to the slivers, and add those
-# # network names to the list of readonly fields.
-#
-# for sliver in obj.slivers.all():
-# for nbs in sliver.networksliver_set.all():
-# if nbs.ip:
-# network_name = nbs.network.name
-# if network_name not in [str(x) for x in readonly_fields]:
-# readonly_fields.append(NetworkLookerUpper(network_name))
-#
-# return readonly_fields
-#
-# def get_fieldsets(self, request, obj=None):
-# form = self.get_formset(request, obj).form
-# # fields = the read/write files + the read-only fields
-# fields = self.fields
-# for fieldName in self.get_readonly_fields(request,obj):
-# if not fieldName in fields:
-# fields.append(fieldName)
-#
-# return [(None, {'fields': fields})]
+ def formfield_for_foreignkey(self, db_field, request=None, **kwargs):
+ if db_field.name == 'deploymentNetwork':
+ kwargs['queryset'] = Deployment.select_by_acl(request.user)
+ # the inscrutable jquery selector below says:
+ # find the closest parent "tr" to the current element
+ # then find the child with class "field-node"
+ # then find the child with that is a select
+ # then return its id
+ kwargs['widget'] = forms.Select(attrs={'onChange': "update_nodes(this, $($(this).closest('tr')[0]).find('.field-node select')[0].id)"})
+ #kwargs['widget'] = forms.Select(attrs={'onChange': "console.log($($($(this).closest('tr')[0]).children('.field-node')[0]).children('select')[0].id);"})
+
+ field = super(SliverInline, self).formfield_for_foreignkey(db_field, request, **kwargs)
-
+ return field
-class SiteROInline(ReadOnlyTabularInline):
- model = Site
- extra = 0
- fields = ['name', 'login_base', 'site_url', 'enabled']
- suit_classes = 'suit-tab suit-tab-sites'
+"""
+ SMBAKER: This is the old code that implemented each network type as a
+ separate column in the sliver table.
+
+ def _declared_fieldsets(self):
+ # Return None so django will call get_fieldsets and we can insert our
+ # dynamic fields
+ return None
+
+ def get_readonly_fields(self, request, obj=None):
+ readonly_fields = list(super(SliverInline, self).get_readonly_fields(request, obj))
+
+ # Lookup the networks that are bound to the slivers, and add those
+ # network names to the list of readonly fields.
+
+ for sliver in obj.slivers.all():
+ for nbs in sliver.networksliver_set.all():
+ if nbs.ip:
+ network_name = nbs.network.name
+ if network_name not in [str(x) for x in readonly_fields]:
+ readonly_fields.append(NetworkLookerUpper.get(network_name))
+
+ return readonly_fields
+
+ def get_fieldsets(self, request, obj=None):
+ form = self.get_formset(request, obj).form
+ # fields = the read/write files + the read-only fields
+ fields = list(self.fields)
+ for fieldName in self.get_readonly_fields(request,obj):
+ if not fieldName in fields:
+ fields.append(fieldName)
+
+ return [(None, {'fields': fields})]
+"""
class SiteInline(PlStackTabularInline):
model = Site
def queryset(self, request):
return Site.select_by_user(request.user)
-class UserROInline(ReadOnlyTabularInline):
- model = User
- fields = ['email', 'firstname', 'lastname']
- extra = 0
- suit_classes = 'suit-tab suit-tab-users'
-
class UserInline(PlStackTabularInline):
model = User
fields = ['email', 'firstname', 'lastname']
def queryset(self, request):
return User.select_by_user(request.user)
-class SliceROInline(ReadOnlyTabularInline):
- model = Slice
- suit_classes = 'suit-tab suit-tab-slices'
- fields = ['name','site', 'serviceClass', 'service']
-
class SliceInline(PlStackTabularInline):
model = Slice
fields = ['name','site', 'serviceClass', 'service']
def queryset(self, request):
return Slice.select_by_user(request.user)
-class NodeROInline(ReadOnlyTabularInline):
- model = Node
- extra = 0
- suit_classes = 'suit-tab suit-tab-nodes'
- fields = ['name','deployment']
-
class NodeInline(PlStackTabularInline):
model = Node
extra = 0
suit_classes = 'suit-tab suit-tab-nodes'
- fields = ['name','deployment']
-
-class DeploymentPrivilegeROInline(ReadOnlyTabularInline):
- model = DeploymentPrivilege
- extra = 0
- suit_classes = 'suit-tab suit-tab-deploymentprivileges'
- fields = ['user','role','deployment']
+ fields = ['name','deployment','site']
class DeploymentPrivilegeInline(PlStackTabularInline):
model = DeploymentPrivilege
def queryset(self, request):
return DeploymentPrivilege.select_by_user(request.user)
-#CLEANUP DOUBLE SitePrivilegeInline
-class SitePrivilegeROInline(ReadOnlyTabularInline):
- model = SitePrivilege
- extra = 0
- suit_classes = 'suit-tab suit-tab-siteprivileges'
- fields = ['user','site', 'role']
-
class SitePrivilegeInline(PlStackTabularInline):
model = SitePrivilege
extra = 0
def queryset(self, request):
return SitePrivilege.select_by_user(request.user)
-class SiteDeploymentROInline(ReadOnlyTabularInline):
- model = SiteDeployments
- #model = Site.deployments.through
- extra = 0
- suit_classes = 'suit-tab suit-tab-deployments'
- fields = ['deployment','site']
-
class SiteDeploymentInline(PlStackTabularInline):
model = SiteDeployments
#model = Site.deployments.through
return SiteDeployments.select_by_user(request.user)
-class SlicePrivilegeROInline(ReadOnlyTabularInline):
- model = SlicePrivilege
- extra = 0
- suit_classes = 'suit-tab suit-tab-sliceprivileges'
- fields = ['user', 'slice', 'role']
-
class SlicePrivilegeInline(PlStackTabularInline):
model = SlicePrivilege
suit_classes = 'suit-tab suit-tab-sliceprivileges'
def queryset(self, request):
return SlicePrivilege.select_by_user(request.user)
-class SliceNetworkROInline(ReadOnlyTabularInline):
- model = Network.slices.through
- extra = 0
- verbose_name = "Network Connection"
- verbose_name_plural = "Network Connections"
- suit_classes = 'suit-tab suit-tab-slicenetworks'
- fields = ['network']
-
class SliceNetworkInline(PlStackTabularInline):
model = Network.slices.through
selflink_fieldname = "network"
verbose_name = "Image Deployments"
verbose_name_plural = "Image Deployments"
suit_classes = 'suit-tab suit-tab-imagedeployments'
- fields = ['deployment', 'glance_image_id']
- readonly_fields = ['deployment', 'glance_image_id']
+ fields = ['image', 'deployment', 'glance_image_id']
+ readonly_fields = ['glance_image_id']
class PlainTextWidget(forms.HiddenInput):
input_type = 'hidden'
sites = forms.ModelMultipleChoiceField(
queryset=Site.objects.all(),
required=False,
+ help_text="Select which sites are allowed to host nodes in this deployment",
widget=FilteredSelectMultiple(
verbose_name=('Sites'), is_stacked=False
)
)
+ images = forms.ModelMultipleChoiceField(
+ queryset=Image.objects.all(),
+ required=False,
+ help_text="Select which images should be deployed on this deployment",
+ widget=FilteredSelectMultiple(
+ verbose_name=('Images'), is_stacked=False
+ )
+ )
class Meta:
model = Deployment
def __init__(self, *args, **kwargs):
+ request = kwargs.pop('request', None)
super(DeploymentAdminForm, self).__init__(*args, **kwargs)
+ self.fields['accessControl'].initial = "allow site " + request.user.site.name
+
if self.instance and self.instance.pk:
self.fields['sites'].initial = [x.site for x in self.instance.sitedeployments_set.all()]
+ self.fields['images'].initial = [x.image for x in self.instance.imagedeployments_set.all()]
+
+ def manipulate_m2m_objs(self, this_obj, selected_objs, all_relations, relation_class, local_attrname, foreign_attrname):
+ """ helper function for handling m2m relations from the MultipleChoiceField
+
+ this_obj: the source object we want to link from
+
+ selected_objs: a list of destination objects we want to link to
+
+ all_relations: the full set of relations involving this_obj, including ones we don't want
+
+ relation_class: the class that implements the relation from source to dest
+
+ local_attrname: field name representing this_obj in relation_class
+
+ foreign_attrname: field name representing selected_objs in relation_class
+
+ This function will remove all newobjclass relations from this_obj
+ that are not contained in selected_objs, and add any relations that
+ are in selected_objs but don't exist in the data model yet.
+ """
+
+ existing_dest_objs = []
+ for relation in list(all_relations):
+ if getattr(relation, foreign_attrname) not in selected_objs:
+ #print "deleting site", sdp.site
+ relation.delete()
+ else:
+ existing_dest_objs.append(getattr(relation, foreign_attrname))
+
+ for dest_obj in selected_objs:
+ if dest_obj not in existing_dest_objs:
+ #print "adding site", site
+ kwargs = {foreign_attrname: dest_obj, local_attrname: this_obj}
+ relation = relation_class(**kwargs)
+ relation.save()
def save(self, commit=True):
deployment = super(DeploymentAdminForm, self).save(commit=False)
# create/destroy the through models ourselves. There has to be
# a better way...
- sites = self.cleaned_data['sites']
-
- existing_sites = []
- for sdp in list(deployment.sitedeployments_set.all()):
- if sdp.site not in sites:
- #print "deleting site", sdp.site
- sdp.delete()
- else:
- existing_sites.append(sdp.site)
-
- for site in sites:
- if site not in existing_sites:
- #print "adding site", site
- sdp = SiteDeployments(site=site, deployment=deployment)
- sdp.save()
+ self.manipulate_m2m_objs(deployment, self.cleaned_data['sites'], deployment.sitedeployments_set.all(), SiteDeployments, "deployment", "site")
+ self.manipulate_m2m_objs(deployment, self.cleaned_data['images'], deployment.imagedeployments_set.all(), ImageDeployments, "deployment", "image")
self.save_m2m()
suit_classes = 'suit-tab suit-tab-sites'
class DeploymentAdmin(PlanetStackBaseAdmin):
- #form = DeploymentAdminForm
model = Deployment
- fieldList = ['name','sites']
+ fieldList = ['name','sites', 'images', 'accessControl']
fieldsets = [(None, {'fields': fieldList, 'classes':['suit-tab suit-tab-sites']})]
- inlines = [DeploymentPrivilegeInline,NodeInline,TagInline]
+ inlines = [DeploymentPrivilegeInline,NodeInline,TagInline] # ,ImageDeploymentsInline]
- user_readonly_inlines = [DeploymentPrivilegeROInline,NodeROInline,TagROInline]
user_readonly_fields = ['name']
- suit_form_tabs =(('sites','Deployment Details'),('nodes','Nodes'),('deploymentprivileges','Privileges'),('tags','Tags'))
+ suit_form_tabs =(('sites','Deployment Details'),('nodes','Nodes'),('deploymentprivileges','Privileges'),('tags','Tags')) # ,('imagedeployments','Images'))
def get_form(self, request, obj=None, **kwargs):
if request.user.isReadOnlyUser():
kwargs["form"] = DeploymentAdminROForm
else:
kwargs["form"] = DeploymentAdminForm
- return super(DeploymentAdmin,self).get_form(request, obj, **kwargs)
-\r
-class ServiceAttrAsTabROInline(ReadOnlyTabularInline):
- model = ServiceAttribute
- fields = ['name','value']
- extra = 0
- suit_classes = 'suit-tab suit-tab-serviceattrs'
+ adminForm = super(DeploymentAdmin,self).get_form(request, obj, **kwargs)
+
+ # from stackexchange: pass the request object into the form
+
+ class AdminFormMetaClass(adminForm):
+ def __new__(cls, *args, **kwargs):
+ kwargs['request'] = request
+ return adminForm(*args, **kwargs)
+
+ return AdminFormMetaClass
class ServiceAttrAsTabInline(PlStackTabularInline):
model = ServiceAttribute
inlines = [ServiceAttrAsTabInline,SliceInline]
user_readonly_fields = fieldList
- user_readonly_inlines = [ServiceAttrAsTabROInline,SliceROInline]
suit_form_tabs =(('general', 'Service Details'),
('slices','Slices'),
readonly_fields = ['accountLink']
user_readonly_fields = ['name', 'deployments','site_url', 'enabled', 'is_public', 'login_base', 'accountLink']
- user_readonly_inlines = [SliceROInline,UserROInline,TagROInline, NodeROInline, SitePrivilegeROInline,SiteDeploymentROInline]
list_display = ('name', 'login_base','site_url', 'enabled')
filter_horizontal = ('deployments',)
inlines = [SlicePrivilegeInline,SliverInline, TagInline, ReservationInline,SliceNetworkInline]
user_readonly_fields = fieldList
- user_readonly_inlines = [SlicePrivilegeROInline,SliverROInline,TagROInline, ReservationROInline, SliceNetworkROInline]
suit_form_tabs =(('general', 'Slice Details'),
('slicenetworks','Networks'),
('reservations','Reservations'),
)
+ def render_change_form(self, request, context, add=False, change=False, form_url='', obj=None):
+ #deployment_nodes = {}
+ #for node in Node.objects.all():
+ # deployment_nodes[node.deployment.id] = get(deployment_nodes, node.deployment.id, []).append( (node.id, node.name) )
+
+ deployment_nodes = []
+ for node in Node.objects.all():
+ deployment_nodes.append( (node.deployment.id, node.id, node.name) )
+
+ context["deployment_nodes"] = deployment_nodes
+
+ return super(SliceAdmin, self).render_change_form(request, context, add, change, form_url, obj)
+
def formfield_for_foreignkey(self, db_field, request, **kwargs):
if db_field.name == 'site':
kwargs['queryset'] = Site.select_by_user(request.user)
def save_model(self, request, obj, form, change):
# update openstack connection to use this site/tenant
auth = request.session.get('auth', {})
- auth['tenant'] = obj.slice.name
+ auth['tenant'] = obj.slice.slicename
obj.os_manager = OpenStackManager(auth=auth, caller=request.user)
obj.save()
def delete_model(self, request, obj):
# update openstack connection to use this site/tenant
auth = request.session.get('auth', {})
- auth['tenant'] = obj.slice.name
+ auth['tenant'] = obj.slice.slicename
obj.os_manager = OpenStackManager(auth=auth, caller=request.user)
obj.delete()
suit_form_tabs =(('general','Image Details'),('slivers','Slivers'),('imagedeployments','Deployments'))
inlines = [SliverInline, ImageDeploymentsInline]
-
+
user_readonly_fields = ['name', 'disk_format', 'container_format']
- user_readonly_inlines = [SliverROInline]
-
+
class NodeForm(forms.ModelForm):
class Meta:
widgets = {
inlines = [TagInline]
user_readonly_fields = ['slice', 'deploymentNetwork', 'node', 'ip', 'instance_name', 'numberCores', 'image']
- user_readonly_inlines = [TagROInline]
def formfield_for_foreignkey(self, db_field, request, **kwargs):
if db_field.name == 'slice':
suit_classes = 'suit-tab suit-tab-dashboards'
fields = ['user', 'dashboardView', 'order']
-class UserDashboardViewROInline(ReadOnlyTabularInline):
- model = UserDashboardView
- extra = 0
- suit_classes = 'suit-tab suit-tab-dashboards'
- fields = ['user', 'dashboardView', 'order']
-
class UserAdmin(UserAdmin):
class Meta:
app_label = "core"
# These override the definitions on the base UserAdmin
# that reference specific fields on auth.User.
list_display = ('email', 'firstname', 'lastname', 'site', 'last_login')
- #list_display = ('email', 'username','firstname', 'lastname', 'is_admin', 'last_login')
list_filter = ('site',)
inlines = [SlicePrivilegeInline,SitePrivilegeInline,DeploymentPrivilegeInline,UserDashboardViewInline]
- fieldListLoginDetails = ['email','site','password','is_readonly','is_amin','public_key']
+ fieldListLoginDetails = ['email','site','password','is_active','is_readonly','is_admin','public_key']
fieldListContactInfo = ['firstname','lastname','phone','timezone']
fieldsets = (
- ('Login Details', {'fields': ['email', 'site','password', 'is_readonly', 'is_admin', 'public_key'], 'classes':['suit-tab suit-tab-general']}),
+ ('Login Details', {'fields': ['email', 'site','password', 'is_active', 'is_readonly', 'is_admin', 'public_key'], 'classes':['suit-tab suit-tab-general']}),
('Contact Information', {'fields': ('firstname','lastname','phone', 'timezone'), 'classes':['suit-tab suit-tab-contact']}),
#('Dashboard Views', {'fields': ('dashboards',), 'classes':['suit-tab suit-tab-dashboards']}),
#('Important dates', {'fields': ('last_login',)}),
filter_horizontal = ()
user_readonly_fields = fieldListLoginDetails + fieldListContactInfo
- user_readonly_inlines = [SlicePrivilegeROInline,SitePrivilegeROInline,DeploymentPrivilegeROInline,UserDashboardViewROInline]
suit_form_tabs =(('general','Login Details'),
('contact','Contact Information'),
# save the original readonly fields\r
self.readonly_save = self.readonly_fields\r
self.inlines_save = self.inlines
- self.readonly_fields=self.user_readonly_fields
- self.inlines = self.user_readonly_inlines
+ if hasattr(self, "user_readonly_fields"):
+ self.readonly_fields=self.user_readonly_fields
+ if hasattr(self, "user_readonly_inlines"):
+ self.inlines = self.user_readonly_inlines
else:
if hasattr(self, "readonly_save"):\r
# restore the original readonly fields\r
suit_form_tabs =(('general','Dashboard View Details'),)
-class ServiceResourceROInline(ReadOnlyTabularInline):
- model = ServiceResource
- extra = 0
- fields = ['serviceClass', 'name', 'maxUnitsDeployment', 'maxUnitsNode', 'maxDuration', 'bucketInRate', 'bucketMaxSize', 'cost', 'calendarReservable']
-
class ServiceResourceInline(PlStackTabularInline):
model = ServiceResource
extra = 0
user_readonly_fields = ['name', 'commitment', 'membershipFee']
user_readonly_inlines = []
-class ReservedResourceROInline(ReadOnlyTabularInline):
- model = ReservedResource
- extra = 0
- fields = ['sliver', 'resource','quantity','reservationSet']
- suit_classes = 'suit-tab suit-tab-reservedresources'
-
class ReservedResourceInline(PlStackTabularInline):
model = ReservedResource
extra = 0
suit_form_tabs = (('general','Reservation Details'), ('reservedresources','Reserved Resources'))
inlines = [ReservedResourceInline]
- user_readonly_inlines = [ReservedResourceROInline]
user_readonly_fields = fieldList
def add_view(self, request, form_url='', extra_context=None):
user_readonly_fields = ['name']
user_readonly_inlines = []
-class RouterROInline(ReadOnlyTabularInline):
- model = Router.networks.through
- extra = 0
- verbose_name_plural = "Routers"
- verbose_name = "Router"
- suit_classes = 'suit-tab suit-tab-routers'
-
- fields = ['name', 'owner', 'permittedNetworks', 'networks']
-
class RouterInline(PlStackTabularInline):
model = Router.networks.through
extra = 0
verbose_name = "Router"
suit_classes = 'suit-tab suit-tab-routers'
-class NetworkParameterROInline(ReadOnlyTabularInline):
+class NetworkParameterInline(PlStackGenericTabularInline):
model = NetworkParameter
- extra = 1
- verbose_name_plural = "Parameters"
- verbose_name = "Parameter"
- suit_classes = 'suit-tab suit-tab-netparams'
- fields = ['parameter', 'value', 'content_type', 'object_id', 'content_object']
-
-class NetworkParameterInline(generic.GenericTabularInline):
- model = NetworkParameter
- extra = 1
+ extra = 0
verbose_name_plural = "Parameters"
verbose_name = "Parameter"
suit_classes = 'suit-tab suit-tab-netparams'
-
-class NetworkSliversROInline(ReadOnlyTabularInline):
- fields = ['network', 'sliver', 'ip', 'port_id']
- model = NetworkSliver
- extra = 0
- verbose_name_plural = "Slivers"
- verbose_name = "Sliver"
- suit_classes = 'suit-tab suit-tab-networkslivers'
+ fields = ['parameter', 'value']
class NetworkSliversInline(PlStackTabularInline):
+ fields = ['network','sliver','ip']
readonly_fields = ("ip", )
model = NetworkSliver
selflink_fieldname = "sliver"
verbose_name = "Sliver"
suit_classes = 'suit-tab suit-tab-networkslivers'
-class NetworkSlicesROInline(ReadOnlyTabularInline):
- model = NetworkSlice
- extra = 0
- verbose_name_plural = "Slices"
- verbose_name = "Slice"
- suit_classes = 'suit-tab suit-tab-networkslices'
- fields = ['network','slice']
-
class NetworkSlicesInline(PlStackTabularInline):
model = NetworkSlice
selflink_fieldname = "slice"
verbose_name_plural = "Slices"
verbose_name = "Slice"
suit_classes = 'suit-tab suit-tab-networkslices'
+ fields = ['network','slice']
class NetworkAdmin(PlanetStackBaseAdmin):
list_display = ("name", "subnet", "ports", "labels")
(None, {'fields': ['name','template','ports','labels','owner','guaranteedBandwidth', 'permitAllSlices','permittedSlices','network_id','router_id','subnet_id','subnet'], 'classes':['suit-tab suit-tab-general']}),]
user_readonly_fields = ['name','template','ports','labels','owner','guaranteedBandwidth', 'permitAllSlices','permittedSlices','network_id','router_id','subnet_id','subnet']
- user_readonly_inlines = [NetworkParameterROInline, NetworkSliversROInline, NetworkSlicesROInline, RouterROInline]
suit_form_tabs =(
('general','Network Details'),