refactor and bug fixes
[plstackapi.git] / planetstack / core / admin.py
index ffa21d9..bc84554 100644 (file)
@@ -340,7 +340,7 @@ class NetworkLookerUpper:
 
 class SliverInline(PlStackTabularInline):
     model = Sliver
-    fields = ['backend_status_icon', 'all_ips_string', 'instance_name', 'slice', 'deploymentNetwork', 'flavor', 'image', 'node']
+    fields = ['backend_status_icon', 'all_ips_string', 'instance_name', 'slice', 'controllerNetwork', 'flavor', 'image', 'node']
     extra = 0
     readonly_fields = ['backend_status_icon', 'all_ips_string', 'instance_name']
     suit_classes = 'suit-tab suit-tab-slivers'
@@ -349,7 +349,7 @@ class SliverInline(PlStackTabularInline):
         return Sliver.select_by_user(request.user)
 
     def formfield_for_foreignkey(self, db_field, request=None, **kwargs):
-        if db_field.name == 'deploymentNetwork':
+        if db_field.name == 'controllerNetwork':
            kwargs['queryset'] = Deployment.select_by_acl(request.user)
            kwargs['widget'] = forms.Select(attrs={'onChange': "sliver_deployment_changed(this);"})
         elif db_field.name == 'flavor':
@@ -391,9 +391,19 @@ class NodeInline(PlStackTabularInline):
     model = Node
     extra = 0
     suit_classes = 'suit-tab suit-tab-nodes'
-    fields = ['backend_status_icon', 'name','deployment','site']
+    fields = ['backend_status_icon', 'name', 'site_deployment']
     readonly_fields = ('backend_status_icon', )
 
+class DeploymentPrivilegeInline(PlStackTabularInline):
+    model = DeploymentPrivilege
+    extra = 0
+    suit_classes = 'suit-tab suit-tab-admin-only'
+    fields = ['backend_status_icon', 'user','role','deployment']
+    readonly_fields = ('backend_status_icon', )
+
+    def queryset(self, request):
+        return DeploymentPrivilege.select_by_user(request.user)
+
 class ControllerPrivilegeInline(PlStackTabularInline):
     model = ControllerPrivilege
     extra = 0
@@ -404,6 +414,12 @@ class ControllerPrivilegeInline(PlStackTabularInline):
     def queryset(self, request):
         return ControllerPrivilege.select_by_user(request.user)
 
+class ControllerSiteDeploymentsInline(PlStackTabularInline):
+    model = ControllerSiteDeployments
+    extra = 0
+    suit_classes = 'suit-tab suit-tab-admin-only'
+    fields = ['controller', 'site_deployment', 'tenant_id']
+
 class SitePrivilegeInline(PlStackTabularInline):
     model = SitePrivilege
     extra = 0
@@ -426,7 +442,7 @@ class SiteDeploymentsInline(PlStackTabularInline):
     model = SiteDeployments
     extra = 0
     suit_classes = 'suit-tab suit-tab-deployments'
-    fields = ['backend_status_icon', 'deployment','site']
+    fields = ['backend_status_icon', 'deployment','site', 'controller']
     readonly_fields = ('backend_status_icon', )
 
     def formfield_for_foreignkey(self, db_field, request, **kwargs):
@@ -435,28 +451,14 @@ class SiteDeploymentsInline(PlStackTabularInline):
 
         if db_field.name == 'deployment':
             kwargs['queryset'] = Deployment.select_by_user(request.user)
-        return super(SiteDeploymentsInline, self).formfield_for_foreignkey(db_field, request, **kwargs)
-
-    def queryset(self, request):
-        return SiteDeployments.select_by_user(request.user)
-
-class ControllerSitesInline(PlStackTabularInline):
-    model = ControllerSites
-    extra = 0
-    suit_classes = 'suit-tab suit-tab-admin-only'
-    fields = ['backend_status_icon', 'controller','site']
-    readonly_fields = ('backend_status_icon', )
-
-    def formfield_for_foreignkey(self, db_field, request, **kwargs):
-        if db_field.name == 'site':
-            kwargs['queryset'] = Site.select_by_user(request.user)
 
         if db_field.name == 'controller':
             kwargs['queryset'] = Controller.select_by_user(request.user)
-        return super(ControllerSitesInline, self).formfield_for_foreignkey(db_field, request, **kwargs)
+
+        return super(SiteDeploymentsInline, self).formfield_for_foreignkey(db_field, request, **kwargs)
 
     def queryset(self, request):
-        return ControllerSites.select_by_user(request.user)
+        return SiteDeployments.select_by_user(request.user)
 
 
 class SlicePrivilegeInline(PlStackTabularInline):
@@ -602,7 +604,7 @@ class DeploymentAdminForm(forms.ModelForm):
         #    a better way...
 
         self.manipulate_m2m_objs(deployment, self.cleaned_data['sites'], deployment.sitedeployments.all(), SiteDeployments, "deployment", "site")
-        self.manipulate_m2m_objs(deployment, self.cleaned_data['images'], deployment.imagedeployments.all(), ControllerImages, "deployment", "image")
+        self.manipulate_m2m_objs(deployment, self.cleaned_data['images'], deployment.imagedeployments.all(), DeploymentImages, "deployment", "image")
 
       self.save_m2m()
 
@@ -619,16 +621,20 @@ class SiteAssocInline(PlStackTabularInline):
 
 class DeploymentAdmin(PlanetStackBaseAdmin):
     model = Deployment
-    fieldList = ['backend_status_text', 'name', 'availability_zone', 'sites', 'images', 'flavors', 'accessControl']
+    fieldList = ['backend_status_text', 'name', 'sites', 'images', 'flavors', 'accessControl']
     fieldsets = [(None, {'fields': fieldList, 'classes':['suit-tab suit-tab-sites']})]
-    inlines = [ControllerPrivilegeInline,NodeInline,TagInline] # ,ControllerImagesInline]
+    # node no longer directly connected to deployment
+    #inlines = [DeploymentPrivilegeInline,NodeInline,TagInline,ImageDeploymentsInline]
+    inlines = [DeploymentPrivilegeInline,TagInline,ImageDeploymentsInline]
     list_display = ['backend_status_icon', 'name']
     list_display_links = ('backend_status_icon', 'name', )
     readonly_fields = ('backend_status_text', )
 
     user_readonly_fields = ['name']
 
-    suit_form_tabs =(('sites','Deployment Details'),('nodes','Nodes'),('deploymentprivileges','Privileges'),('tags','Tags')) # ,('imagedeployments','Images'))
+    # nodes no longer direclty connected to deployments
+    #suit_form_tabs =(('sites','Deployment Details'),('nodes','Nodes'),('deploymentprivileges','Privileges'),('tags','Tags'),('imagedeployments','Images'))
+    suit_form_tabs =(('sites','Deployment Details'),('deploymentprivileges','Privileges'),('tags','Tags'),('imagedeployments','Images'))
 
     def get_form(self, request, obj=None, **kwargs):
         if request.user.isReadOnlyUser():
@@ -646,6 +652,96 @@ class DeploymentAdmin(PlanetStackBaseAdmin):
 
         return AdminFormMetaClass
 
+class ControllerAdminForm(forms.ModelForm):
+    site_deployments = forms.ModelMultipleChoiceField(
+        queryset=SiteDeployments.objects.all(),
+        required=False,
+        help_text="Select which sites deployments are managed by this controller",
+        widget=FilteredSelectMultiple(
+            verbose_name=('Site Deployments'), is_stacked=False
+        )
+    )
+
+    class Meta: 
+        model = Controller
+        
+    def __init__(self, *args, **kwargs):
+        request = kwargs.pop('request', None)
+        super(ControllerAdminForm, self).__init__(*args, **kwargs)  
+
+        if self.instance and self.instance.pk:
+            self.fields['site_deployments'].initial = [x.site_deployment for x in self.instance.controllersitedeployments.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):
+        controller = super(ControllerAdminForm, self).save(commit=False)
+        if commit:
+            controller.save()
+
+        if controller.pk:
+            # save_m2m() doesn't seem to work with 'through' relations. So we
+            #    create/destroy the through models ourselves. There has to be
+            #    a better way...
+            self.manipulate_m2m_objs(controller, self.cleaned_data['site_deployments'], controller.controllersitedeployments.all(), ControllerSiteDeployments, "controller", "site_deployment")
+
+        self.save_m2m()
+
+        return controller 
+      
+class ControllerAdmin(PlanetStackBaseAdmin):
+    model = Controller 
+    fieldList = ['name', 'version', 'backend_type', 'auth_url', 'admin_user', 'admin_tenant','admin_password']
+    #fieldsets = [(None, {'fields': fieldList, 'classes':['suit-tab suit-tab-general']})]
+    inlines = [ControllerSiteDeploymentsInline] # ,ControllerImagesInline]
+    list_display = ['backend_status_icon', 'name', 'version', 'backend_type']
+    list_display_links = ('backend_status_icon', 'name', )
+    readonly_fields = ('backend_status_text',)
+
+    user_readonly_fields = []
+
+    def get_form(self, request, obj=None, **kwargs):
+        print self.fieldsets
+        if request.user.isReadOnlyUser():
+            kwargs["form"] = ControllerAdminROForm
+        else:
+            kwargs["form"] = ControllerAdminForm
+        adminForm = super(ControllerAdmin,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
     fields = ['name','value']
@@ -678,7 +774,7 @@ class SiteAdmin(PlanetStackBaseAdmin):
         ('siteprivileges','Privileges'),
         ('deployments','Deployments'),
         ('slices','Slices'),
-        ('nodes','Nodes'),
+        #('nodes','Nodes'),
         ('tags','Tags'),
     )
     readonly_fields = ['backend_status_text', 'accountLink']
@@ -688,7 +784,7 @@ class SiteAdmin(PlanetStackBaseAdmin):
     list_display = ('backend_status_icon', 'name', 'login_base','site_url', 'enabled')
     list_display_links = ('backend_status_icon', 'name', )
     filter_horizontal = ('deployments',)
-    inlines = [SliceInline,UserInline,TagInline, NodeInline, SitePrivilegeInline, SiteDeploymentsInline]
+    inlines = [SliceInline,UserInline,TagInline, SitePrivilegeInline, SiteDeploymentsInline]
     search_fields = ['name']
 
     def queryset(self, request):
@@ -832,7 +928,6 @@ class SliceAdmin(PlanetStackBaseAdmin):
         return super(SliceAdmin, self).add_view(request, form_url, extra_context=extra_context)
 
     def change_view(self, request, object_id, form_url='', extra_context=None):
-        print object_id
         # cannot change the site of an existing slice so make the site field read only
         if object_id:
             self.readonly_fields = ('backend_status_text','site')
@@ -848,10 +943,10 @@ class SliceAdmin(PlanetStackBaseAdmin):
             for deployment in flavor.deployments.all():
                 deployment_flavors.append( (deployment.id, flavor.id, flavor.name) )
 
-        controller_images = []
+        deployment_images = []
         for image in Image.objects.all():
-            for controller_image in image.controllerimages.all():
-                controller_images.append( (controller_image.controller.id, image.id, image.name) )
+            for deployment_image in image.imagedeployments.all():
+                deployment_images.append( (deployment_image.controller.id, image.id, image.name) )
 
         site_login_bases = []
         for site in Site.objects.all():
@@ -949,15 +1044,15 @@ class NodeForm(forms.ModelForm):
 
 class NodeAdmin(PlanetStackBaseAdmin):
     form = NodeForm
-    list_display = ('backend_status_icon', 'name', 'site', 'deployment')
+    list_display = ('backend_status_icon', 'name', 'site_deployment')
     list_display_links = ('backend_status_icon', 'name', )
-    list_filter = ('deployment',)
+    list_filter = ('site_deployment',)
 
     inlines = [TagInline,SliverInline]
-    fieldsets = [('Node Details', {'fields': ['backend_status_text', 'name','site','deployment'], 'classes':['suit-tab suit-tab-details']})]
+    fieldsets = [('Node Details', {'fields': ['backend_status_text', 'name','site_deployment'], 'classes':['suit-tab suit-tab-details']})]
     readonly_fields = ('backend_status_text', )
 
-    user_readonly_fields = ['name','site','deployment']
+    user_readonly_fields = ['name','site_deployment']
     user_readonly_inlines = [TagInline,SliverInline]
 
     suit_form_tabs =(('details','Node Details'),('slivers','Slivers'),('tags','Tags'))
@@ -972,7 +1067,7 @@ class SliverForm(forms.ModelForm):
             'ip': PlainTextWidget(),
             'instance_name': PlainTextWidget(),
             'slice': LinkedSelect,
-            'deploymentNetwork': LinkedSelect,
+            'controllerNetwork': LinkedSelect,
             'node': LinkedSelect,
             'image': LinkedSelect
         }
@@ -986,10 +1081,10 @@ class TagAdmin(PlanetStackBaseAdmin):
 class SliverAdmin(PlanetStackBaseAdmin):
     form = SliverForm
     fieldsets = [
-        ('Sliver Details', {'fields': ['backend_status_text', 'slice', 'deploymentNetwork', 'node', 'ip', 'instance_name', 'flavor', 'image', ], 'classes': ['suit-tab suit-tab-general'], })
+        ('Sliver Details', {'fields': ['backend_status_text', 'slice', 'controllerNetwork', 'node', 'ip', 'instance_name', 'flavor', 'image', ], 'classes': ['suit-tab suit-tab-general'], })
     ]
     readonly_fields = ('backend_status_text', )
-    list_display = ['backend_status_icon', 'ip', 'instance_name', 'slice', 'flavor', 'image', 'node', 'deploymentNetwork']
+    list_display = ['backend_status_icon', 'ip', 'instance_name', 'slice', 'flavor', 'image', 'node', 'controllerNetwork']
     list_display_links = ('backend_status_icon', 'ip',)
 
     suit_form_tabs =(('general', 'Sliver Details'),
@@ -998,7 +1093,7 @@ class SliverAdmin(PlanetStackBaseAdmin):
 
     inlines = [TagInline]
 
-    user_readonly_fields = ['slice', 'deploymentNetwork', 'node', 'ip', 'instance_name', 'flavor', 'image']
+    user_readonly_fields = ['slice', 'controllerNetwork', 'node', 'ip', 'instance_name', 'flavor', 'image']
 
     def formfield_for_foreignkey(self, db_field, request, **kwargs):
         if db_field.name == 'slice':