forked from uncloud/uncloud
Make VM order-able again
This commit is contained in:
parent
df059fb00d
commit
d794b24c86
5 changed files with 70 additions and 34 deletions
|
@ -636,6 +636,20 @@ class Order(models.Model):
|
|||
def bills(self):
|
||||
return Bill.objects.filter(order=self)
|
||||
|
||||
@staticmethod
|
||||
def from_product(product, **kwargs):
|
||||
# FIXME: this is only a workaround.
|
||||
billing_address = BillingAddress.get_preferred_address_for(product.owner)
|
||||
if billing_address == None:
|
||||
raise Exception("Owner does not have a billing address!")
|
||||
|
||||
return Order(description=product.description,
|
||||
one_time_price=product.one_time_price,
|
||||
recurring_price=product.recurring_price,
|
||||
billing_address=billing_address,
|
||||
owner=product.owner,
|
||||
**kwargs)
|
||||
|
||||
def __str__(self):
|
||||
return "Order {} created at {}, {}->{}, recurring period {}. One time price {}, recurring price {}".format(
|
||||
self.uuid, self.creation_date,
|
||||
|
|
19
uncloud_vm/migrations/0014_vmwithosproduct_primary_disk.py
Normal file
19
uncloud_vm/migrations/0014_vmwithosproduct_primary_disk.py
Normal file
|
@ -0,0 +1,19 @@
|
|||
# Generated by Django 3.0.6 on 2020-05-08 14:01
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('uncloud_vm', '0013_remove_vmproduct_primary_disk'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='vmwithosproduct',
|
||||
name='primary_disk',
|
||||
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='uncloud_vm.VMDiskProduct'),
|
||||
),
|
||||
]
|
|
@ -69,7 +69,7 @@ class VMProduct(Product):
|
|||
cores = models.IntegerField()
|
||||
ram_in_gb = models.FloatField()
|
||||
|
||||
|
||||
# Default recurring price is PER_MONTH, see uncloud_pay.models.Product.
|
||||
@property
|
||||
def recurring_price(self):
|
||||
return self.cores * 3 + self.ram_in_gb * 4
|
||||
|
@ -99,7 +99,7 @@ class VMProduct(Product):
|
|||
|
||||
|
||||
class VMWithOSProduct(VMProduct):
|
||||
pass
|
||||
primary_disk = models.ForeignKey('VMDiskProduct', on_delete=models.CASCADE, null=True)
|
||||
|
||||
|
||||
class VMDiskImageProduct(UncloudModel):
|
||||
|
|
|
@ -2,7 +2,7 @@ from django.contrib.auth import get_user_model
|
|||
|
||||
from rest_framework import serializers
|
||||
|
||||
from .models import VMHost, VMProduct, VMSnapshotProduct, VMDiskProduct, VMDiskImageProduct, VMCluster
|
||||
from .models import *
|
||||
from uncloud_pay.models import RecurringPeriod, BillingAddress
|
||||
|
||||
# XXX: does not seem to be used?
|
||||
|
@ -86,40 +86,33 @@ class ManagedVMProductSerializer(serializers.ModelSerializer):
|
|||
"""
|
||||
primary_disk = CreateManagedVMDiskProductSerializer()
|
||||
class Meta:
|
||||
model = VMProduct
|
||||
model = VMWithOSProduct
|
||||
fields = [ 'cores', 'ram_in_gb', 'primary_disk']
|
||||
|
||||
class VMProductSerializer(serializers.HyperlinkedModelSerializer):
|
||||
class VMProductSerializer(serializers.ModelSerializer):
|
||||
primary_disk = CreateVMDiskProductSerializer()
|
||||
snapshots = VMSnapshotProductSerializer(many=True, read_only=True)
|
||||
disks = VMDiskProductSerializer(many=True, read_only=True)
|
||||
|
||||
class Meta:
|
||||
model = VMProduct
|
||||
model = VMWithOSProduct
|
||||
fields = ['uuid', 'order', 'owner', 'status', 'name', 'cores',
|
||||
'ram_in_gb', 'primary_disk', 'snapshots', 'disks', 'extra_data']
|
||||
read_only_fields = ['uuid', 'order', 'owner', 'status']
|
||||
|
||||
class OrderVMProductSerializer(VMProductSerializer):
|
||||
recurring_period = serializers.ChoiceField(
|
||||
choices=VMProduct.allowed_recurring_periods())
|
||||
choices=VMWithOSProduct.allowed_recurring_periods())
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(VMProductSerializer, self).__init__(*args, **kwargs)
|
||||
self.fields['billing_address'] = serializers.ChoiceField(
|
||||
choices=BillingAddress.get_addresses_for(
|
||||
self.context['request'].user)
|
||||
)
|
||||
|
||||
class Meta:
|
||||
model = VMProductSerializer.Meta.model
|
||||
fields = VMProductSerializer.Meta.fields + [
|
||||
'recurring_period', 'billing_address'
|
||||
]
|
||||
fields = VMProductSerializer.Meta.fields + [ 'recurring_period' ]
|
||||
read_only_fields = VMProductSerializer.Meta.read_only_fields
|
||||
|
||||
# Nico's playground.
|
||||
|
||||
class NicoVMProductSerializer(serializers.ModelSerializer):
|
||||
snapshots = VMSnapshotProductSerializer(many=True, read_only=True)
|
||||
order = serializers.StringRelatedField()
|
||||
|
@ -134,7 +127,6 @@ class NicoVMProductSerializer(serializers.ModelSerializer):
|
|||
'ram_in_gb'
|
||||
]
|
||||
|
||||
|
||||
class DCLVMProductSerializer(serializers.HyperlinkedModelSerializer):
|
||||
"""
|
||||
Create an interface similar to standard DCL
|
||||
|
|
|
@ -10,7 +10,7 @@ from rest_framework.response import Response
|
|||
from rest_framework.exceptions import ValidationError
|
||||
|
||||
from .models import VMHost, VMProduct, VMSnapshotProduct, VMDiskProduct, VMDiskImageProduct, VMCluster
|
||||
from uncloud_pay.models import Order
|
||||
from uncloud_pay.models import Order, BillingAddress
|
||||
|
||||
from .serializers import *
|
||||
from uncloud_pay.helpers import ProductViewSet
|
||||
|
@ -136,9 +136,9 @@ class VMProductViewSet(ProductViewSet):
|
|||
|
||||
def get_queryset(self):
|
||||
if self.request.user.is_superuser:
|
||||
obj = VMProduct.objects.all()
|
||||
obj = VMWithOSProduct.objects.all()
|
||||
else:
|
||||
obj = VMProduct.objects.filter(owner=self.request.user)
|
||||
obj = VMWithOSProduct.objects.filter(owner=self.request.user)
|
||||
|
||||
return obj
|
||||
|
||||
|
@ -156,29 +156,39 @@ class VMProductViewSet(ProductViewSet):
|
|||
serializer = self.get_serializer(data=request.data)
|
||||
serializer.is_valid(raise_exception=True)
|
||||
order_recurring_period = serializer.validated_data.pop("recurring_period")
|
||||
order_billing_address = serializer.validated_data.pop("billing_address")
|
||||
|
||||
# Create base order.
|
||||
order = Order(
|
||||
recurring_period=order_recurring_period,
|
||||
billing_address=order_billing_address,
|
||||
owner=request.user,
|
||||
starting_date=timezone.now()
|
||||
)
|
||||
order.save()
|
||||
|
||||
# Create disk image.
|
||||
disk = VMDiskProduct(owner=request.user, order=order,
|
||||
disk = VMDiskProduct(owner=request.user,
|
||||
**serializer.validated_data.pop("primary_disk"))
|
||||
vm = VMWithOSProduct(owner=request.user, primary_disk=disk,
|
||||
**serializer.validated_data)
|
||||
disk.vm = vm # XXX: Is this really needed?
|
||||
|
||||
# Create VM.
|
||||
vm = serializer.save(owner=request.user, order=order, primary_disk=disk)
|
||||
disk.vm = vm
|
||||
# Create VM and Disk orders.
|
||||
vm_order = Order.from_product(
|
||||
vm,
|
||||
recurring_period=order_recurring_period,
|
||||
starting_date=timezone.now()
|
||||
)
|
||||
|
||||
disk_order = Order.from_product(
|
||||
disk,
|
||||
recurring_period=order_recurring_period,
|
||||
starting_date=timezone.now()
|
||||
)
|
||||
|
||||
|
||||
# Commit to DB.
|
||||
vm.order = vm_order
|
||||
vm.save()
|
||||
vm_order.save()
|
||||
|
||||
disk.order = disk_order
|
||||
disk_order.save()
|
||||
disk.save()
|
||||
|
||||
return Response(VMProductSerializer(vm, context={'request': request}).data)
|
||||
|
||||
|
||||
class NicoVMProductViewSet(ProductViewSet):
|
||||
permission_classes = [permissions.IsAuthenticated]
|
||||
serializer_class = NicoVMProductSerializer
|
||||
|
@ -194,6 +204,7 @@ class NicoVMProductViewSet(ProductViewSet):
|
|||
|
||||
return Response(serializer.data)
|
||||
|
||||
|
||||
###
|
||||
# Admin stuff.
|
||||
|
||||
|
|
Loading…
Reference in a new issue