class SliverROInline(ReadOnlyTabularInline):
model = Sliver
- fields = ['ip', 'instance_name', 'slice', 'numberCores', 'image', 'node', 'deploymentNetwork']
+ fields = ['ip', 'instance_name', 'slice', 'numberCores', 'deploymentNetwork', 'image', 'node']
suit_classes = 'suit-tab suit-tab-slivers'
class SliverInline(PlStackTabularInline):
model = Sliver
- fields = ['ip', 'instance_name', 'slice', 'numberCores', 'image', 'node', 'deploymentNetwork']
+ fields = ['ip', 'instance_name', 'slice', 'numberCores', 'deploymentNetwork', 'image', 'node']
extra = 0
readonly_fields = ['ip', 'instance_name']
suit_classes = 'suit-tab suit-tab-slivers'
def queryset(self, request):
return Sliver.select_by_user(request.user)
+ 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
+
# 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
model = Node
extra = 0
suit_classes = 'suit-tab suit-tab-nodes'
- fields = ['name','deployment']
+ fields = ['name','deployment','site']
class NodeInline(PlStackTabularInline):
model = Node
extra = 0
suit_classes = 'suit-tab suit-tab-nodes'
- fields = ['name','deployment']
+ fields = ['name','deployment','site']
class DeploymentPrivilegeROInline(ReadOnlyTabularInline):
model = DeploymentPrivilege
suit_classes = 'suit-tab suit-tab-slicenetworks'
fields = ['network']
+class ImageDeploymentsROInline(ReadOnlyTabularInline):
+ model = ImageDeployments
+ extra = 0
+ verbose_name = "Image Deployments"
+ verbose_name_plural = "Image Deployments"
+ suit_classes = 'suit-tab suit-tab-imagedeployments'
+ fields = ['image', 'deployment', 'glance_image_id']
+
class ImageDeploymentsInline(PlStackTabularInline):
model = ImageDeployments
extra = 0
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
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()
class DeploymentAdmin(PlanetStackBaseAdmin):
model = Deployment
- fieldList = ['name','sites', 'accessControl']
+ 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_inlines = [DeploymentPrivilegeROInline,NodeROInline,TagROInline] # ,ImageDeploymentsROInline]
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():
('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]
+ user_readonly_inlines = [SliverROInline, ImageDeploymentsROInline]
class NodeForm(forms.ModelForm):
class Meta: