consolidate API code for core and plus, fix access/default change in sliceplus, shore up caller arguments in update
diff --git a/planetstack/core/xoslib/methods/plus.py b/planetstack/core/xoslib/methods/plus.py
index a50b064..f753620 100644
--- a/planetstack/core/xoslib/methods/plus.py
+++ b/planetstack/core/xoslib/methods/plus.py
@@ -2,6 +2,7 @@
from rest_framework import serializers
from rest_framework.response import Response
from rest_framework import status
+from xosapibase import XOSRetrieveUpdateDestroyAPIView, XOSListCreateAPIView
""" PlusSerializerMixin
@@ -25,87 +26,7 @@
def getBackendHtml(self, obj):
return obj.getBackendHtml()
-# XXX this was lifted and hacked up a bit from genapi.py
-class PlusListCreateAPIView(generics.ListCreateAPIView):
- def create(self, request, *args, **kwargs):
- serializer = self.get_serializer(data=request.DATA, files=request.FILES)
- if not (serializer.is_valid()):
- response = {"error": "validation",
- "specific_error": "not serializer.is_valid()",
- "reasons": serializer.errors}
- return Response(response, status=status.HTTP_400_BAD_REQUEST)
- # now do XOS can_update permission checking
- obj = serializer.object
- obj.caller = request.user
- if not obj.can_update(request.user):
- response = {"error": "validation",
- "specific_error": "failed can_update",
- "reasons": []}
- return Response(response, status=status.HTTP_400_BAD_REQUEST)
- # stuff below is from generics.ListCreateAPIView
-
- if (hasattr(self, "pre_save")):
- # rest_framework 2.x
- self.pre_save(serializer.object)
- self.object = serializer.save(force_insert=True)
- self.post_save(self.object, created=True)
- else:
- # rest_framework 3.x
- self.perform_create(serializer)
-
- headers = self.get_success_headers(serializer.data)
- return Response(serializer.data, status=status.HTTP_201_CREATED,
- headers=headers)
-
-# XXX this is taken from genapi.py
-# XXX find a better way to re-use the code
-class PlusRetrieveUpdateDestroyAPIView(generics.RetrieveUpdateDestroyAPIView):
-
- # To handle fine-grained field permissions, we have to check can_update
- # the object has been updated but before it has been saved.
-
- def update(self, request, *args, **kwargs):
- partial = kwargs.pop('partial', False)
- self.object = self.get_object_or_none()
-
- serializer = self.get_serializer(self.object, data=request.DATA,
- files=request.FILES, partial=partial)
-
- if not serializer.is_valid():
- response = {"error": "validation",
- "specific_error": "not serializer.is_valid()",
- "reasons": serializer.errors}
- return Response(response, status=status.HTTP_400_BAD_REQUEST)
-
- try:
- self.pre_save(serializer.object)
- except ValidationError as err:
- # full_clean on model instance may be called in pre_save,
- # so we have to handle eventual errors.
- response = {"error": "validation",
- "specific_error": "ValidationError in pre_save",
- "reasons": err.message_dict}
- return Response(response, status=status.HTTP_400_BAD_REQUEST)
-
- if serializer.object is not None:
- if not serializer.object.can_update(request.user):
- return Response(status=status.HTTP_400_BAD_REQUEST)
-
- if self.object is None:
- raise Exception("Use the List API for creating objects")
-
- self.object = serializer.save(force_update=True)
- self.object.caller = request.user
- self.post_save(self.object, created=False)
- return Response(serializer.data, status=status.HTTP_200_OK)
-
- def destroy(self, request, *args, **kwargs):
- obj = self.get_object()
- if obj.can_update(request.user):
- return super(generics.RetrieveUpdateDestroyAPIView, self).destroy(request, *args, **kwargs)
- else:
- return Response(status=status.HTTP_400_BAD_REQUEST)
diff --git a/planetstack/core/xoslib/methods/sliceplus.py b/planetstack/core/xoslib/methods/sliceplus.py
index 2af4263..0539e62 100644
--- a/planetstack/core/xoslib/methods/sliceplus.py
+++ b/planetstack/core/xoslib/methods/sliceplus.py
@@ -6,7 +6,8 @@
from core.models import *
from django.forms import widgets
from core.xoslib.objects.sliceplus import SlicePlus
-from plus import PlusSerializerMixin, PlusRetrieveUpdateDestroyAPIView, PlusListCreateAPIView
+from plus import PlusSerializerMixin
+from xosapibase import XOSListCreateAPIView, XOSRetrieveUpdateDestroyAPIView
from rest_framework.exceptions import PermissionDenied as RestFrameworkPermissionDenied
if hasattr(serializers, "ReadOnlyField"):
@@ -70,7 +71,7 @@
'default_image', 'default_flavor',
'serviceClass','creator','networks','sliceInfo','network_ports','backendIcon','backendHtml','site_allocation','site_ready','users',"user_names","current_user_can_see")
-class SlicePlusList(PlusListCreateAPIView):
+class SlicePlusList(XOSListCreateAPIView):
queryset = SlicePlus.objects.select_related().all()
serializer_class = SlicePlusIdSerializer
@@ -98,7 +99,7 @@
return slices
-class SlicePlusDetail(PlusRetrieveUpdateDestroyAPIView):
+class SlicePlusDetail(XOSRetrieveUpdateDestroyAPIView):
queryset = SlicePlus.objects.select_related().all()
serializer_class = SlicePlusIdSerializer
@@ -110,16 +111,4 @@
raise RestFrameworkPermissionDenied("You must be authenticated in order to use this API")
return SlicePlus.select_by_user(self.request.user)
- def update(self, request, *args, **kwargs):
- obj = self.get_object()
- if obj.can_update(request.user):
- return super(SlicePlusDetail, self).update(request, *args, **kwargs)
- else:
- return Response(status=status.HTTP_400_BAD_REQUEST)
- def destroy(self, request, *args, **kwargs):
- obj = self.get_object()
- if obj.can_update(request.user):
- return super(SlicePlusDetail, self).destroy(request, *args, **kwargs)
- else:
- return Response(status=status.HTTP_400_BAD_REQUEST)
diff --git a/planetstack/core/xoslib/objects/sliceplus.py b/planetstack/core/xoslib/objects/sliceplus.py
index 6bbbfa2..47c93d7 100644
--- a/planetstack/core/xoslib/objects/sliceplus.py
+++ b/planetstack/core/xoslib/objects/sliceplus.py
@@ -135,6 +135,9 @@
return nodeList
def save(self, *args, **kwargs):
+ if (not hasattr(self,"caller")) or self.caller==None:
+ raise APIException("no self.caller in SlicePlus.save")
+
updated_image = self.has_field_changed("default_image")
updated_flavor = self.has_field_changed("default_flavor")
@@ -210,6 +213,7 @@
flavor = self.default_flavor,
creator = self.creator,
deployment = node.site_deployment.deployment)
+ sliver.caller = self.caller
slivers.append(sliver)
if (not noAct):
print "added sliver", sliver
@@ -222,7 +226,10 @@
def save_users(self, noAct = False):
new_users = self._update_users
- default_role = SliceRole.objects.get(role="default")
+ try:
+ default_role = SliceRole.objects.get(role="access")
+ except:
+ default_role = SliceRole.objects.get(role="default")
slice_privs = self.sliceprivileges.all()
slice_user_ids = [priv.user.id for priv in slice_privs]
@@ -230,6 +237,7 @@
for user_id in new_users:
if (user_id not in slice_user_ids):
priv = SlicePrivilege(slice=self, user=User.objects.get(id=user_id), role=default_role)
+ priv.caller = self.caller
if (not noAct):
priv.save()
@@ -256,6 +264,7 @@
continue
if network.ports:
network.ports = self._network_ports
+ network.caller = self.caller
if (not noAct):
network.save()
return
@@ -268,6 +277,7 @@
continue
if network.template.translation=="NAT":
network.ports = self._network_ports
+ network.caller = self.caller
if (not noAct):
network.save()
return