support creating disks
Signed-off-by: Nico Schottelius <nico@nico-notebook.schottelius.org>
This commit is contained in:
parent
6a38e4e0a4
commit
5c33bc5c02
4 changed files with 71 additions and 18 deletions
|
@ -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
|
||||||
|
|
|
@ -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):
|
||||||
|
|
|
@ -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__'
|
||||||
|
|
|
@ -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]
|
||||||
|
|
Loading…
Reference in a new issue