support creating disks

Signed-off-by: Nico Schottelius <nico@nico-notebook.schottelius.org>
This commit is contained in:
Nico Schottelius 2020-02-29 17:57:57 +01:00
parent 6a38e4e0a4
commit 5c33bc5c02
4 changed files with 71 additions and 18 deletions

View file

@ -26,14 +26,27 @@ router = routers.DefaultRouter()
# user / regular urls # user / regular urls
router.register(r'vm/snapshot', vmviews.VMSnapshotProductViewSet, basename='vmsnapshotproduct') router.register(r'vm/snapshot', vmviews.VMSnapshotProductViewSet, basename='vmsnapshotproduct')
router.register(r'vm/disk', vmviews.VMDiskProductViewSet, basename='vmdiskproduct')
router.register(r'vm/image/mine', vmviews.VMDiskImageProductMineViewSet, basename='vmdiskimagemineproduct') router.register(r'vm/image/mine', vmviews.VMDiskImageProductMineViewSet, basename='vmdiskimagemineproduct')
router.register(r'vm/image/public', vmviews.VMDiskImageProductPublicViewSet, basename='vmdiskimagepublicproduct') router.register(r'vm/image/public', vmviews.VMDiskImageProductPublicViewSet, basename='vmdiskimagepublicproduct')
# images the provider provides :-)
# router.register(r'vm/image/official', vmviews.VMDiskImageProductPublicViewSet, basename='vmdiskimagepublicproduct')
#router.register(r'vm/disk', vmviews.VMDiskProductViewSet, basename='vmdiskproduct')
router.register(r'vm/vm', vmviews.VMProductViewSet, basename='vmproduct') router.register(r'vm/vm', vmviews.VMProductViewSet, basename='vmproduct')
# TBD
#router.register(r'vm/disk', vmviews.VMDiskProductViewSet, basename='vmdiskproduct')
# creates VM from os image
#router.register(r'vm/ipv6onlyvm', vmviews.VMProductViewSet, basename='vmproduct')
# ... AND adds IPv4 mapping
#router.register(r'vm/dualstackvm', vmviews.VMProductViewSet, basename='vmproduct')
# allow vm creation from own images
# Pay # Pay

View file

@ -4,6 +4,16 @@ import uuid
from uncloud_pay.models import Product from uncloud_pay.models import Product
STATUS_CHOICES = (
('pending', 'Pending'), # Initial state
('creating', 'Creating'), # Creating VM/image/etc.
('active', 'Active'), # Is usable / active
('disabled', 'Disabled'), # Is usable, but cannot be used for new things
('unusable', 'Unusable'), # Has some kind of error
('deleted', 'Deleted'), # Does not exist anymore, only DB entry as a log
)
STATUS_DEFAULT='pending'
class VMHost(models.Model): class VMHost(models.Model):
uuid = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) uuid = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
@ -22,13 +32,8 @@ class VMHost(models.Model):
status = models.CharField(max_length=32, status = models.CharField(max_length=32,
choices = ( choices=STATUS_CHOICES,
('pending', 'Pending'), default=STATUS_DEFAULT
('active', 'Active'),
('unusable', 'Unusable'),
('deleted', 'Deleted'),
),
default='pending'
) )
@ -80,13 +85,10 @@ class VMDiskImageProduct(models.Model):
default='ssd' default='ssd'
) )
# source = models.CharField(max_length=32, status = models.CharField(max_length=32,
# choices = ( choices=STATUS_CHOICES,
# ('url', 'HDD'), default=STATUS_DEFAULT
# ('ssd', 'SSD'), )
# ),
# default='ssd'
# )
class VMDiskProduct(models.Model): class VMDiskProduct(models.Model):
""" """
@ -105,7 +107,7 @@ class VMDiskProduct(models.Model):
vm = models.ForeignKey(VMProduct, on_delete=models.CASCADE) vm = models.ForeignKey(VMProduct, on_delete=models.CASCADE)
image = models.ForeignKey(VMDiskImageProduct, on_delete=models.CASCADE) image = models.ForeignKey(VMDiskImageProduct, on_delete=models.CASCADE)
size_in_gb = models.FloatField() size_in_gb = models.FloatField(blank=True)
class VMNetworkCard(models.Model): class VMNetworkCard(models.Model):

View file

@ -22,6 +22,8 @@ class VMProductSerializer(serializers.ModelSerializer):
fields = '__all__' fields = '__all__'
class VMDiskProductSerializer(serializers.ModelSerializer): class VMDiskProductSerializer(serializers.ModelSerializer):
# vm = VMProductSerializer()
class Meta: class Meta:
model = VMDiskProduct model = VMDiskProduct
fields = '__all__' fields = '__all__'

View file

@ -5,11 +5,13 @@ from django.shortcuts import get_object_or_404
from rest_framework import viewsets, permissions from rest_framework import viewsets, permissions
from rest_framework.response import Response from rest_framework.response import Response
from rest_framework.exceptions import ValidationError
from .models import VMHost, VMProduct, VMSnapshotProduct, VMDiskProduct, VMDiskImageProduct from .models import VMHost, VMProduct, VMSnapshotProduct, VMDiskProduct, VMDiskImageProduct
from uncloud_pay.models import Order from uncloud_pay.models import Order
from .serializers import VMHostSerializer, VMProductSerializer, VMSnapshotProductSerializer, VMDiskImageProductSerializer from .serializers import VMHostSerializer, VMProductSerializer, VMSnapshotProductSerializer, VMDiskImageProductSerializer, VMDiskProductSerializer
import datetime import datetime
@ -27,8 +29,14 @@ class VMDiskImageProductMineViewSet(viewsets.ModelViewSet):
return VMDiskImageProduct.objects.filter(owner=self.request.user) return VMDiskImageProduct.objects.filter(owner=self.request.user)
def create(self, request): def create(self, request):
serializer = VMProductSerializer(data=request.data, context={'request': request}) serializer = VMDiskImageProductSerializer(data=request.data, context={'request': request})
serializer.is_valid(raise_exception=True) serializer.is_valid(raise_exception=True)
# did not specify size NOR import url?
if not serializer.validated_data['size_in_gb']:
if not serializer.validated_data['import_url']:
raise ValidationError(detail={ 'error_mesage': 'Specify either import_url or size_in_gb' })
serializer.save(owner=request.user) serializer.save(owner=request.user)
return Response(serializer.data) return Response(serializer.data)
@ -40,6 +48,34 @@ class VMDiskImageProductPublicViewSet(viewsets.ReadOnlyModelViewSet):
def get_queryset(self): def get_queryset(self):
return VMDiskImageProduct.objects.filter(is_public=True) return VMDiskImageProduct.objects.filter(is_public=True)
class VMDiskProductViewSet(viewsets.ModelViewSet):
"""
Let a user modify their own VMDisks
"""
permission_classes = [permissions.IsAuthenticated]
serializer_class = VMDiskProductSerializer
def get_queryset(self):
return VMDiskProduct.objects.filter(owner=self.request.user)
def create(self, request):
serializer = VMDiskProductSerializer(data=request.data, context={'request': request})
serializer.is_valid(raise_exception=True)
# get disk size from image, if not specified
if not 'size_in_gb' in serializer.validated_data:
size_in_gb = serializer.validated_data['image'].size_in_gb
else:
size_in_gb = serializer.validated_data['size_in_gb']
if size_in_gb < serializer.validated_data['image'].size_in_gb:
raise ValidationError(detail={ 'error_mesage': 'Size is smaller than original image' })
serializer.save(owner=request.user, size_in_gb=size_in_gb)
return Response(serializer.data)
class VMProductViewSet(viewsets.ModelViewSet): class VMProductViewSet(viewsets.ModelViewSet):
permission_classes = [permissions.IsAuthenticated] permission_classes = [permissions.IsAuthenticated]