From 9410b7c56b61a2226871d263b5e42c862b0824f3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timoth=C3=A9e=20Floure?=
Date: Sat, 18 Apr 2020 13:51:31 +0200
Subject: [PATCH 001/241] Make VM order-able again
---
.../uncloud/uncloud_vm/models.py | 15 +--
.../uncloud/uncloud_vm/serializers.py | 92 ++++++++-----
.../uncloud/uncloud_vm/views.py | 125 ++++++++++--------
3 files changed, 132 insertions(+), 100 deletions(-)
diff --git a/uncloud_django_based/uncloud/uncloud_vm/models.py b/uncloud_django_based/uncloud/uncloud_vm/models.py
index f56ed0d..5dacdbe 100644
--- a/uncloud_django_based/uncloud/uncloud_vm/models.py
+++ b/uncloud_django_based/uncloud/uncloud_vm/models.py
@@ -72,6 +72,7 @@ class VMProduct(Product):
primary_disk = models.ForeignKey('VMDiskProduct', on_delete=models.CASCADE, null=True)
# 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
@@ -153,17 +154,9 @@ class VMDiskProduct(Product):
def description(self):
return "Disk for VM '{}': {}GB".format(self.vm.name, self.size_in_gb)
- # TODO: move magic numbers in variables
- def recurring_price(self, recurring_period=RecurringPeriod.PER_MONTH):
- # TODO: move magic numbers in variables
- if recurring_period == RecurringPeriod.PER_MONTH:
- return (self.size_in_gb / 10) * 3.5
- if recurring_period == RecurringPeriod.PER_YEAR:
- return recurring_price(self, recurring_period.PER_MONTH) * 12
- if recurring_period == RecurringPeriod.PER_HOUR:
- return recurring_price(self, recurring_period.PER_MONTH) / 25
- else:
- raise Exception('Invalid recurring period for VM Disk Product pricing.')
+ @property
+ def recurring_price(self):
+ return (self.size_in_gb / 10) * 3.5
# Sample code for clean method
diff --git a/uncloud_django_based/uncloud/uncloud_vm/serializers.py b/uncloud_django_based/uncloud/uncloud_vm/serializers.py
index 9435de2..92c7fe8 100644
--- a/uncloud_django_based/uncloud/uncloud_vm/serializers.py
+++ b/uncloud_django_based/uncloud/uncloud_vm/serializers.py
@@ -3,7 +3,9 @@ from django.contrib.auth import get_user_model
from rest_framework import serializers
from .models import VMHost, VMProduct, VMSnapshotProduct, VMDiskProduct, VMDiskImageProduct, VMCluster
-from uncloud_pay.models import RecurringPeriod
+from uncloud_pay.models import RecurringPeriod, BillingAddress
+
+# XXX: does not seem to be used?
GB_SSD_PER_DAY=0.012
GB_HDD_PER_DAY=0.0006
@@ -11,6 +13,8 @@ GB_HDD_PER_DAY=0.0006
GB_SSD_PER_DAY=0.012
GB_HDD_PER_DAY=0.0006
+###
+# Admin views.
class VMHostSerializer(serializers.HyperlinkedModelSerializer):
vms = serializers.PrimaryKeyRelatedField(many=True, read_only=True)
@@ -26,6 +30,9 @@ class VMClusterSerializer(serializers.HyperlinkedModelSerializer):
fields = '__all__'
+###
+# Disks.
+
class VMDiskProductSerializer(serializers.ModelSerializer):
class Meta:
model = VMDiskProduct
@@ -46,30 +53,6 @@ class VMDiskImageProductSerializer(serializers.ModelSerializer):
model = VMDiskImageProduct
fields = '__all__'
-class DCLVMProductSerializer(serializers.HyperlinkedModelSerializer):
- """
- Create an interface similar to standard DCL
- """
-
- # Custom field used at creation (= ordering) only.
- recurring_period = serializers.ChoiceField(
- choices=VMProduct.allowed_recurring_periods())
-
- os_disk_uuid = serializers.UUIDField()
- # os_disk_size =
-
- class Meta:
- model = VMProduct
-
-class ManagedVMProductSerializer(serializers.ModelSerializer):
- """
- Managed VM serializer used in ungleich_service app.
- """
- primary_disk = CreateManagedVMDiskProductSerializer()
- class Meta:
- model = VMProduct
- fields = [ 'cores', 'ram_in_gb', 'primary_disk']
-
class VMSnapshotProductSerializer(serializers.ModelSerializer):
class Meta:
model = VMSnapshotProduct
@@ -93,22 +76,61 @@ class VMSnapshotProductSerializer(serializers.ModelSerializer):
pricing['per_gb_hdd'] = 0.0006
pricing['recurring_period'] = 'per_day'
+###
+# VMs
+
+# Helper used in uncloud_service for services allocating VM.
+class ManagedVMProductSerializer(serializers.ModelSerializer):
+ """
+ Managed VM serializer used in ungleich_service app.
+ """
+ primary_disk = CreateManagedVMDiskProductSerializer()
+ class Meta:
+ model = VMProduct
+ fields = [ 'cores', 'ram_in_gb', 'primary_disk']
class VMProductSerializer(serializers.HyperlinkedModelSerializer):
- # Custom field used at creation (= ordering) only.
- recurring_period = serializers.ChoiceField(
- choices=VMProduct.allowed_recurring_periods())
primary_disk = CreateVMDiskProductSerializer()
+ snapshots = VMSnapshotProductSerializer(many=True, read_only=True)
+ disks = VMDiskProductSerializer(many=True, read_only=True)
class Meta:
model = VMProduct
- fields = ['uuid', 'order', 'owner', 'status', 'name', \
- 'cores', 'ram_in_gb', 'recurring_period', 'primary_disk',
- 'snapshots', 'disks', 'extra_data' ]
+ fields = ['uuid', 'order', 'owner', 'status', 'name', 'cores',
+ 'ram_in_gb', 'primary_disk', 'snapshots', 'disks', 'extra_data']
read_only_fields = ['uuid', 'order', 'owner', 'status']
- snapshots = VMSnapshotProductSerializer(many=True,
- read_only=True)
+class OrderVMProductSerializer(VMProductSerializer):
+ recurring_period = serializers.ChoiceField(
+ choices=VMProduct.allowed_recurring_periods())
- disks = VMDiskProductSerializer(many=True,
- read_only=True)
+ 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'
+ ]
+ read_only_fields = VMProductSerializer.Meta.read_only_fields
+
+# Nico's playground.
+
+class DCLVMProductSerializer(serializers.HyperlinkedModelSerializer):
+ """
+ Create an interface similar to standard DCL
+ """
+
+ # Custom field used at creation (= ordering) only.
+ recurring_period = serializers.ChoiceField(
+ choices=VMProduct.allowed_recurring_periods())
+
+ os_disk_uuid = serializers.UUIDField()
+ # os_disk_size =
+
+ class Meta:
+ model = VMProduct
diff --git a/uncloud_django_based/uncloud/uncloud_vm/views.py b/uncloud_django_based/uncloud/uncloud_vm/views.py
index 71ffe6d..1dead62 100644
--- a/uncloud_django_based/uncloud/uncloud_vm/views.py
+++ b/uncloud_django_based/uncloud/uncloud_vm/views.py
@@ -15,20 +15,12 @@ from uncloud_pay.models import Order
from .serializers import *
from uncloud_pay.helpers import ProductViewSet
-
import datetime
-class VMHostViewSet(viewsets.ModelViewSet):
- serializer_class = VMHostSerializer
- queryset = VMHost.objects.all()
- permission_classes = [permissions.IsAdminUser]
+###
+# Generic disk image views. Do not require orders / billing.
-class VMClusterViewSet(viewsets.ModelViewSet):
- serializer_class = VMClusterSerializer
- queryset = VMCluster.objects.all()
- permission_classes = [permissions.IsAdminUser]
-
-class VMDiskImageProductViewSet(viewsets.ModelViewSet):
+class VMDiskImageProductViewSet(ProductViewSet):
permission_classes = [permissions.IsAuthenticated]
serializer_class = VMDiskImageProductSerializer
@@ -53,7 +45,6 @@ class VMDiskImageProductViewSet(viewsets.ModelViewSet):
serializer.save(owner=request.user)
return Response(serializer.data)
-
class VMDiskImageProductPublicViewSet(viewsets.ReadOnlyModelViewSet):
permission_classes = [permissions.IsAuthenticated]
serializer_class = VMDiskImageProductSerializer
@@ -61,6 +52,9 @@ class VMDiskImageProductPublicViewSet(viewsets.ReadOnlyModelViewSet):
def get_queryset(self):
return VMDiskImageProduct.objects.filter(is_public=True)
+###
+# User VM disk and snapshots.
+
class VMDiskProductViewSet(viewsets.ModelViewSet):
"""
Let a user modify their own VMDisks
@@ -92,48 +86,6 @@ class VMDiskProductViewSet(viewsets.ModelViewSet):
serializer.save(owner=request.user, size_in_gb=size_in_gb)
return Response(serializer.data)
-
-
-class VMProductViewSet(ProductViewSet):
- permission_classes = [permissions.IsAuthenticated]
- serializer_class = VMProductSerializer
-
- def get_queryset(self):
- if self.request.user.is_superuser:
- obj = VMProduct.objects.all()
- else:
- obj = VMProduct.objects.filter(owner=self.request.user)
-
- return obj
-
- # Use a database transaction so that we do not get half-created structure
- # if something goes wrong.
- @transaction.atomic
- def create(self, request):
- # Extract serializer data.
- serializer = VMProductSerializer(data=request.data, context={'request': request})
- serializer.is_valid(raise_exception=True)
- order_recurring_period = serializer.validated_data.pop("recurring_period")
-
- # Create base order.
- order = Order(
- recurring_period=order_recurring_period,
- owner=request.user,
- starting_date=timezone.now()
- )
-
- # Create disk image.
- disk = VMDiskProduct(owner=request.user, order=order,
- **serializer.validated_data.pop("primary_disk"))
-
- # Create VM.
- vm = serializer.save(owner=request.user, order=order, primary_disk=disk)
- disk.vm = vm
- disk.save()
-
- return Response(serializer.data)
-
-
class VMSnapshotProductViewSet(viewsets.ModelViewSet):
permission_classes = [permissions.IsAuthenticated]
serializer_class = VMSnapshotProductSerializer
@@ -176,7 +128,72 @@ class VMSnapshotProductViewSet(viewsets.ModelViewSet):
return Response(serializer.data)
+###
+# User VMs.
+class VMProductViewSet(ProductViewSet):
+ permission_classes = [permissions.IsAuthenticated]
+
+ def get_queryset(self):
+ if self.request.user.is_superuser:
+ obj = VMProduct.objects.all()
+ else:
+ obj = VMProduct.objects.filter(owner=self.request.user)
+
+ return obj
+
+ def get_serializer_class(self):
+ if self.action == 'create':
+ return OrderVMProductSerializer
+ else:
+ return VMProductSerializer
+
+ # Use a database transaction so that we do not get half-created structure
+ # if something goes wrong.
+ @transaction.atomic
+ def create(self, request):
+ # Extract serializer data.
+ 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,
+ **serializer.validated_data.pop("primary_disk"))
+
+ # Create VM.
+ vm = serializer.save(owner=request.user, order=order, primary_disk=disk)
+ disk.vm = vm
+ disk.save()
+
+ return Response(VMProductSerializer(vm, context={'request': request}).data)
+
+
+###
+# Admin stuff.
+
+class VMHostViewSet(viewsets.ModelViewSet):
+ serializer_class = VMHostSerializer
+ queryset = VMHost.objects.all()
+ permission_classes = [permissions.IsAdminUser]
+
+class VMClusterViewSet(viewsets.ModelViewSet):
+ serializer_class = VMClusterSerializer
+ queryset = VMCluster.objects.all()
+ permission_classes = [permissions.IsAdminUser]
+
+##
+# Nico's playground.
# Also create:
# - /dcl/available_os
From a15952862ad027efe9b823ffea6b0d3fd5bf067b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timoth=C3=A9e=20Floure?=
Date: Sat, 18 Apr 2020 13:51:31 +0200
Subject: [PATCH 002/241] Make VM order-able again
---
.../uncloud/uncloud_vm/models.py | 15 +--
.../uncloud/uncloud_vm/serializers.py | 92 ++++++++-----
.../uncloud/uncloud_vm/views.py | 125 ++++++++++--------
3 files changed, 132 insertions(+), 100 deletions(-)
diff --git a/uncloud_django_based/uncloud/uncloud_vm/models.py b/uncloud_django_based/uncloud/uncloud_vm/models.py
index f56ed0d..5dacdbe 100644
--- a/uncloud_django_based/uncloud/uncloud_vm/models.py
+++ b/uncloud_django_based/uncloud/uncloud_vm/models.py
@@ -72,6 +72,7 @@ class VMProduct(Product):
primary_disk = models.ForeignKey('VMDiskProduct', on_delete=models.CASCADE, null=True)
# 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
@@ -153,17 +154,9 @@ class VMDiskProduct(Product):
def description(self):
return "Disk for VM '{}': {}GB".format(self.vm.name, self.size_in_gb)
- # TODO: move magic numbers in variables
- def recurring_price(self, recurring_period=RecurringPeriod.PER_MONTH):
- # TODO: move magic numbers in variables
- if recurring_period == RecurringPeriod.PER_MONTH:
- return (self.size_in_gb / 10) * 3.5
- if recurring_period == RecurringPeriod.PER_YEAR:
- return recurring_price(self, recurring_period.PER_MONTH) * 12
- if recurring_period == RecurringPeriod.PER_HOUR:
- return recurring_price(self, recurring_period.PER_MONTH) / 25
- else:
- raise Exception('Invalid recurring period for VM Disk Product pricing.')
+ @property
+ def recurring_price(self):
+ return (self.size_in_gb / 10) * 3.5
# Sample code for clean method
diff --git a/uncloud_django_based/uncloud/uncloud_vm/serializers.py b/uncloud_django_based/uncloud/uncloud_vm/serializers.py
index 9435de2..92c7fe8 100644
--- a/uncloud_django_based/uncloud/uncloud_vm/serializers.py
+++ b/uncloud_django_based/uncloud/uncloud_vm/serializers.py
@@ -3,7 +3,9 @@ from django.contrib.auth import get_user_model
from rest_framework import serializers
from .models import VMHost, VMProduct, VMSnapshotProduct, VMDiskProduct, VMDiskImageProduct, VMCluster
-from uncloud_pay.models import RecurringPeriod
+from uncloud_pay.models import RecurringPeriod, BillingAddress
+
+# XXX: does not seem to be used?
GB_SSD_PER_DAY=0.012
GB_HDD_PER_DAY=0.0006
@@ -11,6 +13,8 @@ GB_HDD_PER_DAY=0.0006
GB_SSD_PER_DAY=0.012
GB_HDD_PER_DAY=0.0006
+###
+# Admin views.
class VMHostSerializer(serializers.HyperlinkedModelSerializer):
vms = serializers.PrimaryKeyRelatedField(many=True, read_only=True)
@@ -26,6 +30,9 @@ class VMClusterSerializer(serializers.HyperlinkedModelSerializer):
fields = '__all__'
+###
+# Disks.
+
class VMDiskProductSerializer(serializers.ModelSerializer):
class Meta:
model = VMDiskProduct
@@ -46,30 +53,6 @@ class VMDiskImageProductSerializer(serializers.ModelSerializer):
model = VMDiskImageProduct
fields = '__all__'
-class DCLVMProductSerializer(serializers.HyperlinkedModelSerializer):
- """
- Create an interface similar to standard DCL
- """
-
- # Custom field used at creation (= ordering) only.
- recurring_period = serializers.ChoiceField(
- choices=VMProduct.allowed_recurring_periods())
-
- os_disk_uuid = serializers.UUIDField()
- # os_disk_size =
-
- class Meta:
- model = VMProduct
-
-class ManagedVMProductSerializer(serializers.ModelSerializer):
- """
- Managed VM serializer used in ungleich_service app.
- """
- primary_disk = CreateManagedVMDiskProductSerializer()
- class Meta:
- model = VMProduct
- fields = [ 'cores', 'ram_in_gb', 'primary_disk']
-
class VMSnapshotProductSerializer(serializers.ModelSerializer):
class Meta:
model = VMSnapshotProduct
@@ -93,22 +76,61 @@ class VMSnapshotProductSerializer(serializers.ModelSerializer):
pricing['per_gb_hdd'] = 0.0006
pricing['recurring_period'] = 'per_day'
+###
+# VMs
+
+# Helper used in uncloud_service for services allocating VM.
+class ManagedVMProductSerializer(serializers.ModelSerializer):
+ """
+ Managed VM serializer used in ungleich_service app.
+ """
+ primary_disk = CreateManagedVMDiskProductSerializer()
+ class Meta:
+ model = VMProduct
+ fields = [ 'cores', 'ram_in_gb', 'primary_disk']
class VMProductSerializer(serializers.HyperlinkedModelSerializer):
- # Custom field used at creation (= ordering) only.
- recurring_period = serializers.ChoiceField(
- choices=VMProduct.allowed_recurring_periods())
primary_disk = CreateVMDiskProductSerializer()
+ snapshots = VMSnapshotProductSerializer(many=True, read_only=True)
+ disks = VMDiskProductSerializer(many=True, read_only=True)
class Meta:
model = VMProduct
- fields = ['uuid', 'order', 'owner', 'status', 'name', \
- 'cores', 'ram_in_gb', 'recurring_period', 'primary_disk',
- 'snapshots', 'disks', 'extra_data' ]
+ fields = ['uuid', 'order', 'owner', 'status', 'name', 'cores',
+ 'ram_in_gb', 'primary_disk', 'snapshots', 'disks', 'extra_data']
read_only_fields = ['uuid', 'order', 'owner', 'status']
- snapshots = VMSnapshotProductSerializer(many=True,
- read_only=True)
+class OrderVMProductSerializer(VMProductSerializer):
+ recurring_period = serializers.ChoiceField(
+ choices=VMProduct.allowed_recurring_periods())
- disks = VMDiskProductSerializer(many=True,
- read_only=True)
+ 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'
+ ]
+ read_only_fields = VMProductSerializer.Meta.read_only_fields
+
+# Nico's playground.
+
+class DCLVMProductSerializer(serializers.HyperlinkedModelSerializer):
+ """
+ Create an interface similar to standard DCL
+ """
+
+ # Custom field used at creation (= ordering) only.
+ recurring_period = serializers.ChoiceField(
+ choices=VMProduct.allowed_recurring_periods())
+
+ os_disk_uuid = serializers.UUIDField()
+ # os_disk_size =
+
+ class Meta:
+ model = VMProduct
diff --git a/uncloud_django_based/uncloud/uncloud_vm/views.py b/uncloud_django_based/uncloud/uncloud_vm/views.py
index 71ffe6d..1dead62 100644
--- a/uncloud_django_based/uncloud/uncloud_vm/views.py
+++ b/uncloud_django_based/uncloud/uncloud_vm/views.py
@@ -15,20 +15,12 @@ from uncloud_pay.models import Order
from .serializers import *
from uncloud_pay.helpers import ProductViewSet
-
import datetime
-class VMHostViewSet(viewsets.ModelViewSet):
- serializer_class = VMHostSerializer
- queryset = VMHost.objects.all()
- permission_classes = [permissions.IsAdminUser]
+###
+# Generic disk image views. Do not require orders / billing.
-class VMClusterViewSet(viewsets.ModelViewSet):
- serializer_class = VMClusterSerializer
- queryset = VMCluster.objects.all()
- permission_classes = [permissions.IsAdminUser]
-
-class VMDiskImageProductViewSet(viewsets.ModelViewSet):
+class VMDiskImageProductViewSet(ProductViewSet):
permission_classes = [permissions.IsAuthenticated]
serializer_class = VMDiskImageProductSerializer
@@ -53,7 +45,6 @@ class VMDiskImageProductViewSet(viewsets.ModelViewSet):
serializer.save(owner=request.user)
return Response(serializer.data)
-
class VMDiskImageProductPublicViewSet(viewsets.ReadOnlyModelViewSet):
permission_classes = [permissions.IsAuthenticated]
serializer_class = VMDiskImageProductSerializer
@@ -61,6 +52,9 @@ class VMDiskImageProductPublicViewSet(viewsets.ReadOnlyModelViewSet):
def get_queryset(self):
return VMDiskImageProduct.objects.filter(is_public=True)
+###
+# User VM disk and snapshots.
+
class VMDiskProductViewSet(viewsets.ModelViewSet):
"""
Let a user modify their own VMDisks
@@ -92,48 +86,6 @@ class VMDiskProductViewSet(viewsets.ModelViewSet):
serializer.save(owner=request.user, size_in_gb=size_in_gb)
return Response(serializer.data)
-
-
-class VMProductViewSet(ProductViewSet):
- permission_classes = [permissions.IsAuthenticated]
- serializer_class = VMProductSerializer
-
- def get_queryset(self):
- if self.request.user.is_superuser:
- obj = VMProduct.objects.all()
- else:
- obj = VMProduct.objects.filter(owner=self.request.user)
-
- return obj
-
- # Use a database transaction so that we do not get half-created structure
- # if something goes wrong.
- @transaction.atomic
- def create(self, request):
- # Extract serializer data.
- serializer = VMProductSerializer(data=request.data, context={'request': request})
- serializer.is_valid(raise_exception=True)
- order_recurring_period = serializer.validated_data.pop("recurring_period")
-
- # Create base order.
- order = Order(
- recurring_period=order_recurring_period,
- owner=request.user,
- starting_date=timezone.now()
- )
-
- # Create disk image.
- disk = VMDiskProduct(owner=request.user, order=order,
- **serializer.validated_data.pop("primary_disk"))
-
- # Create VM.
- vm = serializer.save(owner=request.user, order=order, primary_disk=disk)
- disk.vm = vm
- disk.save()
-
- return Response(serializer.data)
-
-
class VMSnapshotProductViewSet(viewsets.ModelViewSet):
permission_classes = [permissions.IsAuthenticated]
serializer_class = VMSnapshotProductSerializer
@@ -176,7 +128,72 @@ class VMSnapshotProductViewSet(viewsets.ModelViewSet):
return Response(serializer.data)
+###
+# User VMs.
+class VMProductViewSet(ProductViewSet):
+ permission_classes = [permissions.IsAuthenticated]
+
+ def get_queryset(self):
+ if self.request.user.is_superuser:
+ obj = VMProduct.objects.all()
+ else:
+ obj = VMProduct.objects.filter(owner=self.request.user)
+
+ return obj
+
+ def get_serializer_class(self):
+ if self.action == 'create':
+ return OrderVMProductSerializer
+ else:
+ return VMProductSerializer
+
+ # Use a database transaction so that we do not get half-created structure
+ # if something goes wrong.
+ @transaction.atomic
+ def create(self, request):
+ # Extract serializer data.
+ 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,
+ **serializer.validated_data.pop("primary_disk"))
+
+ # Create VM.
+ vm = serializer.save(owner=request.user, order=order, primary_disk=disk)
+ disk.vm = vm
+ disk.save()
+
+ return Response(VMProductSerializer(vm, context={'request': request}).data)
+
+
+###
+# Admin stuff.
+
+class VMHostViewSet(viewsets.ModelViewSet):
+ serializer_class = VMHostSerializer
+ queryset = VMHost.objects.all()
+ permission_classes = [permissions.IsAdminUser]
+
+class VMClusterViewSet(viewsets.ModelViewSet):
+ serializer_class = VMClusterSerializer
+ queryset = VMCluster.objects.all()
+ permission_classes = [permissions.IsAdminUser]
+
+##
+# Nico's playground.
# Also create:
# - /dcl/available_os
From 94932edebef2b2c0b53b0516a312b6be55aa0af3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timoth=C3=A9e=20Floure?=
Date: Sat, 18 Apr 2020 15:11:02 +0200
Subject: [PATCH 003/241] Add user admin endpoint, import from LDAP
---
uncloud_django_based/uncloud/uncloud/urls.py | 3 +-
.../uncloud/uncloud_auth/serializers.py | 9 ++--
.../uncloud/uncloud_auth/views.py | 42 +++++++++++++++----
3 files changed, 39 insertions(+), 15 deletions(-)
diff --git a/uncloud_django_based/uncloud/uncloud/urls.py b/uncloud_django_based/uncloud/uncloud/urls.py
index 14a87e8..4d0ada1 100644
--- a/uncloud_django_based/uncloud/uncloud/urls.py
+++ b/uncloud_django_based/uncloud/uncloud/urls.py
@@ -67,12 +67,11 @@ router.register(r'admin/order', payviews.AdminOrderViewSet, basename='admin/orde
router.register(r'admin/vmhost', vmviews.VMHostViewSet)
router.register(r'admin/vmcluster', vmviews.VMClusterViewSet)
router.register(r'admin/vpnpool', netviews.VPNPoolViewSet)
-
router.register(r'admin/opennebula', oneviews.VMViewSet, basename='opennebula')
# User/Account
router.register(r'user', authviews.UserViewSet, basename='user')
-
+router.register(r'admin/user', authviews.AdminUserViewSet, basename='useradmin')
urlpatterns = [
path('', include(router.urls)),
diff --git a/uncloud_django_based/uncloud/uncloud_auth/serializers.py b/uncloud_django_based/uncloud/uncloud_auth/serializers.py
index de369c3..71aeb03 100644
--- a/uncloud_django_based/uncloud/uncloud_auth/serializers.py
+++ b/uncloud_django_based/uncloud/uncloud_auth/serializers.py
@@ -5,11 +5,12 @@ from uncloud import AMOUNT_DECIMALS, AMOUNT_MAX_DIGITS
class UserSerializer(serializers.ModelSerializer):
+ balance = serializers.DecimalField(max_digits=AMOUNT_MAX_DIGITS,
+ decimal_places=AMOUNT_DECIMALS)
+
class Meta:
model = get_user_model()
fields = ['username', 'email', 'balance', 'maximum_credit' ]
-
-
- balance = serializers.DecimalField(max_digits=AMOUNT_MAX_DIGITS,
- decimal_places=AMOUNT_DECIMALS)
+class ImportUserSerializer(serializers.Serializer):
+ username = serializers.CharField()
diff --git a/uncloud_django_based/uncloud/uncloud_auth/views.py b/uncloud_django_based/uncloud/uncloud_auth/views.py
index 2f78e1f..9c5bd1f 100644
--- a/uncloud_django_based/uncloud/uncloud_auth/views.py
+++ b/uncloud_django_based/uncloud/uncloud_auth/views.py
@@ -1,17 +1,41 @@
from rest_framework import viewsets, permissions, status
from .serializers import *
+from django_auth_ldap.backend import LDAPBackend
+from rest_framework.decorators import action
+from rest_framework.response import Response
+from rest_framework import mixins
-class UserViewSet(viewsets.ReadOnlyModelViewSet):
+class UserViewSet(mixins.ListModelMixin, viewsets.GenericViewSet):
+ permission_classes = [permissions.IsAuthenticated]
serializer_class = UserSerializer
+
+ def list(self, request, format=None):
+ # This is a bit stupid: we have a user, we create a queryset by
+ # matching on the username. But I don't know a "nicer" way.
+ # Nico, 2020-03-18
+ user = get_user_model().objects.get(
+ username=self.request.user.username)
+ serializer = self.get_serializer(user, context = {'request': request})
+ return Response(serializer.data)
+
+class AdminUserViewSet(viewsets.ReadOnlyModelViewSet):
+ # FIXME: make this admin
permission_classes = [permissions.IsAuthenticated]
- def get_queryset(self):
- if self.request.user.is_superuser:
- obj = get_user_model().objects.all()
+ def get_serializer_class(self):
+ if self.action == 'import_from_ldap':
+ return ImportUserSerializer
else:
- # This is a bit stupid: we have a user, we create a queryset by
- # matching on the username. But I don't know a "nicer" way.
- # Nico, 2020-03-18
- obj = get_user_model().objects.filter(username=self.request.user.username)
+ return UserSerializer
- return obj
+ def get_queryset(self):
+ return get_user_model().objects.all()
+
+ @action(detail=False, methods=['post'], url_path='import_from_ldap')
+ def import_from_ldap(self, request, pk=None):
+ serializer = self.get_serializer(data=request.data)
+ serializer.is_valid(raise_exception=True)
+ ldap_username = serializer.validated_data.pop("username")
+ user = LDAPBackend().populate_user(ldap_username)
+
+ return Response(UserSerializer(user, context = {'request': request}).data)
From 1cf20a2cb6c84b2db79d2e45e49d5fbb81b392e7 Mon Sep 17 00:00:00 2001
From: Nico Schottelius
Date: Mon, 27 Apr 2020 18:25:27 +0200
Subject: [PATCH 004/241] Disable vat validator to get project back running
---
uncloud_django_based/uncloud/uncloud_pay/views.py | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/uncloud_django_based/uncloud/uncloud_pay/views.py b/uncloud_django_based/uncloud/uncloud_pay/views.py
index aaf90e2..82b5787 100644
--- a/uncloud_django_based/uncloud/uncloud_pay/views.py
+++ b/uncloud_django_based/uncloud/uncloud_pay/views.py
@@ -7,8 +7,8 @@ from rest_framework.response import Response
from rest_framework.decorators import action
from rest_framework.reverse import reverse
from rest_framework.decorators import renderer_classes
-from vat_validator import validate_vat, vies
-from vat_validator.countries import EU_COUNTRY_CODES
+#from vat_validator import validate_vat, vies
+#from vat_validator.countries import EU_COUNTRY_CODES
import json
import logging
@@ -16,7 +16,7 @@ import logging
from .models import *
from .serializers import *
from datetime import datetime
-from vat_validator import sanitize_vat
+#from vat_validator import sanitize_vat
import uncloud_pay.stripe as uncloud_stripe
logger = logging.getLogger(__name__)
From 62d9ccbbef06706dcb7467d693ba31d732c882a7 Mon Sep 17 00:00:00 2001
From: Nico Schottelius
Date: Mon, 27 Apr 2020 18:25:44 +0200
Subject: [PATCH 005/241] [vpn] begin to introduce save() method
The save() and delete() method will create/manage the orders
---
uncloud_django_based/uncloud/uncloud_net/models.py | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/uncloud_django_based/uncloud/uncloud_net/models.py b/uncloud_django_based/uncloud/uncloud_net/models.py
index 26a6eb8..8dfff05 100644
--- a/uncloud_django_based/uncloud/uncloud_net/models.py
+++ b/uncloud_django_based/uncloud/uncloud_net/models.py
@@ -173,11 +173,11 @@ class VPNNetwork(Product):
wireguard_public_key = models.CharField(max_length=48)
+ def save(self, *args, **kwargs):
+ super().save(*args, **kwargs)
+
def delete(self, *args, **kwargs):
self.network.status = 'free'
self.network.save()
super().save(*args, **kwargs)
print("deleted {}".format(self))
-
-# managing deletion
-# - record free network (?)
From 2cda6441f41776d4605bf141b97c67b4baa767a7 Mon Sep 17 00:00:00 2001
From: Nico Schottelius
Date: Sat, 2 May 2020 00:16:29 +0200
Subject: [PATCH 006/241] Refactor secret / local settings handling
---
.../uncloud/uncloud/secrets_sample.py | 21 ------
.../uncloud/uncloud/settings.py | 73 +++++++++++--------
.../uncloud/uncloud_net/models.py | 3 -
.../uncloud/uncloud_pay/models.py | 15 +++-
.../uncloud/uncloud_pay/stripe.py | 8 +-
5 files changed, 60 insertions(+), 60 deletions(-)
delete mode 100644 uncloud_django_based/uncloud/uncloud/secrets_sample.py
diff --git a/uncloud_django_based/uncloud/uncloud/secrets_sample.py b/uncloud_django_based/uncloud/uncloud/secrets_sample.py
deleted file mode 100644
index 150fefb..0000000
--- a/uncloud_django_based/uncloud/uncloud/secrets_sample.py
+++ /dev/null
@@ -1,21 +0,0 @@
-from django.core.management.utils import get_random_secret_key
-
-# XML-RPC interface of opennebula
-OPENNEBULA_URL = 'https://opennebula.ungleich.ch:2634/RPC2'
-
-# user:pass for accessing opennebula
-OPENNEBULA_USER_PASS = 'user:password'
-
-POSTGRESQL_DB_NAME="uncloud"
-
-# See https://django-auth-ldap.readthedocs.io/en/latest/authentication.html
-LDAP_ADMIN_DN=""
-LDAP_ADMIN_PASSWORD=""
-LDAP_SERVER_URI = ""
-
-# Stripe (Credit Card payments)
-STRIPE_KEY=""
-STRIPE_PUBLIC_KEY=""
-
-# The django secret key
-SECRET_KEY=get_random_secret_key()
diff --git a/uncloud_django_based/uncloud/uncloud/settings.py b/uncloud_django_based/uncloud/uncloud/settings.py
index b525073..527749d 100644
--- a/uncloud_django_based/uncloud/uncloud/settings.py
+++ b/uncloud_django_based/uncloud/uncloud/settings.py
@@ -13,41 +13,32 @@ https://docs.djangoproject.com/en/3.0/ref/settings/
import os
import ldap
-# Uncommitted file with secrets
-import uncloud.secrets
-
+from django.core.management.utils import get_random_secret_key
from django_auth_ldap.config import LDAPSearch, LDAPSearchUnion
-# Uncommitted file with local settings i.e logging
-try:
- from uncloud.local_settings import LOGGING, DATABASES
-except ModuleNotFoundError:
- LOGGING = {}
- # https://docs.djangoproject.com/en/3.0/ref/settings/#databases
- DATABASES = {
- 'default': {
- 'ENGINE': 'django.db.backends.postgresql',
- 'NAME': uncloud.secrets.POSTGRESQL_DB_NAME,
- 'HOST': os.environ.get('DATABASE_HOST', '::1'),
- 'USER': os.environ.get('DATABASE_USER', 'postgres'),
- }
- }
+
+LOGGING = {}
+
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
+# https://docs.djangoproject.com/en/3.0/ref/settings/#databases
+DATABASES = {
+ 'default': {
+ 'ENGINE': 'django.db.backends.sqlite3',
+ 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
+ }
+}
+
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/3.0/howto/deployment/checklist/
-# SECURITY WARNING: keep the secret key used in production secret!
-SECRET_KEY = uncloud.secrets.SECRET_KEY
-
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
-ALLOWED_HOSTS = []
# Application definition
@@ -123,7 +114,12 @@ AUTH_PASSWORD_VALIDATORS = [
################################################################################
# AUTH/LDAP
-AUTH_LDAP_SERVER_URI = uncloud.secrets.LDAP_SERVER_URI
+AUTH_LDAP_SERVER_URI = ""
+AUTH_LDAP_BIND_DN = ""
+AUTH_LDAP_BIND_PASSWORD = ""
+AUTH_LDAP_USER_SEARCH = LDAPSearch("dc=example,dc=com",
+ ldap.SCOPE_SUBTREE,
+ "(uid=%(user)s)")
AUTH_LDAP_USER_ATTR_MAP = {
"first_name": "givenName",
@@ -131,13 +127,6 @@ AUTH_LDAP_USER_ATTR_MAP = {
"email": "mail"
}
-
-AUTH_LDAP_BIND_DN = uncloud.secrets.LDAP_ADMIN_DN
-AUTH_LDAP_BIND_PASSWORD = uncloud.secrets.LDAP_ADMIN_PASSWORD
-
-AUTH_LDAP_USER_SEARCH = LDAPSearch("dc=ungleich,dc=ch", ldap.SCOPE_SUBTREE, "(uid=%(user)s)")
-
-
################################################################################
# AUTH/Django
AUTHENTICATION_BACKENDS = [
@@ -158,7 +147,6 @@ REST_FRAMEWORK = {
}
-
# Internationalization
# https://docs.djangoproject.com/en/3.0/topics/i18n/
@@ -177,3 +165,28 @@ USE_TZ = True
# https://docs.djangoproject.com/en/3.0/howto/static-files/
STATIC_URL = '/static/'
STATICFILES_DIRS = [ os.path.join(BASE_DIR, "static") ]
+
+# XML-RPC interface of opennebula
+OPENNEBULA_URL = 'https://opennebula.example.com:2634/RPC2'
+
+# user:pass for accessing opennebula
+OPENNEBULA_USER_PASS = 'user:password'
+
+# See https://django-auth-ldap.readthedocs.io/en/latest/authentication.html
+LDAP_ADMIN_DN=""
+LDAP_ADMIN_PASSWORD=""
+LDAP_SERVER_URI = ""
+
+# Stripe (Credit Card payments)
+STRIPE_KEY=""
+STRIPE_PUBLIC_KEY=""
+
+# The django secret key
+SECRET_KEY=get_random_secret_key()
+
+
+# Overwrite settings with local settings, if existing
+try:
+ from uncloud.local_settings import *
+except (ModuleNotFoundError, ImportError):
+ pass
diff --git a/uncloud_django_based/uncloud/uncloud_net/models.py b/uncloud_django_based/uncloud/uncloud_net/models.py
index 8dfff05..e56b79c 100644
--- a/uncloud_django_based/uncloud/uncloud_net/models.py
+++ b/uncloud_django_based/uncloud/uncloud_net/models.py
@@ -173,9 +173,6 @@ class VPNNetwork(Product):
wireguard_public_key = models.CharField(max_length=48)
- def save(self, *args, **kwargs):
- super().save(*args, **kwargs)
-
def delete(self, *args, **kwargs):
self.network.status = 'free'
self.network.save()
diff --git a/uncloud_django_based/uncloud/uncloud_pay/models.py b/uncloud_django_based/uncloud/uncloud_pay/models.py
index bcce598..55cf1ea 100644
--- a/uncloud_django_based/uncloud/uncloud_pay/models.py
+++ b/uncloud_django_based/uncloud/uncloud_pay/models.py
@@ -4,7 +4,7 @@ from django.contrib.auth import get_user_model
from django.core.validators import MinValueValidator
from django.utils.translation import gettext_lazy as _
from django.utils import timezone
-from django.core.exceptions import ObjectDoesNotExist
+from django.core.exceptions import ObjectDoesNotExist, ValidationError
import uuid
import logging
@@ -811,7 +811,7 @@ class Order(models.Model):
# TODO: enforce ending_date - starting_date to be larger than recurring_period.
creation_date = models.DateTimeField(auto_now_add=True)
- starting_date = models.DateTimeField()
+ starting_date = models.DateTimeField(default=timezone.now)
ending_date = models.DateTimeField(blank=True,
null=True)
@@ -918,6 +918,17 @@ class Product(UncloudModel):
# _state.adding is switched to false after super(...) call.
being_created = self._state.adding
+ # First time saving - create an order
+ if not self.order:
+ billing_address = BillingAddress.get_preferred_address_for(self.owner)
+
+ if not billing_address:
+ raise ValidationError("Cannot create order without a billing address")
+
+ self.order = Order(owner=self.owner,
+ billing_address=billing_address)
+
+
super(Product, self).save(*args, **kwargs)
# Make sure we only create records on creation.
diff --git a/uncloud_django_based/uncloud/uncloud_pay/stripe.py b/uncloud_django_based/uncloud/uncloud_pay/stripe.py
index f23002b..2ed4ef2 100644
--- a/uncloud_django_based/uncloud/uncloud_pay/stripe.py
+++ b/uncloud_django_based/uncloud/uncloud_pay/stripe.py
@@ -3,9 +3,9 @@ import stripe.error
import logging
from django.core.exceptions import ObjectDoesNotExist
-import uncloud_pay.models
+from django.conf import settings
-import uncloud.secrets
+import uncloud_pay.models
# Static stripe configuration used below.
CURRENCY = 'chf'
@@ -14,7 +14,7 @@ CURRENCY = 'chf'
# https://stripe.com/docs/payments/save-and-reuse
# For internal use only.
-stripe.api_key = uncloud.secrets.STRIPE_KEY
+stripe.api_key = settings.STRIPE_KEY
# Helper (decorator) used to catch errors raised by stripe logic.
# Catch errors that should not be displayed to the end user, raise again.
@@ -64,7 +64,7 @@ def handle_stripe_error(f):
# Actual Stripe logic.
def public_api_key():
- return uncloud.secrets.STRIPE_PUBLIC_KEY
+ return settings.STRIPE_PUBLIC_KEY
def get_customer_id_for(user):
try:
From eea654a9f8b71d8dabc112b0c31476878edc6167 Mon Sep 17 00:00:00 2001
From: Nico Schottelius
Date: Sat, 2 May 2020 19:15:48 +0200
Subject: [PATCH 007/241] Phase in new beta/vm view for creating vms + orders +
bills
---
.../uncloud/uncloud/settings.py | 5 +--
uncloud_django_based/uncloud/uncloud/urls.py | 4 ++
.../uncloud/uncloud_vm/models.py | 1 +
.../uncloud/uncloud_vm/serializers.py | 19 +++++++++
.../uncloud/uncloud_vm/views.py | 40 +++++++++++++++++++
5 files changed, 65 insertions(+), 4 deletions(-)
diff --git a/uncloud_django_based/uncloud/uncloud/settings.py b/uncloud_django_based/uncloud/uncloud/settings.py
index 527749d..884c370 100644
--- a/uncloud_django_based/uncloud/uncloud/settings.py
+++ b/uncloud_django_based/uncloud/uncloud/settings.py
@@ -172,10 +172,6 @@ OPENNEBULA_URL = 'https://opennebula.example.com:2634/RPC2'
# user:pass for accessing opennebula
OPENNEBULA_USER_PASS = 'user:password'
-# See https://django-auth-ldap.readthedocs.io/en/latest/authentication.html
-LDAP_ADMIN_DN=""
-LDAP_ADMIN_PASSWORD=""
-LDAP_SERVER_URI = ""
# Stripe (Credit Card payments)
STRIPE_KEY=""
@@ -184,6 +180,7 @@ STRIPE_PUBLIC_KEY=""
# The django secret key
SECRET_KEY=get_random_secret_key()
+ALLOWED_HOSTS = []
# Overwrite settings with local settings, if existing
try:
diff --git a/uncloud_django_based/uncloud/uncloud/urls.py b/uncloud_django_based/uncloud/uncloud/urls.py
index 4d0ada1..5539846 100644
--- a/uncloud_django_based/uncloud/uncloud/urls.py
+++ b/uncloud_django_based/uncloud/uncloud/urls.py
@@ -31,12 +31,16 @@ from uncloud_service import views as serviceviews
router = routers.DefaultRouter()
+# Beta endpoints
+router.register(r'beta/vm', vmviews.NicoVMProductViewSet, basename='nicovmproduct')
+
# VM
router.register(r'vm/snapshot', vmviews.VMSnapshotProductViewSet, basename='vmsnapshotproduct')
router.register(r'vm/diskimage', vmviews.VMDiskImageProductViewSet, basename='vmdiskimageproduct')
router.register(r'vm/disk', vmviews.VMDiskProductViewSet, basename='vmdiskproduct')
router.register(r'vm/vm', vmviews.VMProductViewSet, basename='vmproduct')
+
# creates VM from os image
#router.register(r'vm/ipv6onlyvm', vmviews.VMProductViewSet, basename='vmproduct')
# ... AND adds IPv4 mapping
diff --git a/uncloud_django_based/uncloud/uncloud_vm/models.py b/uncloud_django_based/uncloud/uncloud_vm/models.py
index 5dacdbe..39a5f40 100644
--- a/uncloud_django_based/uncloud/uncloud_vm/models.py
+++ b/uncloud_django_based/uncloud/uncloud_vm/models.py
@@ -69,6 +69,7 @@ class VMProduct(Product):
cores = models.IntegerField()
ram_in_gb = models.FloatField()
+ # Optional disk
primary_disk = models.ForeignKey('VMDiskProduct', on_delete=models.CASCADE, null=True)
# Default recurring price is PER_MONTH, see uncloud_pay.models.Product.
diff --git a/uncloud_django_based/uncloud/uncloud_vm/serializers.py b/uncloud_django_based/uncloud/uncloud_vm/serializers.py
index 92c7fe8..2c7137e 100644
--- a/uncloud_django_based/uncloud/uncloud_vm/serializers.py
+++ b/uncloud_django_based/uncloud/uncloud_vm/serializers.py
@@ -120,6 +120,25 @@ class OrderVMProductSerializer(VMProductSerializer):
# Nico's playground.
+class NicoVMProductSerializer(serializers.ModelSerializer):
+ primary_disk = CreateVMDiskProductSerializer()
+ snapshots = VMSnapshotProductSerializer(many=True, read_only=True)
+ disks = VMDiskProductSerializer(many=True, read_only=True)
+
+ class Meta:
+ model = VMProduct
+ read_only_fields = ['uuid', 'order', 'owner', 'status',
+ 'vmhost', 'vmcluster',
+ 'extra_data' ]
+ fields = read_only_fields + [ 'name',
+ 'cores',
+ 'ram_in_gb',
+ 'primary_disk',
+ 'snapshots',
+ 'disks' ]
+
+
+
class DCLVMProductSerializer(serializers.HyperlinkedModelSerializer):
"""
Create an interface similar to standard DCL
diff --git a/uncloud_django_based/uncloud/uncloud_vm/views.py b/uncloud_django_based/uncloud/uncloud_vm/views.py
index 1dead62..39b7668 100644
--- a/uncloud_django_based/uncloud/uncloud_vm/views.py
+++ b/uncloud_django_based/uncloud/uncloud_vm/views.py
@@ -179,6 +179,46 @@ class VMProductViewSet(ProductViewSet):
return Response(VMProductSerializer(vm, context={'request': request}).data)
+class NicoVMProductViewSet(ProductViewSet):
+ permission_classes = [permissions.IsAuthenticated]
+ serializer_class = NicoVMProductSerializer
+
+ def get_queryset(self):
+ obj = VMProduct.objects.filter(owner=self.request.user)
+
+ return obj
+
+ # Use a database transaction so that we do not get half-created structure
+ # if something goes wrong.
+ @transaction.atomic
+ def create(self, request):
+ # Extract serializer data.
+ 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,
+ **serializer.validated_data.pop("primary_disk"))
+
+ # Create VM.
+ vm = serializer.save(owner=request.user, order=order, primary_disk=disk)
+ disk.vm = vm
+ disk.save()
+
+ return Response(VMProductSerializer(vm, context={'request': request}).data)
+
+
###
# Admin stuff.
From 927fb206712d92ec33d9969c159b951a9a7ec7ca Mon Sep 17 00:00:00 2001
From: Nico Schottelius
Date: Sat, 2 May 2020 20:31:36 +0200
Subject: [PATCH 008/241] Versionise API and cleanups
---
uncloud_django_based/uncloud/uncloud/urls.py | 44 +++++++++----------
.../uncloud/uncloud_pay/models.py | 6 ++-
.../uncloud/uncloud_vm/models.py | 4 +-
.../uncloud/uncloud_vm/serializers.py | 11 ++---
.../uncloud/uncloud_vm/views.py | 1 +
5 files changed, 32 insertions(+), 34 deletions(-)
diff --git a/uncloud_django_based/uncloud/uncloud/urls.py b/uncloud_django_based/uncloud/uncloud/urls.py
index 5539846..05b1f0f 100644
--- a/uncloud_django_based/uncloud/uncloud/urls.py
+++ b/uncloud_django_based/uncloud/uncloud/urls.py
@@ -35,10 +35,10 @@ router = routers.DefaultRouter()
router.register(r'beta/vm', vmviews.NicoVMProductViewSet, basename='nicovmproduct')
# VM
-router.register(r'vm/snapshot', vmviews.VMSnapshotProductViewSet, basename='vmsnapshotproduct')
-router.register(r'vm/diskimage', vmviews.VMDiskImageProductViewSet, basename='vmdiskimageproduct')
-router.register(r'vm/disk', vmviews.VMDiskProductViewSet, basename='vmdiskproduct')
-router.register(r'vm/vm', vmviews.VMProductViewSet, basename='vmproduct')
+router.register(r'v1/vm/snapshot', vmviews.VMSnapshotProductViewSet, basename='vmsnapshotproduct')
+router.register(r'v1/vm/diskimage', vmviews.VMDiskImageProductViewSet, basename='vmdiskimageproduct')
+router.register(r'v1/vm/disk', vmviews.VMDiskProductViewSet, basename='vmdiskproduct')
+router.register(r'v1/vm/vm', vmviews.VMProductViewSet, basename='vmproduct')
# creates VM from os image
@@ -47,35 +47,35 @@ router.register(r'vm/vm', vmviews.VMProductViewSet, basename='vmproduct')
#router.register(r'vm/dualstackvm', vmviews.VMProductViewSet, basename='vmproduct')
# Services
-router.register(r'service/matrix', serviceviews.MatrixServiceProductViewSet, basename='matrixserviceproduct')
-router.register(r'service/generic', serviceviews.GenericServiceProductViewSet, basename='genericserviceproduct')
+router.register(r'v1/service/matrix', serviceviews.MatrixServiceProductViewSet, basename='matrixserviceproduct')
+router.register(r'v1/service/generic', serviceviews.GenericServiceProductViewSet, basename='genericserviceproduct')
# Net
-router.register(r'net/vpn', netviews.VPNNetworkViewSet, basename='vpnnet')
-router.register(r'net/vpnreservation', netviews.VPNNetworkReservationViewSet, basename='vpnnetreservation')
+router.register(r'v1/net/vpn', netviews.VPNNetworkViewSet, basename='vpnnet')
+router.register(r'v1/admin/vpnreservation', netviews.VPNNetworkReservationViewSet, basename='vpnnetreservation')
# Pay
-router.register(r'address', payviews.BillingAddressViewSet, basename='address')
-router.register(r'bill', payviews.BillViewSet, basename='bill')
-router.register(r'order', payviews.OrderViewSet, basename='order')
-router.register(r'payment', payviews.PaymentViewSet, basename='payment')
-router.register(r'payment-method', payviews.PaymentMethodViewSet, basename='payment-method')
+router.register(r'v1/my/address', payviews.BillingAddressViewSet, basename='address')
+router.register(r'v1/my/bill', payviews.BillViewSet, basename='bill')
+router.register(r'v1/my/order', payviews.OrderViewSet, basename='order')
+router.register(r'v1/my/payment', payviews.PaymentViewSet, basename='payment')
+router.register(r'v1/my/payment-method', payviews.PaymentMethodViewSet, basename='payment-method')
# admin/staff urls
-router.register(r'admin/bill', payviews.AdminBillViewSet, basename='admin/bill')
-router.register(r'admin/payment', payviews.AdminPaymentViewSet, basename='admin/payment')
-router.register(r'admin/order', payviews.AdminOrderViewSet, basename='admin/order')
-router.register(r'admin/vmhost', vmviews.VMHostViewSet)
-router.register(r'admin/vmcluster', vmviews.VMClusterViewSet)
-router.register(r'admin/vpnpool', netviews.VPNPoolViewSet)
-router.register(r'admin/opennebula', oneviews.VMViewSet, basename='opennebula')
+router.register(r'v1/admin/bill', payviews.AdminBillViewSet, basename='admin/bill')
+router.register(r'v1/admin/payment', payviews.AdminPaymentViewSet, basename='admin/payment')
+router.register(r'v1/admin/order', payviews.AdminOrderViewSet, basename='admin/order')
+router.register(r'v1/admin/vmhost', vmviews.VMHostViewSet)
+router.register(r'v1/admin/vmcluster', vmviews.VMClusterViewSet)
+router.register(r'v1/admin/vpnpool', netviews.VPNPoolViewSet)
+router.register(r'v1/admin/opennebula', oneviews.VMViewSet, basename='opennebula')
# User/Account
-router.register(r'user', authviews.UserViewSet, basename='user')
-router.register(r'admin/user', authviews.AdminUserViewSet, basename='useradmin')
+router.register(r'v1/my/user', authviews.UserViewSet, basename='user')
+router.register(r'v1/admin/user', authviews.AdminUserViewSet, basename='useradmin')
urlpatterns = [
path('', include(router.urls)),
diff --git a/uncloud_django_based/uncloud/uncloud_pay/models.py b/uncloud_django_based/uncloud/uncloud_pay/models.py
index 55cf1ea..b06473e 100644
--- a/uncloud_django_based/uncloud/uncloud_pay/models.py
+++ b/uncloud_django_based/uncloud/uncloud_pay/models.py
@@ -825,7 +825,11 @@ class Order(models.Model):
# Trigger initial bill generation at order creation.
def save(self, *args, **kwargs):
- super(Order, self).save(*args, **kwargs)
+ if self.ending_date and self.ending_date < self.starting_date:
+ raise ValidationError("End date cannot be before starting date")
+
+ super().save(*args, **kwargs)
+
Bill.generate_for(self.starting_date.year, self.starting_date.month, self.owner)
@property
diff --git a/uncloud_django_based/uncloud/uncloud_vm/models.py b/uncloud_django_based/uncloud/uncloud_vm/models.py
index 39a5f40..06b5386 100644
--- a/uncloud_django_based/uncloud/uncloud_vm/models.py
+++ b/uncloud_django_based/uncloud/uncloud_vm/models.py
@@ -69,9 +69,6 @@ class VMProduct(Product):
cores = models.IntegerField()
ram_in_gb = models.FloatField()
- # Optional disk
- primary_disk = models.ForeignKey('VMDiskProduct', on_delete=models.CASCADE, null=True)
-
# Default recurring price is PER_MONTH, see uncloud_pay.models.Product.
@property
def recurring_price(self):
@@ -175,6 +172,7 @@ class VMDiskProduct(Product):
super().save(*args, **kwargs)
+
class VMNetworkCard(models.Model):
vm = models.ForeignKey(VMProduct, on_delete=models.CASCADE)
diff --git a/uncloud_django_based/uncloud/uncloud_vm/serializers.py b/uncloud_django_based/uncloud/uncloud_vm/serializers.py
index 2c7137e..a04af8f 100644
--- a/uncloud_django_based/uncloud/uncloud_vm/serializers.py
+++ b/uncloud_django_based/uncloud/uncloud_vm/serializers.py
@@ -121,22 +121,17 @@ class OrderVMProductSerializer(VMProductSerializer):
# Nico's playground.
class NicoVMProductSerializer(serializers.ModelSerializer):
- primary_disk = CreateVMDiskProductSerializer()
snapshots = VMSnapshotProductSerializer(many=True, read_only=True)
- disks = VMDiskProductSerializer(many=True, read_only=True)
class Meta:
model = VMProduct
read_only_fields = ['uuid', 'order', 'owner', 'status',
- 'vmhost', 'vmcluster',
+ 'vmhost', 'vmcluster', 'snapshots',
'extra_data' ]
fields = read_only_fields + [ 'name',
'cores',
- 'ram_in_gb',
- 'primary_disk',
- 'snapshots',
- 'disks' ]
-
+ 'ram_in_gb'
+ ]
class DCLVMProductSerializer(serializers.HyperlinkedModelSerializer):
diff --git a/uncloud_django_based/uncloud/uncloud_vm/views.py b/uncloud_django_based/uncloud/uncloud_vm/views.py
index 39b7668..2d0a693 100644
--- a/uncloud_django_based/uncloud/uncloud_vm/views.py
+++ b/uncloud_django_based/uncloud/uncloud_vm/views.py
@@ -195,6 +195,7 @@ class NicoVMProductViewSet(ProductViewSet):
# Extract serializer data.
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")
From 7d708cfbb685c655fdaaf0672e9df6cebb5fbde9 Mon Sep 17 00:00:00 2001
From: Nico Schottelius
Date: Sat, 2 May 2020 20:42:09 +0200
Subject: [PATCH 009/241] Fix empty vat number bug
---
uncloud_django_based/uncloud/uncloud_pay/views.py | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/uncloud_django_based/uncloud/uncloud_pay/views.py b/uncloud_django_based/uncloud/uncloud_pay/views.py
index 82b5787..59d310e 100644
--- a/uncloud_django_based/uncloud/uncloud_pay/views.py
+++ b/uncloud_django_based/uncloud/uncloud_pay/views.py
@@ -215,10 +215,11 @@ class BillingAddressViewSet(mixins.CreateModelMixin,
# Validate VAT numbers.
country = serializer.validated_data["country"]
- vat_number = serializer.validated_data["vat_number"]
# We ignore empty VAT numbers.
- if vat_number != "":
+ if 'vat_number' in serializer.validated_data and serializer.validated_data["vat_number"] != "":
+ vat_number = serializer.validated_data["vat_number"]
+
if not validate_vat(country, vat_number):
return Response(
{'error': 'Malformed VAT number.'},
From 736fe274935a33006d3eb84f21025872cf536155 Mon Sep 17 00:00:00 2001
From: Nico Schottelius
Date: Sat, 2 May 2020 20:45:19 +0200
Subject: [PATCH 010/241] Add issues.org as a shortcut for registering issues
---
issues.org | 5 +++++
1 file changed, 5 insertions(+)
create mode 100644 issues.org
diff --git a/issues.org b/issues.org
new file mode 100644
index 0000000..f79c1dc
--- /dev/null
+++ b/issues.org
@@ -0,0 +1,5 @@
+* Intro
+ This file lists issues that should be handled, are small and likely
+ not yet high prio.
+* Issues
+** TODO Register prefered address in User model
From 4097c2ce13bfe862a5312ff9952ae625a33c05b2 Mon Sep 17 00:00:00 2001
From: Nico Schottelius
Date: Sat, 2 May 2020 21:20:14 +0200
Subject: [PATCH 011/241] BillingAddress: make mget_preferred_address a
classmethod
---
uncloud_django_based/uncloud/uncloud_pay/models.py | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/uncloud_django_based/uncloud/uncloud_pay/models.py b/uncloud_django_based/uncloud/uncloud_pay/models.py
index b06473e..3b4535c 100644
--- a/uncloud_django_based/uncloud/uncloud_pay/models.py
+++ b/uncloud_django_based/uncloud/uncloud_pay/models.py
@@ -455,9 +455,9 @@ class BillingAddress(models.Model):
def get_addresses_for(user):
return BillingAddress.objects.filter(owner=user)
- @staticmethod
- def get_preferred_address_for(user):
- addresses = get_addresses_for(user)
+ @classmethod
+ def get_preferred_address_for(cls, user):
+ addresses = cls.get_addresses_for(user)
if len(addresses) == 0:
return None
else:
@@ -927,7 +927,7 @@ class Product(UncloudModel):
billing_address = BillingAddress.get_preferred_address_for(self.owner)
if not billing_address:
- raise ValidationError("Cannot create order without a billing address")
+ raise ValidationError("Cannot order without a billing address")
self.order = Order(owner=self.owner,
billing_address=billing_address)
From 9ef5309b91f2f60ae5dead5d02b9a95f83cda4d9 Mon Sep 17 00:00:00 2001
From: Nico Schottelius
Date: Sat, 2 May 2020 21:21:29 +0200
Subject: [PATCH 012/241] +db migrations for pay/vm
Signed-off-by: Nico Schottelius
---
.../migrations/0008_auto_20200502_1921.py | 19 +++++++++++++++++++
.../0013_remove_vmproduct_primary_disk.py | 17 +++++++++++++++++
2 files changed, 36 insertions(+)
create mode 100644 uncloud_django_based/uncloud/uncloud_pay/migrations/0008_auto_20200502_1921.py
create mode 100644 uncloud_django_based/uncloud/uncloud_vm/migrations/0013_remove_vmproduct_primary_disk.py
diff --git a/uncloud_django_based/uncloud/uncloud_pay/migrations/0008_auto_20200502_1921.py b/uncloud_django_based/uncloud/uncloud_pay/migrations/0008_auto_20200502_1921.py
new file mode 100644
index 0000000..c244357
--- /dev/null
+++ b/uncloud_django_based/uncloud/uncloud_pay/migrations/0008_auto_20200502_1921.py
@@ -0,0 +1,19 @@
+# Generated by Django 3.0.5 on 2020-05-02 19:21
+
+from django.db import migrations, models
+import django.utils.timezone
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('uncloud_pay', '0007_auto_20200418_0737'),
+ ]
+
+ operations = [
+ migrations.AlterField(
+ model_name='order',
+ name='starting_date',
+ field=models.DateTimeField(default=django.utils.timezone.now),
+ ),
+ ]
diff --git a/uncloud_django_based/uncloud/uncloud_vm/migrations/0013_remove_vmproduct_primary_disk.py b/uncloud_django_based/uncloud/uncloud_vm/migrations/0013_remove_vmproduct_primary_disk.py
new file mode 100644
index 0000000..849012d
--- /dev/null
+++ b/uncloud_django_based/uncloud/uncloud_vm/migrations/0013_remove_vmproduct_primary_disk.py
@@ -0,0 +1,17 @@
+# Generated by Django 3.0.5 on 2020-05-02 19:21
+
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('uncloud_vm', '0012_auto_20200418_0641'),
+ ]
+
+ operations = [
+ migrations.RemoveField(
+ model_name='vmproduct',
+ name='primary_disk',
+ ),
+ ]
From 028f1ebe6e3e80121e58fe1bf50ffb8535ba0e91 Mon Sep 17 00:00:00 2001
From: Nico Schottelius
Date: Sat, 2 May 2020 22:03:34 +0200
Subject: [PATCH 013/241] Entry point /beta/vm/ works for creating VM + order
---
issues.org | 1 +
.../uncloud/uncloud_pay/models.py | 26 +++++++++------
.../uncloud/uncloud_vm/models.py | 6 ++++
.../uncloud/uncloud_vm/serializers.py | 1 +
.../uncloud/uncloud_vm/views.py | 32 ++-----------------
5 files changed, 28 insertions(+), 38 deletions(-)
diff --git a/issues.org b/issues.org
index f79c1dc..840ec3c 100644
--- a/issues.org
+++ b/issues.org
@@ -3,3 +3,4 @@
not yet high prio.
* Issues
** TODO Register prefered address in User model
+** TODO Allow to specify different recurring periods
diff --git a/uncloud_django_based/uncloud/uncloud_pay/models.py b/uncloud_django_based/uncloud/uncloud_pay/models.py
index 3b4535c..a326810 100644
--- a/uncloud_django_based/uncloud/uncloud_pay/models.py
+++ b/uncloud_django_based/uncloud/uncloud_pay/models.py
@@ -855,6 +855,11 @@ class Order(models.Model):
recurring_price=recurring_price,
description=description)
+ def __str__(self):
+ return "Order {} created at {}, {}->{}, recurring period {}".format(
+ self.uuid, self.creation_date,
+ self.starting_date, self.ending_date,
+ self.recurring_period)
class OrderRecord(models.Model):
@@ -925,23 +930,26 @@ class Product(UncloudModel):
# First time saving - create an order
if not self.order:
billing_address = BillingAddress.get_preferred_address_for(self.owner)
+ print(billing_address)
if not billing_address:
raise ValidationError("Cannot order without a billing address")
- self.order = Order(owner=self.owner,
+ self.order = Order.objects.create(owner=self.owner,
billing_address=billing_address)
- super(Product, self).save(*args, **kwargs)
+ print("in save op: {}".format(self))
+ print(self.order)
+ super().save(*args, **kwargs)
- # Make sure we only create records on creation.
- if being_created:
- record = OrderRecord(
- one_time_price=self.one_time_price,
- recurring_price=self.recurring_price,
- description=self.description)
- self.order.orderrecord_set.add(record, bulk=False)
+ # # Make sure we only create records on creation.
+ # if being_created:
+ # record = OrderRecord(
+ # one_time_price=self.one_time_price,
+ # recurring_price=self.recurring_price,
+ # description=self.description)
+ # self.order.orderrecord_set.add(record, bulk=False)
@property
def recurring_price(self):
diff --git a/uncloud_django_based/uncloud/uncloud_vm/models.py b/uncloud_django_based/uncloud/uncloud_vm/models.py
index 06b5386..91c9291 100644
--- a/uncloud_django_based/uncloud/uncloud_vm/models.py
+++ b/uncloud_django_based/uncloud/uncloud_vm/models.py
@@ -91,6 +91,12 @@ class VMProduct(Product):
RecurringPeriod.PER_MONTH, RecurringPeriod.PER_HOUR],
RecurringPeriod.choices))
+ def __str__(self):
+ return "VM {} ({} Cores/{} GB RAM) running on {} in cluster {}".format(
+ self.uuid, self.cores, self.ram_in_gb,
+ self.vmhost, self.vmcluster)
+
+
class VMWithOSProduct(VMProduct):
pass
diff --git a/uncloud_django_based/uncloud/uncloud_vm/serializers.py b/uncloud_django_based/uncloud/uncloud_vm/serializers.py
index a04af8f..701b187 100644
--- a/uncloud_django_based/uncloud/uncloud_vm/serializers.py
+++ b/uncloud_django_based/uncloud/uncloud_vm/serializers.py
@@ -122,6 +122,7 @@ class OrderVMProductSerializer(VMProductSerializer):
class NicoVMProductSerializer(serializers.ModelSerializer):
snapshots = VMSnapshotProductSerializer(many=True, read_only=True)
+ order = serializers.StringRelatedField()
class Meta:
model = VMProduct
diff --git a/uncloud_django_based/uncloud/uncloud_vm/views.py b/uncloud_django_based/uncloud/uncloud_vm/views.py
index 2d0a693..cf90891 100644
--- a/uncloud_django_based/uncloud/uncloud_vm/views.py
+++ b/uncloud_django_based/uncloud/uncloud_vm/views.py
@@ -185,40 +185,14 @@ class NicoVMProductViewSet(ProductViewSet):
def get_queryset(self):
obj = VMProduct.objects.filter(owner=self.request.user)
-
return obj
- # Use a database transaction so that we do not get half-created structure
- # if something goes wrong.
- @transaction.atomic
def create(self, request):
- # Extract serializer data.
- serializer = self.get_serializer(data=request.data)
+ serializer = self.serializer_class(data=request.data, context={'request': request})
serializer.is_valid(raise_exception=True)
+ vm = serializer.save(owner=request.user)
- 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,
- **serializer.validated_data.pop("primary_disk"))
-
- # Create VM.
- vm = serializer.save(owner=request.user, order=order, primary_disk=disk)
- disk.vm = vm
- disk.save()
-
- return Response(VMProductSerializer(vm, context={'request': request}).data)
-
+ return Response(serializer.data)
###
# Admin stuff.
From c835c874d5e17da2a49d6ed1360556081244d945 Mon Sep 17 00:00:00 2001
From: Nico Schottelius
Date: Sat, 2 May 2020 22:48:05 +0200
Subject: [PATCH 014/241] [BREAKING] make Order a stand-alone version
I think that while the idea of an Orderrecord is good, we might get
away / have a simpler implementation if we only use orders and
reference them where needed.
I saved the previous Order model for easy rollback, if my assumption
is wrong.
---
.../migrations/0009_auto_20200502_2047.py | 47 ++++++++++++++
.../uncloud/uncloud_pay/models.py | 65 ++++++++++++++++++-
2 files changed, 110 insertions(+), 2 deletions(-)
create mode 100644 uncloud_django_based/uncloud/uncloud_pay/migrations/0009_auto_20200502_2047.py
diff --git a/uncloud_django_based/uncloud/uncloud_pay/migrations/0009_auto_20200502_2047.py b/uncloud_django_based/uncloud/uncloud_pay/migrations/0009_auto_20200502_2047.py
new file mode 100644
index 0000000..cb9cd78
--- /dev/null
+++ b/uncloud_django_based/uncloud/uncloud_pay/migrations/0009_auto_20200502_2047.py
@@ -0,0 +1,47 @@
+# Generated by Django 3.0.5 on 2020-05-02 20:47
+
+from django.conf import settings
+import django.core.validators
+from django.db import migrations, models
+import django.db.models.deletion
+import django.utils.timezone
+import uuid
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ migrations.swappable_dependency(settings.AUTH_USER_MODEL),
+ ('uncloud_pay', '0008_auto_20200502_1921'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='order',
+ name='one_time_price',
+ field=models.DecimalField(decimal_places=2, default=0.0, max_digits=10, validators=[django.core.validators.MinValueValidator(0)]),
+ ),
+ migrations.AddField(
+ model_name='order',
+ name='recurring_price',
+ field=models.DecimalField(decimal_places=2, default=0.0, max_digits=10, validators=[django.core.validators.MinValueValidator(0)]),
+ ),
+ migrations.AddField(
+ model_name='order',
+ name='replaced_by',
+ field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='uncloud_pay.Order'),
+ ),
+ migrations.CreateModel(
+ name='OrderTimothee',
+ fields=[
+ ('uuid', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
+ ('creation_date', models.DateTimeField(auto_now_add=True)),
+ ('starting_date', models.DateTimeField(default=django.utils.timezone.now)),
+ ('ending_date', models.DateTimeField(blank=True, null=True)),
+ ('recurring_period', models.CharField(choices=[('ONCE', 'Onetime'), ('YEAR', 'Per Year'), ('MONTH', 'Per Month'), ('WEEK', 'Per Week'), ('DAY', 'Per Day'), ('HOUR', 'Per Hour'), ('MINUTE', 'Per Minute'), ('SECOND', 'Per Second')], default='MONTH', max_length=32)),
+ ('bill', models.ManyToManyField(blank=True, editable=False, to='uncloud_pay.Bill')),
+ ('billing_address', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='uncloud_pay.BillingAddress')),
+ ('owner', models.ForeignKey(editable=False, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
+ ],
+ ),
+ ]
diff --git a/uncloud_django_based/uncloud/uncloud_pay/models.py b/uncloud_django_based/uncloud/uncloud_pay/models.py
index a326810..9a8a49a 100644
--- a/uncloud_django_based/uncloud/uncloud_pay/models.py
+++ b/uncloud_django_based/uncloud/uncloud_pay/models.py
@@ -809,6 +809,64 @@ class Order(models.Model):
editable=False)
billing_address = models.ForeignKey(BillingAddress, on_delete=models.CASCADE)
+ # TODO: enforce ending_date - starting_date to be larger than recurring_period.
+ creation_date = models.DateTimeField(auto_now_add=True)
+ starting_date = models.DateTimeField(default=timezone.now)
+ ending_date = models.DateTimeField(blank=True,
+ null=True)
+
+ bill = models.ManyToManyField(Bill,
+ editable=False,
+ blank=True)
+
+ recurring_period = models.CharField(max_length=32,
+ choices = RecurringPeriod.choices,
+ default = RecurringPeriod.PER_MONTH)
+
+ one_time_price = models.DecimalField(default=0.0,
+ max_digits=AMOUNT_MAX_DIGITS,
+ decimal_places=AMOUNT_DECIMALS,
+ validators=[MinValueValidator(0)])
+
+ recurring_price = models.DecimalField(default=0.0,
+ max_digits=AMOUNT_MAX_DIGITS,
+ decimal_places=AMOUNT_DECIMALS,
+ validators=[MinValueValidator(0)])
+
+ replaced_by = models.ForeignKey('self',
+ on_delete=models.PROTECT,
+ blank=True,
+ null=True)
+
+ # Trigger initial bill generation at order creation.
+ def save(self, *args, **kwargs):
+ if self.ending_date and self.ending_date < self.starting_date:
+ raise ValidationError("End date cannot be before starting date")
+
+ super().save(*args, **kwargs)
+
+ Bill.generate_for(self.starting_date.year, self.starting_date.month, self.owner)
+
+ # Used by uncloud_pay tests.
+ @property
+ def bills(self):
+ return Bill.objects.filter(order=self)
+
+ def __str__(self):
+ return "Order {} created at {}, {}->{}, recurring period {}. Price one time {}, recurring {}".format(
+ self.uuid, self.creation_date,
+ self.starting_date, self.ending_date,
+ self.recurring_period,
+ self.one_time_price,
+ self.recurring_price)
+
+class OrderTimothee(models.Model):
+ uuid = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
+ owner = models.ForeignKey(get_user_model(),
+ on_delete=models.CASCADE,
+ editable=False)
+ billing_address = models.ForeignKey(BillingAddress, on_delete=models.CASCADE)
+
# TODO: enforce ending_date - starting_date to be larger than recurring_period.
creation_date = models.DateTimeField(auto_now_add=True)
starting_date = models.DateTimeField(default=timezone.now)
@@ -856,10 +914,13 @@ class Order(models.Model):
description=description)
def __str__(self):
- return "Order {} created at {}, {}->{}, recurring period {}".format(
+ return "Order {} created at {}, {}->{}, recurring period {}. Price one time {}, recurring {}".format(
self.uuid, self.creation_date,
self.starting_date, self.ending_date,
- self.recurring_period)
+ self.recurring_period,
+ self.one_time_price,
+ self.recurring_price)
+
class OrderRecord(models.Model):
From 99a18232aaacc0872f294952291bc3dbeb5b5c80 Mon Sep 17 00:00:00 2001
From: Nico Schottelius
Date: Sat, 2 May 2020 23:44:20 +0200
Subject: [PATCH 015/241] VMs now properly set their pricing
---
.../uncloud/uncloud_pay/models.py | 19 +++++++++----------
.../uncloud/uncloud_vm/models.py | 3 ++-
2 files changed, 11 insertions(+), 11 deletions(-)
diff --git a/uncloud_django_based/uncloud/uncloud_pay/models.py b/uncloud_django_based/uncloud/uncloud_pay/models.py
index 9a8a49a..aca226e 100644
--- a/uncloud_django_based/uncloud/uncloud_pay/models.py
+++ b/uncloud_django_based/uncloud/uncloud_pay/models.py
@@ -845,15 +845,15 @@ class Order(models.Model):
super().save(*args, **kwargs)
- Bill.generate_for(self.starting_date.year, self.starting_date.month, self.owner)
+# Bill.generate_for(self.starting_date.year, self.starting_date.month, self.owner)
- # Used by uncloud_pay tests.
- @property
- def bills(self):
- return Bill.objects.filter(order=self)
+ # # Used by uncloud_pay tests.
+ # @property
+ # def bills(self):
+ # return Bill.objects.filter(order=self)
def __str__(self):
- return "Order {} created at {}, {}->{}, recurring period {}. Price one time {}, recurring {}".format(
+ return "Order {} created at {}, {}->{}, recurring period {}. One time price {}, recurring price {}".format(
self.uuid, self.creation_date,
self.starting_date, self.ending_date,
self.recurring_period,
@@ -997,11 +997,10 @@ class Product(UncloudModel):
raise ValidationError("Cannot order without a billing address")
self.order = Order.objects.create(owner=self.owner,
- billing_address=billing_address)
+ billing_address=billing_address,
+ one_time_price=self.one_time_price,
+ recurring_price=self.recurring_price)
-
- print("in save op: {}".format(self))
- print(self.order)
super().save(*args, **kwargs)
# # Make sure we only create records on creation.
diff --git a/uncloud_django_based/uncloud/uncloud_vm/models.py b/uncloud_django_based/uncloud/uncloud_vm/models.py
index 91c9291..a542503 100644
--- a/uncloud_django_based/uncloud/uncloud_vm/models.py
+++ b/uncloud_django_based/uncloud/uncloud_vm/models.py
@@ -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
@@ -79,6 +79,7 @@ class VMProduct(Product):
self.name,
self.cores,
self.ram_in_gb)
+
@property
def description(self):
return "Virtual machine '{}': {} core(s), {}GB memory".format(
From e3b28354fef7cff2afdc878030817b97153d4986 Mon Sep 17 00:00:00 2001
From: Nico Schottelius
Date: Tue, 5 May 2020 15:19:04 +0200
Subject: [PATCH 016/241] ++notes
---
.../doc/README-how-to-configure-remote-uncloud-clients.org | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/uncloud_django_based/uncloud/doc/README-how-to-configure-remote-uncloud-clients.org b/uncloud_django_based/uncloud/doc/README-how-to-configure-remote-uncloud-clients.org
index 7217e1f..b48886b 100644
--- a/uncloud_django_based/uncloud/doc/README-how-to-configure-remote-uncloud-clients.org
+++ b/uncloud_django_based/uncloud/doc/README-how-to-configure-remote-uncloud-clients.org
@@ -10,6 +10,7 @@
| SSH -L tunnel | All nodes can use [::1]:5432 | SSH setup can be fragile |
| ssh djangohost manage.py | All DB ops locally | Code is only executed on django host |
| https + token | Rest alike / consistent access | Code is only executed on django host |
+| from_django | Everything is on the django host | main host can become bottleneck |
** remote vs. local Django code execution
- If manage.py is executed locally (= on the client), it can
check/modify local configs
@@ -19,3 +20,9 @@
- Remote execution (= on the primary django host) can acess the db
via unix socket
- However remote execution cannot check local state
+** from_django
+ - might reuse existing methods like celery
+ - reduces the amount of things to be installed on the client to
+ almost zero
+ - follows the opennebula model
+ - has a single point of failurebin
From 594f1a9b69016ad3d02bcf3fe1cc65761c513a8e Mon Sep 17 00:00:00 2001
From: Nico Schottelius
Date: Tue, 5 May 2020 15:19:50 +0200
Subject: [PATCH 017/241] +hacks
---
uncloud_django_based/{ => hacks}/abk-hacks.py | 0
.../{ => hacks}/abkhack/opennebula_hacks.py | 0
uncloud_django_based/hacks/command-wrapper.sh | 18 ++++++++++++++++++
3 files changed, 18 insertions(+)
rename uncloud_django_based/{ => hacks}/abk-hacks.py (100%)
rename uncloud_django_based/{ => hacks}/abkhack/opennebula_hacks.py (100%)
create mode 100644 uncloud_django_based/hacks/command-wrapper.sh
diff --git a/uncloud_django_based/abk-hacks.py b/uncloud_django_based/hacks/abk-hacks.py
similarity index 100%
rename from uncloud_django_based/abk-hacks.py
rename to uncloud_django_based/hacks/abk-hacks.py
diff --git a/uncloud_django_based/abkhack/opennebula_hacks.py b/uncloud_django_based/hacks/abkhack/opennebula_hacks.py
similarity index 100%
rename from uncloud_django_based/abkhack/opennebula_hacks.py
rename to uncloud_django_based/hacks/abkhack/opennebula_hacks.py
diff --git a/uncloud_django_based/hacks/command-wrapper.sh b/uncloud_django_based/hacks/command-wrapper.sh
new file mode 100644
index 0000000..d6ddd13
--- /dev/null
+++ b/uncloud_django_based/hacks/command-wrapper.sh
@@ -0,0 +1,18 @@
+#!/bin/sh
+
+dbhost=$1; shift
+
+ssh -L5432:localhost:5432 "$dbhost" &
+
+python manage.py "$@"
+
+
+
+# command only needs to be active while manage command is running
+
+# -T no pseudo terminal
+
+
+# alternatively: commands output shell code
+
+# ssh uncloud@dbhost "python manage.py --hostname xxx ..."
From aa8ade473033e81664a9eacf17c89af386c3644e Mon Sep 17 00:00:00 2001
From: Nico Schottelius
Date: Tue, 5 May 2020 16:01:47 +0200
Subject: [PATCH 018/241] Add readme about identifiers
---
.../uncloud/doc/README-identifiers.org | 29 +++++++++++++++++++
1 file changed, 29 insertions(+)
create mode 100644 uncloud_django_based/uncloud/doc/README-identifiers.org
diff --git a/uncloud_django_based/uncloud/doc/README-identifiers.org b/uncloud_django_based/uncloud/doc/README-identifiers.org
new file mode 100644
index 0000000..3dbb4b5
--- /dev/null
+++ b/uncloud_django_based/uncloud/doc/README-identifiers.org
@@ -0,0 +1,29 @@
+* Identifiers
+** Problem description
+ Identifiers can be integers, strings or other objects. They should
+ be unique.
+** Approach 1: integers
+ Integers are somewhat easy to remember, but also include
+ predictable growth, which might allow access to guessed hacking
+ (obivously proper permissions should prevent this).
+** Approach 2: random uuids
+ UUIDs are 128 bit integers. Python supports uuid.uuid4() for random
+ uuids.
+** Approach 3: IPv6 addresses
+ uncloud heavily depends on IPv6 in the first place. uncloud could
+ use a /48 to identify all objects. Objects that have IPv6 addresses
+ on their own, don't need to draw from the system /48.
+*** Possible Subnetworks
+ Assuming uncloud uses a /48 to represent all resources.
+
+ | Network | Name | Description |
+ |-----------------+-----------------+----------------------------------------------|
+ | 2001:db8::/48 | uncloud network | All identifiers drawn from here |
+ | 2001:db8:1::/64 | VM network | Every VM has an IPv6 address in this network |
+ | 2001:db8:2::/64 | Bill network | Every bill has an IPv6 address |
+ | 2001:db8:3::/64 | Order network | Every order has an IPv6 address |
+ | 2001:db8:5::/64 | Product network | Every product (?) has an IPv6 address |
+ | 2001:db8:4::/64 | Disk network | Every disk is identified |
+
+*** Tests
+ [15:47:37] black3.place6:~# rbd create -s 10G ssd/2a0a:e5c0:1::8
From 892b2b6f137c97bd863b9d0ef35fcf27be952389 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timoth=C3=A9e=20Floure?=
Date: Thu, 7 May 2020 12:03:28 +0200
Subject: [PATCH 019/241] Revert "Disable vat validator to get project back
running"
This reverts commit 1cf20a2cb6c84b2db79d2e45e49d5fbb81b392e7.
---
uncloud_django_based/uncloud/uncloud_pay/views.py | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/uncloud_django_based/uncloud/uncloud_pay/views.py b/uncloud_django_based/uncloud/uncloud_pay/views.py
index 59d310e..0c68ac6 100644
--- a/uncloud_django_based/uncloud/uncloud_pay/views.py
+++ b/uncloud_django_based/uncloud/uncloud_pay/views.py
@@ -7,8 +7,8 @@ from rest_framework.response import Response
from rest_framework.decorators import action
from rest_framework.reverse import reverse
from rest_framework.decorators import renderer_classes
-#from vat_validator import validate_vat, vies
-#from vat_validator.countries import EU_COUNTRY_CODES
+from vat_validator import validate_vat, vies
+from vat_validator.countries import EU_COUNTRY_CODES
import json
import logging
@@ -16,7 +16,7 @@ import logging
from .models import *
from .serializers import *
from datetime import datetime
-#from vat_validator import sanitize_vat
+from vat_validator import sanitize_vat
import uncloud_pay.stripe as uncloud_stripe
logger = logging.getLogger(__name__)
From db3c29d17ed9ee42b56f7d6d086524a4a40d7581 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timoth=C3=A9e=20Floure?=
Date: Thu, 7 May 2020 12:05:26 +0200
Subject: [PATCH 020/241] Fix admin order creation
---
.../uncloud/uncloud_pay/serializers.py | 32 +++++++++++++++++--
.../uncloud/uncloud_pay/views.py | 4 ++-
2 files changed, 32 insertions(+), 4 deletions(-)
diff --git a/uncloud_django_based/uncloud/uncloud_pay/serializers.py b/uncloud_django_based/uncloud/uncloud_pay/serializers.py
index 1b5db24..70f5c5e 100644
--- a/uncloud_django_based/uncloud/uncloud_pay/serializers.py
+++ b/uncloud_django_based/uncloud/uncloud_pay/serializers.py
@@ -1,5 +1,6 @@
from django.contrib.auth import get_user_model
from rest_framework import serializers
+from uncloud_auth.serializers import UserSerializer
from .models import *
###
@@ -41,11 +42,36 @@ class OrderRecordSerializer(serializers.ModelSerializer):
class OrderSerializer(serializers.ModelSerializer):
- records = OrderRecordSerializer(many=True, read_only=True)
+ owner = serializers.PrimaryKeyRelatedField(queryset=get_user_model().objects.all())
+
+ def __init__(self, *args, **kwargs):
+ # Don't pass the 'fields' arg up to the superclass
+ admin = kwargs.pop('admin', None)
+
+ # Instantiate the superclass normally
+ super(OrderSerializer, self).__init__(*args, **kwargs)
+
+ # Only allows owner in admin mode.
+ if not admin:
+ self.fields.pop('owner')
+
+ def create(self, validated_data):
+ billing_address = BillingAddress.get_preferred_address_for(validated_data["owner"])
+ instance = Order(billing_address=billing_address, **validated_data)
+ instance.save()
+
+ return instance
+
+ def validate_owner(self, value):
+ if BillingAddress.get_preferred_address_for(value) == None:
+ raise serializers.ValidationError("Owner does not have a valid billing address.")
+
+ return value
+
class Meta:
model = Order
- fields = ['uuid', 'creation_date', 'starting_date', 'ending_date',
- 'bill', 'recurring_period', 'records', 'recurring_price', 'one_time_price']
+ fields = ['uuid', 'owner', 'creation_date', 'starting_date', 'ending_date',
+ 'bill', 'recurring_period', 'recurring_price', 'one_time_price']
###
diff --git a/uncloud_django_based/uncloud/uncloud_pay/views.py b/uncloud_django_based/uncloud/uncloud_pay/views.py
index 0c68ac6..54ff2f0 100644
--- a/uncloud_django_based/uncloud/uncloud_pay/views.py
+++ b/uncloud_django_based/uncloud/uncloud_pay/views.py
@@ -279,9 +279,11 @@ class AdminBillViewSet(viewsets.ModelViewSet):
return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)
class AdminOrderViewSet(viewsets.ModelViewSet):
- serializer_class = OrderSerializer
permission_classes = [permissions.IsAuthenticated]
+ def get_serializer(self, *args, **kwargs):
+ return OrderSerializer(*args, **kwargs, admin=True)
+
def get_queryset(self):
return Order.objects.all()
From 056006332639a94b2583877e6fc047349d76cb99 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timoth=C3=A9e=20Floure?=
Date: Thu, 7 May 2020 12:08:18 +0200
Subject: [PATCH 021/241] Add description field to Orders
---
.../migrations/0010_order_description.py | 19 +++++++++++++++++++
.../uncloud/uncloud_pay/models.py | 1 +
.../uncloud/uncloud_pay/serializers.py | 2 +-
3 files changed, 21 insertions(+), 1 deletion(-)
create mode 100644 uncloud_django_based/uncloud/uncloud_pay/migrations/0010_order_description.py
diff --git a/uncloud_django_based/uncloud/uncloud_pay/migrations/0010_order_description.py b/uncloud_django_based/uncloud/uncloud_pay/migrations/0010_order_description.py
new file mode 100644
index 0000000..2613bff
--- /dev/null
+++ b/uncloud_django_based/uncloud/uncloud_pay/migrations/0010_order_description.py
@@ -0,0 +1,19 @@
+# Generated by Django 3.0.6 on 2020-05-07 10:07
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('uncloud_pay', '0009_auto_20200502_2047'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='order',
+ name='description',
+ field=models.TextField(default=''),
+ preserve_default=False,
+ ),
+ ]
diff --git a/uncloud_django_based/uncloud/uncloud_pay/models.py b/uncloud_django_based/uncloud/uncloud_pay/models.py
index aca226e..1294a54 100644
--- a/uncloud_django_based/uncloud/uncloud_pay/models.py
+++ b/uncloud_django_based/uncloud/uncloud_pay/models.py
@@ -808,6 +808,7 @@ class Order(models.Model):
on_delete=models.CASCADE,
editable=False)
billing_address = models.ForeignKey(BillingAddress, on_delete=models.CASCADE)
+ description = models.TextField()
# TODO: enforce ending_date - starting_date to be larger than recurring_period.
creation_date = models.DateTimeField(auto_now_add=True)
diff --git a/uncloud_django_based/uncloud/uncloud_pay/serializers.py b/uncloud_django_based/uncloud/uncloud_pay/serializers.py
index 70f5c5e..ad50c68 100644
--- a/uncloud_django_based/uncloud/uncloud_pay/serializers.py
+++ b/uncloud_django_based/uncloud/uncloud_pay/serializers.py
@@ -70,7 +70,7 @@ class OrderSerializer(serializers.ModelSerializer):
class Meta:
model = Order
- fields = ['uuid', 'owner', 'creation_date', 'starting_date', 'ending_date',
+ fields = ['uuid', 'owner', 'description', 'creation_date', 'starting_date', 'ending_date',
'bill', 'recurring_period', 'recurring_price', 'one_time_price']
From 95d43f002f742090e644d76c9ba8c09a77397db6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timoth=C3=A9e=20Floure?=
Date: Thu, 7 May 2020 12:12:35 +0200
Subject: [PATCH 022/241] Move django-based uncloud to top-level
---
issues.org => archive/issues.org | 0
.../uncloud_django_based}/hacks/abk-hacks.py | 0
.../hacks/abkhack/opennebula_hacks.py | 0
.../uncloud_django_based}/hacks/command-wrapper.sh | 0
.../uncloud_django_based}/meow-payv1/README.md | 0
.../uncloud_django_based}/meow-payv1/config.py | 0
.../uncloud_django_based}/meow-payv1/hack-a-vpn.py | 0
.../uncloud_django_based}/meow-payv1/helper.py | 0
.../meow-payv1/products/ipv6-only-django.json | 0
.../meow-payv1/products/ipv6-only-vm.json | 0
.../meow-payv1/products/ipv6-only-vpn.json | 0
.../meow-payv1/products/ipv6box.json | 0
.../meow-payv1/products/membership.json | 0
.../meow-payv1/requirements.txt | 0
.../meow-payv1/sample-pay.conf | 0
.../uncloud_django_based}/meow-payv1/schemas.py | 0
.../uncloud_django_based}/meow-payv1/stripe_hack.py | 0
.../meow-payv1/stripe_utils.py | 0
.../uncloud_django_based}/meow-payv1/ucloud_pay.py | 0
.../uncloud_django_based}/notes-abk.md | 0
.../uncloud_django_based}/notes-nico.org | 0
.../uncloud_django_based}/plan.org | 0
.../uncloud_django_based}/uncloud/.gitignore | 0
.../uncloud_django_based}/vat_rates.csv | 0
.../uncloud_etcd_based}/bin/gen-version | 0
.../uncloud_etcd_based}/bin/uncloud | 0
.../uncloud_etcd_based}/bin/uncloud-run-reinstall | 0
.../uncloud_etcd_based}/conf/uncloud.conf | 0
.../uncloud_etcd_based}/docs/Makefile | 0
.../uncloud_etcd_based}/docs/README.md | 0
.../uncloud_etcd_based/docs}/__init__.py | 0
.../uncloud_etcd_based/docs/source}/__init__.py | 0
.../uncloud_etcd_based}/docs/source/admin-guide.rst | 0
.../uncloud_etcd_based}/docs/source/conf.py | 0
.../docs/source/diagram-code/ucloud | 0
.../uncloud_etcd_based}/docs/source/hacking.rst | 0
.../docs/source/images/ucloud.svg | 0
.../uncloud_etcd_based}/docs/source/index.rst | 0
.../docs/source/introduction.rst | 0
.../uncloud_etcd_based}/docs/source/misc/todo.rst | 0
.../docs/source/setup-install.rst | 0
.../docs/source/theory/summary.rst | 0
.../docs/source/troubleshooting.rst | 0
.../uncloud_etcd_based}/docs/source/user-guide.rst | 0
.../how-to-create-an-os-image-for-ucloud.rst | 0
.../uncloud_etcd_based}/docs/source/vm-images.rst | 0
.../uncloud_etcd_based}/scripts/uncloud | 0
.../uncloud_etcd_based}/setup.py | 0
.../uncloud_etcd_based/test}/__init__.py | 0
.../uncloud_etcd_based}/test/test_mac_local.py | 0
.../uncloud_etcd_based}/uncloud/__init__.py | 0
.../uncloud_etcd_based}/uncloud/api/README.md | 0
.../uncloud_etcd_based}/uncloud/api/__init__.py | 0
.../uncloud/api/common_fields.py | 0
.../uncloud/api/create_image_store.py | 0
.../uncloud_etcd_based}/uncloud/api/helper.py | 0
.../uncloud_etcd_based}/uncloud/api/main.py | 0
.../uncloud_etcd_based}/uncloud/api/schemas.py | 0
.../uncloud_etcd_based/uncloud/cli}/__init__.py | 0
.../uncloud_etcd_based}/uncloud/cli/helper.py | 0
.../uncloud_etcd_based}/uncloud/cli/host.py | 0
.../uncloud_etcd_based}/uncloud/cli/image.py | 0
.../uncloud_etcd_based}/uncloud/cli/main.py | 0
.../uncloud_etcd_based}/uncloud/cli/network.py | 0
.../uncloud_etcd_based}/uncloud/cli/user.py | 0
.../uncloud_etcd_based}/uncloud/cli/vm.py | 0
.../uncloud_etcd_based/uncloud/client}/__init__.py | 0
.../uncloud_etcd_based}/uncloud/client/main.py | 0
.../uncloud_etcd_based}/uncloud/common/__init__.py | 0
.../uncloud_etcd_based}/uncloud/common/classes.py | 0
.../uncloud_etcd_based}/uncloud/common/cli.py | 0
.../uncloud_etcd_based}/uncloud/common/counters.py | 0
.../uncloud/common/etcd_wrapper.py | 0
.../uncloud_etcd_based}/uncloud/common/host.py | 0
.../uncloud_etcd_based}/uncloud/common/network.py | 0
.../uncloud_etcd_based}/uncloud/common/parser.py | 0
.../uncloud_etcd_based}/uncloud/common/request.py | 0
.../uncloud_etcd_based}/uncloud/common/schemas.py | 0
.../uncloud_etcd_based}/uncloud/common/settings.py | 0
.../uncloud_etcd_based}/uncloud/common/shared.py | 0
.../uncloud/common/storage_handlers.py | 0
.../uncloud_etcd_based}/uncloud/common/vm.py | 0
.../uncloud/configure}/__init__.py | 0
.../uncloud_etcd_based}/uncloud/configure/main.py | 0
.../uncloud/filescanner/__init__.py | 0
.../uncloud_etcd_based}/uncloud/filescanner/main.py | 0
.../uncloud_etcd_based}/uncloud/hack/README.org | 0
.../uncloud_etcd_based}/uncloud/hack/__init__.py | 0
.../uncloud/hack/conf.d/ucloud-host | 0
.../uncloud_etcd_based}/uncloud/hack/config.py | 0
.../uncloud_etcd_based}/uncloud/hack/db.py | 0
.../uncloud/hack/hackcloud/.gitignore | 0
.../uncloud/hack/hackcloud/__init__.py | 0
.../uncloud/hack/hackcloud/etcd-client.sh | 0
.../uncloud/hack/hackcloud/ifdown.sh | 0
.../uncloud/hack/hackcloud/ifup.sh | 0
.../uncloud/hack/hackcloud/mac-last | 0
.../uncloud/hack/hackcloud/mac-prefix | 0
.../uncloud/hack/hackcloud/net.sh | 0
.../uncloud/hack/hackcloud/nftrules | 0
.../uncloud/hack/hackcloud/radvd.conf | 0
.../uncloud/hack/hackcloud/radvd.sh | 0
.../uncloud/hack/hackcloud/vm.sh | 0
.../uncloud_etcd_based}/uncloud/hack/host.py | 0
.../uncloud_etcd_based}/uncloud/hack/mac.py | 0
.../uncloud_etcd_based}/uncloud/hack/main.py | 0
.../uncloud_etcd_based}/uncloud/hack/net.py | 0
.../uncloud_etcd_based}/uncloud/hack/nftables.conf | 0
.../uncloud_etcd_based}/uncloud/hack/product.py | 0
.../uncloud/hack/rc-scripts/ucloud-api | 0
.../uncloud/hack/rc-scripts/ucloud-host | 0
.../uncloud/hack/rc-scripts/ucloud-metadata | 0
.../uncloud/hack/rc-scripts/ucloud-scheduler | 0
.../uncloud/hack/uncloud-hack-init-host | 0
.../uncloud_etcd_based}/uncloud/hack/uncloud-run-vm | 0
.../uncloud_etcd_based}/uncloud/hack/vm.py | 0
.../uncloud_etcd_based}/uncloud/host/__init__.py | 0
.../uncloud_etcd_based}/uncloud/host/main.py | 0
.../uncloud/host/virtualmachine.py | 0
.../uncloud/imagescanner/__init__.py | 0
.../uncloud/imagescanner/main.py | 0
.../uncloud/metadata/__init__.py | 0
.../uncloud_etcd_based}/uncloud/metadata/main.py | 0
.../uncloud_etcd_based}/uncloud/network/README | 0
.../uncloud_etcd_based/uncloud/network}/__init__.py | 0
.../uncloud/network/create-bridge.sh | 0
.../uncloud/network/create-tap.sh | 0
.../uncloud/network/create-vxlan.sh | 0
.../uncloud/network/radvd-template.conf | 0
.../uncloud_etcd_based}/uncloud/oneshot/__init__.py | 0
.../uncloud_etcd_based}/uncloud/oneshot/main.py | 0
.../uncloud/oneshot/virtualmachine.py | 0
.../uncloud/scheduler/__init__.py | 0
.../uncloud_etcd_based}/uncloud/scheduler/helper.py | 0
.../uncloud_etcd_based}/uncloud/scheduler/main.py | 0
.../uncloud/scheduler/tests}/__init__.py | 0
.../uncloud/scheduler/tests/test_basics.py | 0
.../scheduler/tests/test_dead_host_mechanism.py | 0
.../uncloud_etcd_based}/uncloud/version.py | 0
.../uncloud_etcd_based}/uncloud/vmm/__init__.py | 0
...ADME-how-to-configure-remote-uncloud-clients.org | 0
.../uncloud/doc => doc}/README-identifiers.org | 0
.../uncloud/doc => doc}/README-object-relations.md | 0
.../uncloud/doc => doc}/README-postgresql.org | 0
.../uncloud/doc => doc}/README-products.md | 0
.../uncloud/doc => doc}/README-vpn.org | 0
{uncloud_django_based/uncloud/doc => doc}/README.md | 0
uncloud_django_based/uncloud/manage.py => manage.py | 0
.../uncloud/models.dot => models.dot | 0
.../uncloud/models.png => models.png | Bin
.../uncloud_service => opennebula}/__init__.py | 0
.../uncloud/opennebula => opennebula}/admin.py | 0
.../uncloud/opennebula => opennebula}/apps.py | 0
.../management/commands/opennebula-synchosts.py | 0
.../management/commands/opennebula-syncvms.py | 0
.../management/commands/opennebula-to-uncloud.py | 0
.../migrations/0001_initial.py | 0
.../migrations/0002_auto_20200225_1335.py | 0
.../migrations/0003_auto_20200225_1428.py | 0
.../migrations/0004_auto_20200225_1816.py | 0
.../migrations/__init__.py | 0
.../uncloud/opennebula => opennebula}/models.py | 0
.../opennebula => opennebula}/serializers.py | 0
.../uncloud/opennebula => opennebula}/tests.py | 0
.../uncloud/opennebula => opennebula}/views.py | 0
.../uncloud/requirements.txt => requirements.txt | 0
.../uncloud/uncloud => uncloud}/.gitignore | 0
.../uncloud/uncloud => uncloud}/__init__.py | 0
.../uncloud/uncloud => uncloud}/asgi.py | 0
.../management/commands/uncloud.py | 0
.../uncloud/uncloud => uncloud}/models.py | 0
.../uncloud/uncloud => uncloud}/settings.py | 0
.../uncloud/uncloud => uncloud}/urls.py | 0
.../uncloud/uncloud => uncloud}/wsgi.py | 0
.../uncloud_storage => uncloud_auth}/__init__.py | 0
.../uncloud/uncloud_auth => uncloud_auth}/admin.py | 0
.../uncloud/uncloud_auth => uncloud_auth}/apps.py | 0
.../migrations/0001_initial.py | 0
.../migrations/0002_auto_20200318_1343.py | 0
.../migrations/0003_auto_20200318_1345.py | 0
.../migrations}/__init__.py | 0
.../uncloud/uncloud_auth => uncloud_auth}/models.py | 0
.../uncloud_auth => uncloud_auth}/serializers.py | 0
.../uncloud/uncloud_auth => uncloud_auth}/views.py | 0
.../migrations => uncloud_net}/__init__.py | 0
.../uncloud/uncloud_net => uncloud_net}/admin.py | 0
.../uncloud/uncloud_net => uncloud_net}/apps.py | 0
.../management/commands/vpn.py | 0
.../migrations/0001_initial.py | 0
.../migrations/0002_auto_20200409_1225.py | 0
.../migrations/0003_auto_20200417_0551.py | 0
.../docs => uncloud_net/migrations}/__init__.py | 0
.../uncloud/uncloud_net => uncloud_net}/models.py | 0
.../uncloud_net => uncloud_net}/serializers.py | 0
.../uncloud/uncloud_net => uncloud_net}/tests.py | 0
.../uncloud/uncloud_net => uncloud_net}/views.py | 0
.../docs/source => uncloud_pay}/__init__.py | 0
.../uncloud/uncloud_pay => uncloud_pay}/admin.py | 0
.../uncloud/uncloud_pay => uncloud_pay}/apps.py | 0
.../uncloud/uncloud_pay => uncloud_pay}/helpers.py | 0
.../management/commands/charge-negative-balance.py | 0
.../management/commands/generate-bills.py | 0
.../management/commands/handle-overdue-bills.py | 0
.../management/commands/import-vat-rates.py | 0
.../migrations/0001_initial.py | 0
.../migrations/0002_auto_20200305_1524.py | 0
.../migrations/0003_auto_20200305_1354.py | 0
.../migrations/0004_auto_20200409_1225.py | 0
.../migrations/0005_auto_20200413_0924.py | 0
.../migrations/0006_auto_20200415_1003.py | 0
.../migrations/0006_billingaddress.py | 0
.../migrations/0007_auto_20200418_0737.py | 0
.../migrations/0008_auto_20200502_1921.py | 0
.../migrations/0009_auto_20200502_2047.py | 0
.../migrations/0010_order_description.py | 0
.../test => uncloud_pay/migrations}/__init__.py | 0
.../uncloud/uncloud_pay => uncloud_pay}/models.py | 0
.../uncloud_pay => uncloud_pay}/serializers.py | 0
.../uncloud/uncloud_pay => uncloud_pay}/stripe.py | 0
.../uncloud_pay => uncloud_pay}/templates/bill.html | 0
.../templates/error.html.j2 | 0
.../templates/stripe-payment.html.j2 | 0
.../uncloud/uncloud_pay => uncloud_pay}/tests.py | 0
.../uncloud/uncloud_pay => uncloud_pay}/views.py | 0
.../uncloud/cli => uncloud_service}/__init__.py | 0
.../uncloud_service => uncloud_service}/admin.py | 0
.../uncloud_service => uncloud_service}/apps.py | 0
.../migrations/0001_initial.py | 0
.../migrations/0002_auto_20200418_0641.py | 0
.../migrations}/__init__.py | 0
.../uncloud_service => uncloud_service}/models.py | 0
.../serializers.py | 0
.../uncloud_service => uncloud_service}/tests.py | 0
.../uncloud_service => uncloud_service}/views.py | 0
.../configure => uncloud_storage}/__init__.py | 0
.../uncloud_storage => uncloud_storage}/admin.py | 0
.../uncloud_storage => uncloud_storage}/apps.py | 0
.../uncloud_storage => uncloud_storage}/models.py | 0
.../uncloud_storage => uncloud_storage}/tests.py | 0
.../uncloud_storage => uncloud_storage}/views.py | 0
.../uncloud/network => uncloud_vm}/__init__.py | 0
.../uncloud/uncloud_vm => uncloud_vm}/admin.py | 0
.../uncloud/uncloud_vm => uncloud_vm}/apps.py | 0
.../management/commands/vm.py | 0
.../migrations/0001_initial.py | 0
.../migrations/0002_auto_20200305_1321.py | 0
.../migrations/0003_remove_vmhost_vms.py | 0
.../migrations/0004_remove_vmproduct_vmid.py | 0
.../migrations/0004_vmproduct_primary_disk.py | 0
.../migrations/0005_auto_20200309_1258.py | 0
.../migrations/0005_auto_20200321_1058.py | 0
.../migrations/0006_auto_20200322_1758.py | 0
.../migrations/0007_vmhost_vmcluster.py | 0
.../migrations/0008_auto_20200403_1727.py | 0
.../migrations/0009_auto_20200417_0551.py | 0
.../migrations/0009_merge_20200413_0857.py | 0
.../migrations/0010_auto_20200413_0924.py | 0
.../migrations/0011_merge_20200418_0641.py | 0
.../migrations/0012_auto_20200418_0641.py | 0
.../0013_remove_vmproduct_primary_disk.py | 0
.../tests => uncloud_vm/migrations}/__init__.py | 0
.../uncloud/uncloud_vm => uncloud_vm}/models.py | 0
.../uncloud_vm => uncloud_vm}/serializers.py | 0
.../uncloud/uncloud_vm => uncloud_vm}/tests.py | 0
.../uncloud/uncloud_vm => uncloud_vm}/views.py | 0
265 files changed, 0 insertions(+), 0 deletions(-)
rename issues.org => archive/issues.org (100%)
rename {uncloud_django_based => archive/uncloud_django_based}/hacks/abk-hacks.py (100%)
rename {uncloud_django_based => archive/uncloud_django_based}/hacks/abkhack/opennebula_hacks.py (100%)
rename {uncloud_django_based => archive/uncloud_django_based}/hacks/command-wrapper.sh (100%)
rename {uncloud_django_based => archive/uncloud_django_based}/meow-payv1/README.md (100%)
rename {uncloud_django_based => archive/uncloud_django_based}/meow-payv1/config.py (100%)
rename {uncloud_django_based => archive/uncloud_django_based}/meow-payv1/hack-a-vpn.py (100%)
rename {uncloud_django_based => archive/uncloud_django_based}/meow-payv1/helper.py (100%)
rename {uncloud_django_based => archive/uncloud_django_based}/meow-payv1/products/ipv6-only-django.json (100%)
rename {uncloud_django_based => archive/uncloud_django_based}/meow-payv1/products/ipv6-only-vm.json (100%)
rename {uncloud_django_based => archive/uncloud_django_based}/meow-payv1/products/ipv6-only-vpn.json (100%)
rename {uncloud_django_based => archive/uncloud_django_based}/meow-payv1/products/ipv6box.json (100%)
rename {uncloud_django_based => archive/uncloud_django_based}/meow-payv1/products/membership.json (100%)
rename {uncloud_django_based => archive/uncloud_django_based}/meow-payv1/requirements.txt (100%)
rename {uncloud_django_based => archive/uncloud_django_based}/meow-payv1/sample-pay.conf (100%)
rename {uncloud_django_based => archive/uncloud_django_based}/meow-payv1/schemas.py (100%)
rename {uncloud_django_based => archive/uncloud_django_based}/meow-payv1/stripe_hack.py (100%)
rename {uncloud_django_based => archive/uncloud_django_based}/meow-payv1/stripe_utils.py (100%)
rename {uncloud_django_based => archive/uncloud_django_based}/meow-payv1/ucloud_pay.py (100%)
rename {uncloud_django_based => archive/uncloud_django_based}/notes-abk.md (100%)
rename {uncloud_django_based => archive/uncloud_django_based}/notes-nico.org (100%)
rename {uncloud_django_based => archive/uncloud_django_based}/plan.org (100%)
rename {uncloud_django_based => archive/uncloud_django_based}/uncloud/.gitignore (100%)
rename {uncloud_django_based => archive/uncloud_django_based}/vat_rates.csv (100%)
rename {uncloud_etcd_based => archive/uncloud_etcd_based}/bin/gen-version (100%)
rename {uncloud_etcd_based => archive/uncloud_etcd_based}/bin/uncloud (100%)
rename {uncloud_etcd_based => archive/uncloud_etcd_based}/bin/uncloud-run-reinstall (100%)
rename {uncloud_etcd_based => archive/uncloud_etcd_based}/conf/uncloud.conf (100%)
rename {uncloud_etcd_based => archive/uncloud_etcd_based}/docs/Makefile (100%)
rename {uncloud_etcd_based => archive/uncloud_etcd_based}/docs/README.md (100%)
rename {uncloud_django_based/uncloud/opennebula => archive/uncloud_etcd_based/docs}/__init__.py (100%)
rename {uncloud_django_based/uncloud/opennebula/migrations => archive/uncloud_etcd_based/docs/source}/__init__.py (100%)
rename {uncloud_etcd_based => archive/uncloud_etcd_based}/docs/source/admin-guide.rst (100%)
rename {uncloud_etcd_based => archive/uncloud_etcd_based}/docs/source/conf.py (100%)
rename {uncloud_etcd_based => archive/uncloud_etcd_based}/docs/source/diagram-code/ucloud (100%)
rename {uncloud_etcd_based => archive/uncloud_etcd_based}/docs/source/hacking.rst (100%)
rename {uncloud_etcd_based => archive/uncloud_etcd_based}/docs/source/images/ucloud.svg (100%)
rename {uncloud_etcd_based => archive/uncloud_etcd_based}/docs/source/index.rst (100%)
rename {uncloud_etcd_based => archive/uncloud_etcd_based}/docs/source/introduction.rst (100%)
rename {uncloud_etcd_based => archive/uncloud_etcd_based}/docs/source/misc/todo.rst (100%)
rename {uncloud_etcd_based => archive/uncloud_etcd_based}/docs/source/setup-install.rst (100%)
rename {uncloud_etcd_based => archive/uncloud_etcd_based}/docs/source/theory/summary.rst (100%)
rename {uncloud_etcd_based => archive/uncloud_etcd_based}/docs/source/troubleshooting.rst (100%)
rename {uncloud_etcd_based => archive/uncloud_etcd_based}/docs/source/user-guide.rst (100%)
rename {uncloud_etcd_based => archive/uncloud_etcd_based}/docs/source/user-guide/how-to-create-an-os-image-for-ucloud.rst (100%)
rename {uncloud_etcd_based => archive/uncloud_etcd_based}/docs/source/vm-images.rst (100%)
rename {uncloud_etcd_based => archive/uncloud_etcd_based}/scripts/uncloud (100%)
rename {uncloud_etcd_based => archive/uncloud_etcd_based}/setup.py (100%)
rename {uncloud_django_based/uncloud/uncloud_auth => archive/uncloud_etcd_based/test}/__init__.py (100%)
rename {uncloud_etcd_based => archive/uncloud_etcd_based}/test/test_mac_local.py (100%)
rename {uncloud_etcd_based => archive/uncloud_etcd_based}/uncloud/__init__.py (100%)
rename {uncloud_etcd_based => archive/uncloud_etcd_based}/uncloud/api/README.md (100%)
rename {uncloud_etcd_based => archive/uncloud_etcd_based}/uncloud/api/__init__.py (100%)
rename {uncloud_etcd_based => archive/uncloud_etcd_based}/uncloud/api/common_fields.py (100%)
rename {uncloud_etcd_based => archive/uncloud_etcd_based}/uncloud/api/create_image_store.py (100%)
rename {uncloud_etcd_based => archive/uncloud_etcd_based}/uncloud/api/helper.py (100%)
rename {uncloud_etcd_based => archive/uncloud_etcd_based}/uncloud/api/main.py (100%)
rename {uncloud_etcd_based => archive/uncloud_etcd_based}/uncloud/api/schemas.py (100%)
rename {uncloud_django_based/uncloud/uncloud_auth/migrations => archive/uncloud_etcd_based/uncloud/cli}/__init__.py (100%)
rename {uncloud_etcd_based => archive/uncloud_etcd_based}/uncloud/cli/helper.py (100%)
rename {uncloud_etcd_based => archive/uncloud_etcd_based}/uncloud/cli/host.py (100%)
rename {uncloud_etcd_based => archive/uncloud_etcd_based}/uncloud/cli/image.py (100%)
rename {uncloud_etcd_based => archive/uncloud_etcd_based}/uncloud/cli/main.py (100%)
rename {uncloud_etcd_based => archive/uncloud_etcd_based}/uncloud/cli/network.py (100%)
rename {uncloud_etcd_based => archive/uncloud_etcd_based}/uncloud/cli/user.py (100%)
rename {uncloud_etcd_based => archive/uncloud_etcd_based}/uncloud/cli/vm.py (100%)
rename {uncloud_django_based/uncloud/uncloud_net => archive/uncloud_etcd_based/uncloud/client}/__init__.py (100%)
rename {uncloud_etcd_based => archive/uncloud_etcd_based}/uncloud/client/main.py (100%)
rename {uncloud_etcd_based => archive/uncloud_etcd_based}/uncloud/common/__init__.py (100%)
rename {uncloud_etcd_based => archive/uncloud_etcd_based}/uncloud/common/classes.py (100%)
rename {uncloud_etcd_based => archive/uncloud_etcd_based}/uncloud/common/cli.py (100%)
rename {uncloud_etcd_based => archive/uncloud_etcd_based}/uncloud/common/counters.py (100%)
rename {uncloud_etcd_based => archive/uncloud_etcd_based}/uncloud/common/etcd_wrapper.py (100%)
rename {uncloud_etcd_based => archive/uncloud_etcd_based}/uncloud/common/host.py (100%)
rename {uncloud_etcd_based => archive/uncloud_etcd_based}/uncloud/common/network.py (100%)
rename {uncloud_etcd_based => archive/uncloud_etcd_based}/uncloud/common/parser.py (100%)
rename {uncloud_etcd_based => archive/uncloud_etcd_based}/uncloud/common/request.py (100%)
rename {uncloud_etcd_based => archive/uncloud_etcd_based}/uncloud/common/schemas.py (100%)
rename {uncloud_etcd_based => archive/uncloud_etcd_based}/uncloud/common/settings.py (100%)
rename {uncloud_etcd_based => archive/uncloud_etcd_based}/uncloud/common/shared.py (100%)
rename {uncloud_etcd_based => archive/uncloud_etcd_based}/uncloud/common/storage_handlers.py (100%)
rename {uncloud_etcd_based => archive/uncloud_etcd_based}/uncloud/common/vm.py (100%)
rename {uncloud_django_based/uncloud/uncloud_net/migrations => archive/uncloud_etcd_based/uncloud/configure}/__init__.py (100%)
rename {uncloud_etcd_based => archive/uncloud_etcd_based}/uncloud/configure/main.py (100%)
rename {uncloud_etcd_based => archive/uncloud_etcd_based}/uncloud/filescanner/__init__.py (100%)
rename {uncloud_etcd_based => archive/uncloud_etcd_based}/uncloud/filescanner/main.py (100%)
rename {uncloud_etcd_based => archive/uncloud_etcd_based}/uncloud/hack/README.org (100%)
rename {uncloud_etcd_based => archive/uncloud_etcd_based}/uncloud/hack/__init__.py (100%)
rename {uncloud_etcd_based => archive/uncloud_etcd_based}/uncloud/hack/conf.d/ucloud-host (100%)
rename {uncloud_etcd_based => archive/uncloud_etcd_based}/uncloud/hack/config.py (100%)
rename {uncloud_etcd_based => archive/uncloud_etcd_based}/uncloud/hack/db.py (100%)
rename {uncloud_etcd_based => archive/uncloud_etcd_based}/uncloud/hack/hackcloud/.gitignore (100%)
rename {uncloud_etcd_based => archive/uncloud_etcd_based}/uncloud/hack/hackcloud/__init__.py (100%)
rename {uncloud_etcd_based => archive/uncloud_etcd_based}/uncloud/hack/hackcloud/etcd-client.sh (100%)
rename {uncloud_etcd_based => archive/uncloud_etcd_based}/uncloud/hack/hackcloud/ifdown.sh (100%)
rename {uncloud_etcd_based => archive/uncloud_etcd_based}/uncloud/hack/hackcloud/ifup.sh (100%)
rename {uncloud_etcd_based => archive/uncloud_etcd_based}/uncloud/hack/hackcloud/mac-last (100%)
rename {uncloud_etcd_based => archive/uncloud_etcd_based}/uncloud/hack/hackcloud/mac-prefix (100%)
rename {uncloud_etcd_based => archive/uncloud_etcd_based}/uncloud/hack/hackcloud/net.sh (100%)
rename {uncloud_etcd_based => archive/uncloud_etcd_based}/uncloud/hack/hackcloud/nftrules (100%)
rename {uncloud_etcd_based => archive/uncloud_etcd_based}/uncloud/hack/hackcloud/radvd.conf (100%)
rename {uncloud_etcd_based => archive/uncloud_etcd_based}/uncloud/hack/hackcloud/radvd.sh (100%)
rename {uncloud_etcd_based => archive/uncloud_etcd_based}/uncloud/hack/hackcloud/vm.sh (100%)
rename {uncloud_etcd_based => archive/uncloud_etcd_based}/uncloud/hack/host.py (100%)
rename {uncloud_etcd_based => archive/uncloud_etcd_based}/uncloud/hack/mac.py (100%)
rename {uncloud_etcd_based => archive/uncloud_etcd_based}/uncloud/hack/main.py (100%)
rename {uncloud_etcd_based => archive/uncloud_etcd_based}/uncloud/hack/net.py (100%)
rename {uncloud_etcd_based => archive/uncloud_etcd_based}/uncloud/hack/nftables.conf (100%)
rename {uncloud_etcd_based => archive/uncloud_etcd_based}/uncloud/hack/product.py (100%)
rename {uncloud_etcd_based => archive/uncloud_etcd_based}/uncloud/hack/rc-scripts/ucloud-api (100%)
rename {uncloud_etcd_based => archive/uncloud_etcd_based}/uncloud/hack/rc-scripts/ucloud-host (100%)
rename {uncloud_etcd_based => archive/uncloud_etcd_based}/uncloud/hack/rc-scripts/ucloud-metadata (100%)
rename {uncloud_etcd_based => archive/uncloud_etcd_based}/uncloud/hack/rc-scripts/ucloud-scheduler (100%)
rename {uncloud_etcd_based => archive/uncloud_etcd_based}/uncloud/hack/uncloud-hack-init-host (100%)
rename {uncloud_etcd_based => archive/uncloud_etcd_based}/uncloud/hack/uncloud-run-vm (100%)
rename {uncloud_etcd_based => archive/uncloud_etcd_based}/uncloud/hack/vm.py (100%)
rename {uncloud_etcd_based => archive/uncloud_etcd_based}/uncloud/host/__init__.py (100%)
rename {uncloud_etcd_based => archive/uncloud_etcd_based}/uncloud/host/main.py (100%)
rename {uncloud_etcd_based => archive/uncloud_etcd_based}/uncloud/host/virtualmachine.py (100%)
rename {uncloud_etcd_based => archive/uncloud_etcd_based}/uncloud/imagescanner/__init__.py (100%)
rename {uncloud_etcd_based => archive/uncloud_etcd_based}/uncloud/imagescanner/main.py (100%)
rename {uncloud_etcd_based => archive/uncloud_etcd_based}/uncloud/metadata/__init__.py (100%)
rename {uncloud_etcd_based => archive/uncloud_etcd_based}/uncloud/metadata/main.py (100%)
rename {uncloud_etcd_based => archive/uncloud_etcd_based}/uncloud/network/README (100%)
rename {uncloud_django_based/uncloud/uncloud_pay => archive/uncloud_etcd_based/uncloud/network}/__init__.py (100%)
rename {uncloud_etcd_based => archive/uncloud_etcd_based}/uncloud/network/create-bridge.sh (100%)
rename {uncloud_etcd_based => archive/uncloud_etcd_based}/uncloud/network/create-tap.sh (100%)
rename {uncloud_etcd_based => archive/uncloud_etcd_based}/uncloud/network/create-vxlan.sh (100%)
rename {uncloud_etcd_based => archive/uncloud_etcd_based}/uncloud/network/radvd-template.conf (100%)
rename {uncloud_etcd_based => archive/uncloud_etcd_based}/uncloud/oneshot/__init__.py (100%)
rename {uncloud_etcd_based => archive/uncloud_etcd_based}/uncloud/oneshot/main.py (100%)
rename {uncloud_etcd_based => archive/uncloud_etcd_based}/uncloud/oneshot/virtualmachine.py (100%)
rename {uncloud_etcd_based => archive/uncloud_etcd_based}/uncloud/scheduler/__init__.py (100%)
rename {uncloud_etcd_based => archive/uncloud_etcd_based}/uncloud/scheduler/helper.py (100%)
rename {uncloud_etcd_based => archive/uncloud_etcd_based}/uncloud/scheduler/main.py (100%)
rename {uncloud_django_based/uncloud/uncloud_pay/migrations => archive/uncloud_etcd_based/uncloud/scheduler/tests}/__init__.py (100%)
rename {uncloud_etcd_based => archive/uncloud_etcd_based}/uncloud/scheduler/tests/test_basics.py (100%)
rename {uncloud_etcd_based => archive/uncloud_etcd_based}/uncloud/scheduler/tests/test_dead_host_mechanism.py (100%)
rename {uncloud_etcd_based => archive/uncloud_etcd_based}/uncloud/version.py (100%)
rename {uncloud_etcd_based => archive/uncloud_etcd_based}/uncloud/vmm/__init__.py (100%)
rename {uncloud_django_based/uncloud/doc => doc}/README-how-to-configure-remote-uncloud-clients.org (100%)
rename {uncloud_django_based/uncloud/doc => doc}/README-identifiers.org (100%)
rename {uncloud_django_based/uncloud/doc => doc}/README-object-relations.md (100%)
rename {uncloud_django_based/uncloud/doc => doc}/README-postgresql.org (100%)
rename {uncloud_django_based/uncloud/doc => doc}/README-products.md (100%)
rename {uncloud_django_based/uncloud/doc => doc}/README-vpn.org (100%)
rename {uncloud_django_based/uncloud/doc => doc}/README.md (100%)
rename uncloud_django_based/uncloud/manage.py => manage.py (100%)
rename uncloud_django_based/uncloud/models.dot => models.dot (100%)
rename uncloud_django_based/uncloud/models.png => models.png (100%)
rename {uncloud_django_based/uncloud/uncloud_service => opennebula}/__init__.py (100%)
rename {uncloud_django_based/uncloud/opennebula => opennebula}/admin.py (100%)
rename {uncloud_django_based/uncloud/opennebula => opennebula}/apps.py (100%)
rename {uncloud_django_based/uncloud/opennebula => opennebula}/management/commands/opennebula-synchosts.py (100%)
rename {uncloud_django_based/uncloud/opennebula => opennebula}/management/commands/opennebula-syncvms.py (100%)
rename {uncloud_django_based/uncloud/opennebula => opennebula}/management/commands/opennebula-to-uncloud.py (100%)
rename {uncloud_django_based/uncloud/opennebula => opennebula}/migrations/0001_initial.py (100%)
rename {uncloud_django_based/uncloud/opennebula => opennebula}/migrations/0002_auto_20200225_1335.py (100%)
rename {uncloud_django_based/uncloud/opennebula => opennebula}/migrations/0003_auto_20200225_1428.py (100%)
rename {uncloud_django_based/uncloud/opennebula => opennebula}/migrations/0004_auto_20200225_1816.py (100%)
rename {uncloud_django_based/uncloud/uncloud_service => opennebula}/migrations/__init__.py (100%)
rename {uncloud_django_based/uncloud/opennebula => opennebula}/models.py (100%)
rename {uncloud_django_based/uncloud/opennebula => opennebula}/serializers.py (100%)
rename {uncloud_django_based/uncloud/opennebula => opennebula}/tests.py (100%)
rename {uncloud_django_based/uncloud/opennebula => opennebula}/views.py (100%)
rename uncloud_django_based/uncloud/requirements.txt => requirements.txt (100%)
rename {uncloud_django_based/uncloud/uncloud => uncloud}/.gitignore (100%)
rename {uncloud_django_based/uncloud/uncloud => uncloud}/__init__.py (100%)
rename {uncloud_django_based/uncloud/uncloud => uncloud}/asgi.py (100%)
rename {uncloud_django_based/uncloud/uncloud => uncloud}/management/commands/uncloud.py (100%)
rename {uncloud_django_based/uncloud/uncloud => uncloud}/models.py (100%)
rename {uncloud_django_based/uncloud/uncloud => uncloud}/settings.py (100%)
rename {uncloud_django_based/uncloud/uncloud => uncloud}/urls.py (100%)
rename {uncloud_django_based/uncloud/uncloud => uncloud}/wsgi.py (100%)
rename {uncloud_django_based/uncloud/uncloud_storage => uncloud_auth}/__init__.py (100%)
rename {uncloud_django_based/uncloud/uncloud_auth => uncloud_auth}/admin.py (100%)
rename {uncloud_django_based/uncloud/uncloud_auth => uncloud_auth}/apps.py (100%)
rename {uncloud_django_based/uncloud/uncloud_auth => uncloud_auth}/migrations/0001_initial.py (100%)
rename {uncloud_django_based/uncloud/uncloud_auth => uncloud_auth}/migrations/0002_auto_20200318_1343.py (100%)
rename {uncloud_django_based/uncloud/uncloud_auth => uncloud_auth}/migrations/0003_auto_20200318_1345.py (100%)
rename {uncloud_django_based/uncloud/uncloud_vm => uncloud_auth/migrations}/__init__.py (100%)
rename {uncloud_django_based/uncloud/uncloud_auth => uncloud_auth}/models.py (100%)
rename {uncloud_django_based/uncloud/uncloud_auth => uncloud_auth}/serializers.py (100%)
rename {uncloud_django_based/uncloud/uncloud_auth => uncloud_auth}/views.py (100%)
rename {uncloud_django_based/uncloud/uncloud_vm/migrations => uncloud_net}/__init__.py (100%)
rename {uncloud_django_based/uncloud/uncloud_net => uncloud_net}/admin.py (100%)
rename {uncloud_django_based/uncloud/uncloud_net => uncloud_net}/apps.py (100%)
rename {uncloud_django_based/uncloud/uncloud_net => uncloud_net}/management/commands/vpn.py (100%)
rename {uncloud_django_based/uncloud/uncloud_net => uncloud_net}/migrations/0001_initial.py (100%)
rename {uncloud_django_based/uncloud/uncloud_net => uncloud_net}/migrations/0002_auto_20200409_1225.py (100%)
rename {uncloud_django_based/uncloud/uncloud_net => uncloud_net}/migrations/0003_auto_20200417_0551.py (100%)
rename {uncloud_etcd_based/docs => uncloud_net/migrations}/__init__.py (100%)
rename {uncloud_django_based/uncloud/uncloud_net => uncloud_net}/models.py (100%)
rename {uncloud_django_based/uncloud/uncloud_net => uncloud_net}/serializers.py (100%)
rename {uncloud_django_based/uncloud/uncloud_net => uncloud_net}/tests.py (100%)
rename {uncloud_django_based/uncloud/uncloud_net => uncloud_net}/views.py (100%)
rename {uncloud_etcd_based/docs/source => uncloud_pay}/__init__.py (100%)
rename {uncloud_django_based/uncloud/uncloud_pay => uncloud_pay}/admin.py (100%)
rename {uncloud_django_based/uncloud/uncloud_pay => uncloud_pay}/apps.py (100%)
rename {uncloud_django_based/uncloud/uncloud_pay => uncloud_pay}/helpers.py (100%)
rename {uncloud_django_based/uncloud/uncloud_pay => uncloud_pay}/management/commands/charge-negative-balance.py (100%)
rename {uncloud_django_based/uncloud/uncloud_pay => uncloud_pay}/management/commands/generate-bills.py (100%)
rename {uncloud_django_based/uncloud/uncloud_pay => uncloud_pay}/management/commands/handle-overdue-bills.py (100%)
rename {uncloud_django_based/uncloud/uncloud_pay => uncloud_pay}/management/commands/import-vat-rates.py (100%)
rename {uncloud_django_based/uncloud/uncloud_pay => uncloud_pay}/migrations/0001_initial.py (100%)
rename {uncloud_django_based/uncloud/uncloud_pay => uncloud_pay}/migrations/0002_auto_20200305_1524.py (100%)
rename {uncloud_django_based/uncloud/uncloud_pay => uncloud_pay}/migrations/0003_auto_20200305_1354.py (100%)
rename {uncloud_django_based/uncloud/uncloud_pay => uncloud_pay}/migrations/0004_auto_20200409_1225.py (100%)
rename {uncloud_django_based/uncloud/uncloud_pay => uncloud_pay}/migrations/0005_auto_20200413_0924.py (100%)
rename {uncloud_django_based/uncloud/uncloud_pay => uncloud_pay}/migrations/0006_auto_20200415_1003.py (100%)
rename {uncloud_django_based/uncloud/uncloud_pay => uncloud_pay}/migrations/0006_billingaddress.py (100%)
rename {uncloud_django_based/uncloud/uncloud_pay => uncloud_pay}/migrations/0007_auto_20200418_0737.py (100%)
rename {uncloud_django_based/uncloud/uncloud_pay => uncloud_pay}/migrations/0008_auto_20200502_1921.py (100%)
rename {uncloud_django_based/uncloud/uncloud_pay => uncloud_pay}/migrations/0009_auto_20200502_2047.py (100%)
rename {uncloud_django_based/uncloud/uncloud_pay => uncloud_pay}/migrations/0010_order_description.py (100%)
rename {uncloud_etcd_based/test => uncloud_pay/migrations}/__init__.py (100%)
rename {uncloud_django_based/uncloud/uncloud_pay => uncloud_pay}/models.py (100%)
rename {uncloud_django_based/uncloud/uncloud_pay => uncloud_pay}/serializers.py (100%)
rename {uncloud_django_based/uncloud/uncloud_pay => uncloud_pay}/stripe.py (100%)
rename {uncloud_django_based/uncloud/uncloud_pay => uncloud_pay}/templates/bill.html (100%)
rename {uncloud_django_based/uncloud/uncloud_pay => uncloud_pay}/templates/error.html.j2 (100%)
rename {uncloud_django_based/uncloud/uncloud_pay => uncloud_pay}/templates/stripe-payment.html.j2 (100%)
rename {uncloud_django_based/uncloud/uncloud_pay => uncloud_pay}/tests.py (100%)
rename {uncloud_django_based/uncloud/uncloud_pay => uncloud_pay}/views.py (100%)
rename {uncloud_etcd_based/uncloud/cli => uncloud_service}/__init__.py (100%)
rename {uncloud_django_based/uncloud/uncloud_service => uncloud_service}/admin.py (100%)
rename {uncloud_django_based/uncloud/uncloud_service => uncloud_service}/apps.py (100%)
rename {uncloud_django_based/uncloud/uncloud_service => uncloud_service}/migrations/0001_initial.py (100%)
rename {uncloud_django_based/uncloud/uncloud_service => uncloud_service}/migrations/0002_auto_20200418_0641.py (100%)
rename {uncloud_etcd_based/uncloud/client => uncloud_service/migrations}/__init__.py (100%)
rename {uncloud_django_based/uncloud/uncloud_service => uncloud_service}/models.py (100%)
rename {uncloud_django_based/uncloud/uncloud_service => uncloud_service}/serializers.py (100%)
rename {uncloud_django_based/uncloud/uncloud_service => uncloud_service}/tests.py (100%)
rename {uncloud_django_based/uncloud/uncloud_service => uncloud_service}/views.py (100%)
rename {uncloud_etcd_based/uncloud/configure => uncloud_storage}/__init__.py (100%)
rename {uncloud_django_based/uncloud/uncloud_storage => uncloud_storage}/admin.py (100%)
rename {uncloud_django_based/uncloud/uncloud_storage => uncloud_storage}/apps.py (100%)
rename {uncloud_django_based/uncloud/uncloud_storage => uncloud_storage}/models.py (100%)
rename {uncloud_django_based/uncloud/uncloud_storage => uncloud_storage}/tests.py (100%)
rename {uncloud_django_based/uncloud/uncloud_storage => uncloud_storage}/views.py (100%)
rename {uncloud_etcd_based/uncloud/network => uncloud_vm}/__init__.py (100%)
rename {uncloud_django_based/uncloud/uncloud_vm => uncloud_vm}/admin.py (100%)
rename {uncloud_django_based/uncloud/uncloud_vm => uncloud_vm}/apps.py (100%)
rename {uncloud_django_based/uncloud/uncloud_vm => uncloud_vm}/management/commands/vm.py (100%)
rename {uncloud_django_based/uncloud/uncloud_vm => uncloud_vm}/migrations/0001_initial.py (100%)
rename {uncloud_django_based/uncloud/uncloud_vm => uncloud_vm}/migrations/0002_auto_20200305_1321.py (100%)
rename {uncloud_django_based/uncloud/uncloud_vm => uncloud_vm}/migrations/0003_remove_vmhost_vms.py (100%)
rename {uncloud_django_based/uncloud/uncloud_vm => uncloud_vm}/migrations/0004_remove_vmproduct_vmid.py (100%)
rename {uncloud_django_based/uncloud/uncloud_vm => uncloud_vm}/migrations/0004_vmproduct_primary_disk.py (100%)
rename {uncloud_django_based/uncloud/uncloud_vm => uncloud_vm}/migrations/0005_auto_20200309_1258.py (100%)
rename {uncloud_django_based/uncloud/uncloud_vm => uncloud_vm}/migrations/0005_auto_20200321_1058.py (100%)
rename {uncloud_django_based/uncloud/uncloud_vm => uncloud_vm}/migrations/0006_auto_20200322_1758.py (100%)
rename {uncloud_django_based/uncloud/uncloud_vm => uncloud_vm}/migrations/0007_vmhost_vmcluster.py (100%)
rename {uncloud_django_based/uncloud/uncloud_vm => uncloud_vm}/migrations/0008_auto_20200403_1727.py (100%)
rename {uncloud_django_based/uncloud/uncloud_vm => uncloud_vm}/migrations/0009_auto_20200417_0551.py (100%)
rename {uncloud_django_based/uncloud/uncloud_vm => uncloud_vm}/migrations/0009_merge_20200413_0857.py (100%)
rename {uncloud_django_based/uncloud/uncloud_vm => uncloud_vm}/migrations/0010_auto_20200413_0924.py (100%)
rename {uncloud_django_based/uncloud/uncloud_vm => uncloud_vm}/migrations/0011_merge_20200418_0641.py (100%)
rename {uncloud_django_based/uncloud/uncloud_vm => uncloud_vm}/migrations/0012_auto_20200418_0641.py (100%)
rename {uncloud_django_based/uncloud/uncloud_vm => uncloud_vm}/migrations/0013_remove_vmproduct_primary_disk.py (100%)
rename {uncloud_etcd_based/uncloud/scheduler/tests => uncloud_vm/migrations}/__init__.py (100%)
rename {uncloud_django_based/uncloud/uncloud_vm => uncloud_vm}/models.py (100%)
rename {uncloud_django_based/uncloud/uncloud_vm => uncloud_vm}/serializers.py (100%)
rename {uncloud_django_based/uncloud/uncloud_vm => uncloud_vm}/tests.py (100%)
rename {uncloud_django_based/uncloud/uncloud_vm => uncloud_vm}/views.py (100%)
diff --git a/issues.org b/archive/issues.org
similarity index 100%
rename from issues.org
rename to archive/issues.org
diff --git a/uncloud_django_based/hacks/abk-hacks.py b/archive/uncloud_django_based/hacks/abk-hacks.py
similarity index 100%
rename from uncloud_django_based/hacks/abk-hacks.py
rename to archive/uncloud_django_based/hacks/abk-hacks.py
diff --git a/uncloud_django_based/hacks/abkhack/opennebula_hacks.py b/archive/uncloud_django_based/hacks/abkhack/opennebula_hacks.py
similarity index 100%
rename from uncloud_django_based/hacks/abkhack/opennebula_hacks.py
rename to archive/uncloud_django_based/hacks/abkhack/opennebula_hacks.py
diff --git a/uncloud_django_based/hacks/command-wrapper.sh b/archive/uncloud_django_based/hacks/command-wrapper.sh
similarity index 100%
rename from uncloud_django_based/hacks/command-wrapper.sh
rename to archive/uncloud_django_based/hacks/command-wrapper.sh
diff --git a/uncloud_django_based/meow-payv1/README.md b/archive/uncloud_django_based/meow-payv1/README.md
similarity index 100%
rename from uncloud_django_based/meow-payv1/README.md
rename to archive/uncloud_django_based/meow-payv1/README.md
diff --git a/uncloud_django_based/meow-payv1/config.py b/archive/uncloud_django_based/meow-payv1/config.py
similarity index 100%
rename from uncloud_django_based/meow-payv1/config.py
rename to archive/uncloud_django_based/meow-payv1/config.py
diff --git a/uncloud_django_based/meow-payv1/hack-a-vpn.py b/archive/uncloud_django_based/meow-payv1/hack-a-vpn.py
similarity index 100%
rename from uncloud_django_based/meow-payv1/hack-a-vpn.py
rename to archive/uncloud_django_based/meow-payv1/hack-a-vpn.py
diff --git a/uncloud_django_based/meow-payv1/helper.py b/archive/uncloud_django_based/meow-payv1/helper.py
similarity index 100%
rename from uncloud_django_based/meow-payv1/helper.py
rename to archive/uncloud_django_based/meow-payv1/helper.py
diff --git a/uncloud_django_based/meow-payv1/products/ipv6-only-django.json b/archive/uncloud_django_based/meow-payv1/products/ipv6-only-django.json
similarity index 100%
rename from uncloud_django_based/meow-payv1/products/ipv6-only-django.json
rename to archive/uncloud_django_based/meow-payv1/products/ipv6-only-django.json
diff --git a/uncloud_django_based/meow-payv1/products/ipv6-only-vm.json b/archive/uncloud_django_based/meow-payv1/products/ipv6-only-vm.json
similarity index 100%
rename from uncloud_django_based/meow-payv1/products/ipv6-only-vm.json
rename to archive/uncloud_django_based/meow-payv1/products/ipv6-only-vm.json
diff --git a/uncloud_django_based/meow-payv1/products/ipv6-only-vpn.json b/archive/uncloud_django_based/meow-payv1/products/ipv6-only-vpn.json
similarity index 100%
rename from uncloud_django_based/meow-payv1/products/ipv6-only-vpn.json
rename to archive/uncloud_django_based/meow-payv1/products/ipv6-only-vpn.json
diff --git a/uncloud_django_based/meow-payv1/products/ipv6box.json b/archive/uncloud_django_based/meow-payv1/products/ipv6box.json
similarity index 100%
rename from uncloud_django_based/meow-payv1/products/ipv6box.json
rename to archive/uncloud_django_based/meow-payv1/products/ipv6box.json
diff --git a/uncloud_django_based/meow-payv1/products/membership.json b/archive/uncloud_django_based/meow-payv1/products/membership.json
similarity index 100%
rename from uncloud_django_based/meow-payv1/products/membership.json
rename to archive/uncloud_django_based/meow-payv1/products/membership.json
diff --git a/uncloud_django_based/meow-payv1/requirements.txt b/archive/uncloud_django_based/meow-payv1/requirements.txt
similarity index 100%
rename from uncloud_django_based/meow-payv1/requirements.txt
rename to archive/uncloud_django_based/meow-payv1/requirements.txt
diff --git a/uncloud_django_based/meow-payv1/sample-pay.conf b/archive/uncloud_django_based/meow-payv1/sample-pay.conf
similarity index 100%
rename from uncloud_django_based/meow-payv1/sample-pay.conf
rename to archive/uncloud_django_based/meow-payv1/sample-pay.conf
diff --git a/uncloud_django_based/meow-payv1/schemas.py b/archive/uncloud_django_based/meow-payv1/schemas.py
similarity index 100%
rename from uncloud_django_based/meow-payv1/schemas.py
rename to archive/uncloud_django_based/meow-payv1/schemas.py
diff --git a/uncloud_django_based/meow-payv1/stripe_hack.py b/archive/uncloud_django_based/meow-payv1/stripe_hack.py
similarity index 100%
rename from uncloud_django_based/meow-payv1/stripe_hack.py
rename to archive/uncloud_django_based/meow-payv1/stripe_hack.py
diff --git a/uncloud_django_based/meow-payv1/stripe_utils.py b/archive/uncloud_django_based/meow-payv1/stripe_utils.py
similarity index 100%
rename from uncloud_django_based/meow-payv1/stripe_utils.py
rename to archive/uncloud_django_based/meow-payv1/stripe_utils.py
diff --git a/uncloud_django_based/meow-payv1/ucloud_pay.py b/archive/uncloud_django_based/meow-payv1/ucloud_pay.py
similarity index 100%
rename from uncloud_django_based/meow-payv1/ucloud_pay.py
rename to archive/uncloud_django_based/meow-payv1/ucloud_pay.py
diff --git a/uncloud_django_based/notes-abk.md b/archive/uncloud_django_based/notes-abk.md
similarity index 100%
rename from uncloud_django_based/notes-abk.md
rename to archive/uncloud_django_based/notes-abk.md
diff --git a/uncloud_django_based/notes-nico.org b/archive/uncloud_django_based/notes-nico.org
similarity index 100%
rename from uncloud_django_based/notes-nico.org
rename to archive/uncloud_django_based/notes-nico.org
diff --git a/uncloud_django_based/plan.org b/archive/uncloud_django_based/plan.org
similarity index 100%
rename from uncloud_django_based/plan.org
rename to archive/uncloud_django_based/plan.org
diff --git a/uncloud_django_based/uncloud/.gitignore b/archive/uncloud_django_based/uncloud/.gitignore
similarity index 100%
rename from uncloud_django_based/uncloud/.gitignore
rename to archive/uncloud_django_based/uncloud/.gitignore
diff --git a/uncloud_django_based/vat_rates.csv b/archive/uncloud_django_based/vat_rates.csv
similarity index 100%
rename from uncloud_django_based/vat_rates.csv
rename to archive/uncloud_django_based/vat_rates.csv
diff --git a/uncloud_etcd_based/bin/gen-version b/archive/uncloud_etcd_based/bin/gen-version
similarity index 100%
rename from uncloud_etcd_based/bin/gen-version
rename to archive/uncloud_etcd_based/bin/gen-version
diff --git a/uncloud_etcd_based/bin/uncloud b/archive/uncloud_etcd_based/bin/uncloud
similarity index 100%
rename from uncloud_etcd_based/bin/uncloud
rename to archive/uncloud_etcd_based/bin/uncloud
diff --git a/uncloud_etcd_based/bin/uncloud-run-reinstall b/archive/uncloud_etcd_based/bin/uncloud-run-reinstall
similarity index 100%
rename from uncloud_etcd_based/bin/uncloud-run-reinstall
rename to archive/uncloud_etcd_based/bin/uncloud-run-reinstall
diff --git a/uncloud_etcd_based/conf/uncloud.conf b/archive/uncloud_etcd_based/conf/uncloud.conf
similarity index 100%
rename from uncloud_etcd_based/conf/uncloud.conf
rename to archive/uncloud_etcd_based/conf/uncloud.conf
diff --git a/uncloud_etcd_based/docs/Makefile b/archive/uncloud_etcd_based/docs/Makefile
similarity index 100%
rename from uncloud_etcd_based/docs/Makefile
rename to archive/uncloud_etcd_based/docs/Makefile
diff --git a/uncloud_etcd_based/docs/README.md b/archive/uncloud_etcd_based/docs/README.md
similarity index 100%
rename from uncloud_etcd_based/docs/README.md
rename to archive/uncloud_etcd_based/docs/README.md
diff --git a/uncloud_django_based/uncloud/opennebula/__init__.py b/archive/uncloud_etcd_based/docs/__init__.py
similarity index 100%
rename from uncloud_django_based/uncloud/opennebula/__init__.py
rename to archive/uncloud_etcd_based/docs/__init__.py
diff --git a/uncloud_django_based/uncloud/opennebula/migrations/__init__.py b/archive/uncloud_etcd_based/docs/source/__init__.py
similarity index 100%
rename from uncloud_django_based/uncloud/opennebula/migrations/__init__.py
rename to archive/uncloud_etcd_based/docs/source/__init__.py
diff --git a/uncloud_etcd_based/docs/source/admin-guide.rst b/archive/uncloud_etcd_based/docs/source/admin-guide.rst
similarity index 100%
rename from uncloud_etcd_based/docs/source/admin-guide.rst
rename to archive/uncloud_etcd_based/docs/source/admin-guide.rst
diff --git a/uncloud_etcd_based/docs/source/conf.py b/archive/uncloud_etcd_based/docs/source/conf.py
similarity index 100%
rename from uncloud_etcd_based/docs/source/conf.py
rename to archive/uncloud_etcd_based/docs/source/conf.py
diff --git a/uncloud_etcd_based/docs/source/diagram-code/ucloud b/archive/uncloud_etcd_based/docs/source/diagram-code/ucloud
similarity index 100%
rename from uncloud_etcd_based/docs/source/diagram-code/ucloud
rename to archive/uncloud_etcd_based/docs/source/diagram-code/ucloud
diff --git a/uncloud_etcd_based/docs/source/hacking.rst b/archive/uncloud_etcd_based/docs/source/hacking.rst
similarity index 100%
rename from uncloud_etcd_based/docs/source/hacking.rst
rename to archive/uncloud_etcd_based/docs/source/hacking.rst
diff --git a/uncloud_etcd_based/docs/source/images/ucloud.svg b/archive/uncloud_etcd_based/docs/source/images/ucloud.svg
similarity index 100%
rename from uncloud_etcd_based/docs/source/images/ucloud.svg
rename to archive/uncloud_etcd_based/docs/source/images/ucloud.svg
diff --git a/uncloud_etcd_based/docs/source/index.rst b/archive/uncloud_etcd_based/docs/source/index.rst
similarity index 100%
rename from uncloud_etcd_based/docs/source/index.rst
rename to archive/uncloud_etcd_based/docs/source/index.rst
diff --git a/uncloud_etcd_based/docs/source/introduction.rst b/archive/uncloud_etcd_based/docs/source/introduction.rst
similarity index 100%
rename from uncloud_etcd_based/docs/source/introduction.rst
rename to archive/uncloud_etcd_based/docs/source/introduction.rst
diff --git a/uncloud_etcd_based/docs/source/misc/todo.rst b/archive/uncloud_etcd_based/docs/source/misc/todo.rst
similarity index 100%
rename from uncloud_etcd_based/docs/source/misc/todo.rst
rename to archive/uncloud_etcd_based/docs/source/misc/todo.rst
diff --git a/uncloud_etcd_based/docs/source/setup-install.rst b/archive/uncloud_etcd_based/docs/source/setup-install.rst
similarity index 100%
rename from uncloud_etcd_based/docs/source/setup-install.rst
rename to archive/uncloud_etcd_based/docs/source/setup-install.rst
diff --git a/uncloud_etcd_based/docs/source/theory/summary.rst b/archive/uncloud_etcd_based/docs/source/theory/summary.rst
similarity index 100%
rename from uncloud_etcd_based/docs/source/theory/summary.rst
rename to archive/uncloud_etcd_based/docs/source/theory/summary.rst
diff --git a/uncloud_etcd_based/docs/source/troubleshooting.rst b/archive/uncloud_etcd_based/docs/source/troubleshooting.rst
similarity index 100%
rename from uncloud_etcd_based/docs/source/troubleshooting.rst
rename to archive/uncloud_etcd_based/docs/source/troubleshooting.rst
diff --git a/uncloud_etcd_based/docs/source/user-guide.rst b/archive/uncloud_etcd_based/docs/source/user-guide.rst
similarity index 100%
rename from uncloud_etcd_based/docs/source/user-guide.rst
rename to archive/uncloud_etcd_based/docs/source/user-guide.rst
diff --git a/uncloud_etcd_based/docs/source/user-guide/how-to-create-an-os-image-for-ucloud.rst b/archive/uncloud_etcd_based/docs/source/user-guide/how-to-create-an-os-image-for-ucloud.rst
similarity index 100%
rename from uncloud_etcd_based/docs/source/user-guide/how-to-create-an-os-image-for-ucloud.rst
rename to archive/uncloud_etcd_based/docs/source/user-guide/how-to-create-an-os-image-for-ucloud.rst
diff --git a/uncloud_etcd_based/docs/source/vm-images.rst b/archive/uncloud_etcd_based/docs/source/vm-images.rst
similarity index 100%
rename from uncloud_etcd_based/docs/source/vm-images.rst
rename to archive/uncloud_etcd_based/docs/source/vm-images.rst
diff --git a/uncloud_etcd_based/scripts/uncloud b/archive/uncloud_etcd_based/scripts/uncloud
similarity index 100%
rename from uncloud_etcd_based/scripts/uncloud
rename to archive/uncloud_etcd_based/scripts/uncloud
diff --git a/uncloud_etcd_based/setup.py b/archive/uncloud_etcd_based/setup.py
similarity index 100%
rename from uncloud_etcd_based/setup.py
rename to archive/uncloud_etcd_based/setup.py
diff --git a/uncloud_django_based/uncloud/uncloud_auth/__init__.py b/archive/uncloud_etcd_based/test/__init__.py
similarity index 100%
rename from uncloud_django_based/uncloud/uncloud_auth/__init__.py
rename to archive/uncloud_etcd_based/test/__init__.py
diff --git a/uncloud_etcd_based/test/test_mac_local.py b/archive/uncloud_etcd_based/test/test_mac_local.py
similarity index 100%
rename from uncloud_etcd_based/test/test_mac_local.py
rename to archive/uncloud_etcd_based/test/test_mac_local.py
diff --git a/uncloud_etcd_based/uncloud/__init__.py b/archive/uncloud_etcd_based/uncloud/__init__.py
similarity index 100%
rename from uncloud_etcd_based/uncloud/__init__.py
rename to archive/uncloud_etcd_based/uncloud/__init__.py
diff --git a/uncloud_etcd_based/uncloud/api/README.md b/archive/uncloud_etcd_based/uncloud/api/README.md
similarity index 100%
rename from uncloud_etcd_based/uncloud/api/README.md
rename to archive/uncloud_etcd_based/uncloud/api/README.md
diff --git a/uncloud_etcd_based/uncloud/api/__init__.py b/archive/uncloud_etcd_based/uncloud/api/__init__.py
similarity index 100%
rename from uncloud_etcd_based/uncloud/api/__init__.py
rename to archive/uncloud_etcd_based/uncloud/api/__init__.py
diff --git a/uncloud_etcd_based/uncloud/api/common_fields.py b/archive/uncloud_etcd_based/uncloud/api/common_fields.py
similarity index 100%
rename from uncloud_etcd_based/uncloud/api/common_fields.py
rename to archive/uncloud_etcd_based/uncloud/api/common_fields.py
diff --git a/uncloud_etcd_based/uncloud/api/create_image_store.py b/archive/uncloud_etcd_based/uncloud/api/create_image_store.py
similarity index 100%
rename from uncloud_etcd_based/uncloud/api/create_image_store.py
rename to archive/uncloud_etcd_based/uncloud/api/create_image_store.py
diff --git a/uncloud_etcd_based/uncloud/api/helper.py b/archive/uncloud_etcd_based/uncloud/api/helper.py
similarity index 100%
rename from uncloud_etcd_based/uncloud/api/helper.py
rename to archive/uncloud_etcd_based/uncloud/api/helper.py
diff --git a/uncloud_etcd_based/uncloud/api/main.py b/archive/uncloud_etcd_based/uncloud/api/main.py
similarity index 100%
rename from uncloud_etcd_based/uncloud/api/main.py
rename to archive/uncloud_etcd_based/uncloud/api/main.py
diff --git a/uncloud_etcd_based/uncloud/api/schemas.py b/archive/uncloud_etcd_based/uncloud/api/schemas.py
similarity index 100%
rename from uncloud_etcd_based/uncloud/api/schemas.py
rename to archive/uncloud_etcd_based/uncloud/api/schemas.py
diff --git a/uncloud_django_based/uncloud/uncloud_auth/migrations/__init__.py b/archive/uncloud_etcd_based/uncloud/cli/__init__.py
similarity index 100%
rename from uncloud_django_based/uncloud/uncloud_auth/migrations/__init__.py
rename to archive/uncloud_etcd_based/uncloud/cli/__init__.py
diff --git a/uncloud_etcd_based/uncloud/cli/helper.py b/archive/uncloud_etcd_based/uncloud/cli/helper.py
similarity index 100%
rename from uncloud_etcd_based/uncloud/cli/helper.py
rename to archive/uncloud_etcd_based/uncloud/cli/helper.py
diff --git a/uncloud_etcd_based/uncloud/cli/host.py b/archive/uncloud_etcd_based/uncloud/cli/host.py
similarity index 100%
rename from uncloud_etcd_based/uncloud/cli/host.py
rename to archive/uncloud_etcd_based/uncloud/cli/host.py
diff --git a/uncloud_etcd_based/uncloud/cli/image.py b/archive/uncloud_etcd_based/uncloud/cli/image.py
similarity index 100%
rename from uncloud_etcd_based/uncloud/cli/image.py
rename to archive/uncloud_etcd_based/uncloud/cli/image.py
diff --git a/uncloud_etcd_based/uncloud/cli/main.py b/archive/uncloud_etcd_based/uncloud/cli/main.py
similarity index 100%
rename from uncloud_etcd_based/uncloud/cli/main.py
rename to archive/uncloud_etcd_based/uncloud/cli/main.py
diff --git a/uncloud_etcd_based/uncloud/cli/network.py b/archive/uncloud_etcd_based/uncloud/cli/network.py
similarity index 100%
rename from uncloud_etcd_based/uncloud/cli/network.py
rename to archive/uncloud_etcd_based/uncloud/cli/network.py
diff --git a/uncloud_etcd_based/uncloud/cli/user.py b/archive/uncloud_etcd_based/uncloud/cli/user.py
similarity index 100%
rename from uncloud_etcd_based/uncloud/cli/user.py
rename to archive/uncloud_etcd_based/uncloud/cli/user.py
diff --git a/uncloud_etcd_based/uncloud/cli/vm.py b/archive/uncloud_etcd_based/uncloud/cli/vm.py
similarity index 100%
rename from uncloud_etcd_based/uncloud/cli/vm.py
rename to archive/uncloud_etcd_based/uncloud/cli/vm.py
diff --git a/uncloud_django_based/uncloud/uncloud_net/__init__.py b/archive/uncloud_etcd_based/uncloud/client/__init__.py
similarity index 100%
rename from uncloud_django_based/uncloud/uncloud_net/__init__.py
rename to archive/uncloud_etcd_based/uncloud/client/__init__.py
diff --git a/uncloud_etcd_based/uncloud/client/main.py b/archive/uncloud_etcd_based/uncloud/client/main.py
similarity index 100%
rename from uncloud_etcd_based/uncloud/client/main.py
rename to archive/uncloud_etcd_based/uncloud/client/main.py
diff --git a/uncloud_etcd_based/uncloud/common/__init__.py b/archive/uncloud_etcd_based/uncloud/common/__init__.py
similarity index 100%
rename from uncloud_etcd_based/uncloud/common/__init__.py
rename to archive/uncloud_etcd_based/uncloud/common/__init__.py
diff --git a/uncloud_etcd_based/uncloud/common/classes.py b/archive/uncloud_etcd_based/uncloud/common/classes.py
similarity index 100%
rename from uncloud_etcd_based/uncloud/common/classes.py
rename to archive/uncloud_etcd_based/uncloud/common/classes.py
diff --git a/uncloud_etcd_based/uncloud/common/cli.py b/archive/uncloud_etcd_based/uncloud/common/cli.py
similarity index 100%
rename from uncloud_etcd_based/uncloud/common/cli.py
rename to archive/uncloud_etcd_based/uncloud/common/cli.py
diff --git a/uncloud_etcd_based/uncloud/common/counters.py b/archive/uncloud_etcd_based/uncloud/common/counters.py
similarity index 100%
rename from uncloud_etcd_based/uncloud/common/counters.py
rename to archive/uncloud_etcd_based/uncloud/common/counters.py
diff --git a/uncloud_etcd_based/uncloud/common/etcd_wrapper.py b/archive/uncloud_etcd_based/uncloud/common/etcd_wrapper.py
similarity index 100%
rename from uncloud_etcd_based/uncloud/common/etcd_wrapper.py
rename to archive/uncloud_etcd_based/uncloud/common/etcd_wrapper.py
diff --git a/uncloud_etcd_based/uncloud/common/host.py b/archive/uncloud_etcd_based/uncloud/common/host.py
similarity index 100%
rename from uncloud_etcd_based/uncloud/common/host.py
rename to archive/uncloud_etcd_based/uncloud/common/host.py
diff --git a/uncloud_etcd_based/uncloud/common/network.py b/archive/uncloud_etcd_based/uncloud/common/network.py
similarity index 100%
rename from uncloud_etcd_based/uncloud/common/network.py
rename to archive/uncloud_etcd_based/uncloud/common/network.py
diff --git a/uncloud_etcd_based/uncloud/common/parser.py b/archive/uncloud_etcd_based/uncloud/common/parser.py
similarity index 100%
rename from uncloud_etcd_based/uncloud/common/parser.py
rename to archive/uncloud_etcd_based/uncloud/common/parser.py
diff --git a/uncloud_etcd_based/uncloud/common/request.py b/archive/uncloud_etcd_based/uncloud/common/request.py
similarity index 100%
rename from uncloud_etcd_based/uncloud/common/request.py
rename to archive/uncloud_etcd_based/uncloud/common/request.py
diff --git a/uncloud_etcd_based/uncloud/common/schemas.py b/archive/uncloud_etcd_based/uncloud/common/schemas.py
similarity index 100%
rename from uncloud_etcd_based/uncloud/common/schemas.py
rename to archive/uncloud_etcd_based/uncloud/common/schemas.py
diff --git a/uncloud_etcd_based/uncloud/common/settings.py b/archive/uncloud_etcd_based/uncloud/common/settings.py
similarity index 100%
rename from uncloud_etcd_based/uncloud/common/settings.py
rename to archive/uncloud_etcd_based/uncloud/common/settings.py
diff --git a/uncloud_etcd_based/uncloud/common/shared.py b/archive/uncloud_etcd_based/uncloud/common/shared.py
similarity index 100%
rename from uncloud_etcd_based/uncloud/common/shared.py
rename to archive/uncloud_etcd_based/uncloud/common/shared.py
diff --git a/uncloud_etcd_based/uncloud/common/storage_handlers.py b/archive/uncloud_etcd_based/uncloud/common/storage_handlers.py
similarity index 100%
rename from uncloud_etcd_based/uncloud/common/storage_handlers.py
rename to archive/uncloud_etcd_based/uncloud/common/storage_handlers.py
diff --git a/uncloud_etcd_based/uncloud/common/vm.py b/archive/uncloud_etcd_based/uncloud/common/vm.py
similarity index 100%
rename from uncloud_etcd_based/uncloud/common/vm.py
rename to archive/uncloud_etcd_based/uncloud/common/vm.py
diff --git a/uncloud_django_based/uncloud/uncloud_net/migrations/__init__.py b/archive/uncloud_etcd_based/uncloud/configure/__init__.py
similarity index 100%
rename from uncloud_django_based/uncloud/uncloud_net/migrations/__init__.py
rename to archive/uncloud_etcd_based/uncloud/configure/__init__.py
diff --git a/uncloud_etcd_based/uncloud/configure/main.py b/archive/uncloud_etcd_based/uncloud/configure/main.py
similarity index 100%
rename from uncloud_etcd_based/uncloud/configure/main.py
rename to archive/uncloud_etcd_based/uncloud/configure/main.py
diff --git a/uncloud_etcd_based/uncloud/filescanner/__init__.py b/archive/uncloud_etcd_based/uncloud/filescanner/__init__.py
similarity index 100%
rename from uncloud_etcd_based/uncloud/filescanner/__init__.py
rename to archive/uncloud_etcd_based/uncloud/filescanner/__init__.py
diff --git a/uncloud_etcd_based/uncloud/filescanner/main.py b/archive/uncloud_etcd_based/uncloud/filescanner/main.py
similarity index 100%
rename from uncloud_etcd_based/uncloud/filescanner/main.py
rename to archive/uncloud_etcd_based/uncloud/filescanner/main.py
diff --git a/uncloud_etcd_based/uncloud/hack/README.org b/archive/uncloud_etcd_based/uncloud/hack/README.org
similarity index 100%
rename from uncloud_etcd_based/uncloud/hack/README.org
rename to archive/uncloud_etcd_based/uncloud/hack/README.org
diff --git a/uncloud_etcd_based/uncloud/hack/__init__.py b/archive/uncloud_etcd_based/uncloud/hack/__init__.py
similarity index 100%
rename from uncloud_etcd_based/uncloud/hack/__init__.py
rename to archive/uncloud_etcd_based/uncloud/hack/__init__.py
diff --git a/uncloud_etcd_based/uncloud/hack/conf.d/ucloud-host b/archive/uncloud_etcd_based/uncloud/hack/conf.d/ucloud-host
similarity index 100%
rename from uncloud_etcd_based/uncloud/hack/conf.d/ucloud-host
rename to archive/uncloud_etcd_based/uncloud/hack/conf.d/ucloud-host
diff --git a/uncloud_etcd_based/uncloud/hack/config.py b/archive/uncloud_etcd_based/uncloud/hack/config.py
similarity index 100%
rename from uncloud_etcd_based/uncloud/hack/config.py
rename to archive/uncloud_etcd_based/uncloud/hack/config.py
diff --git a/uncloud_etcd_based/uncloud/hack/db.py b/archive/uncloud_etcd_based/uncloud/hack/db.py
similarity index 100%
rename from uncloud_etcd_based/uncloud/hack/db.py
rename to archive/uncloud_etcd_based/uncloud/hack/db.py
diff --git a/uncloud_etcd_based/uncloud/hack/hackcloud/.gitignore b/archive/uncloud_etcd_based/uncloud/hack/hackcloud/.gitignore
similarity index 100%
rename from uncloud_etcd_based/uncloud/hack/hackcloud/.gitignore
rename to archive/uncloud_etcd_based/uncloud/hack/hackcloud/.gitignore
diff --git a/uncloud_etcd_based/uncloud/hack/hackcloud/__init__.py b/archive/uncloud_etcd_based/uncloud/hack/hackcloud/__init__.py
similarity index 100%
rename from uncloud_etcd_based/uncloud/hack/hackcloud/__init__.py
rename to archive/uncloud_etcd_based/uncloud/hack/hackcloud/__init__.py
diff --git a/uncloud_etcd_based/uncloud/hack/hackcloud/etcd-client.sh b/archive/uncloud_etcd_based/uncloud/hack/hackcloud/etcd-client.sh
similarity index 100%
rename from uncloud_etcd_based/uncloud/hack/hackcloud/etcd-client.sh
rename to archive/uncloud_etcd_based/uncloud/hack/hackcloud/etcd-client.sh
diff --git a/uncloud_etcd_based/uncloud/hack/hackcloud/ifdown.sh b/archive/uncloud_etcd_based/uncloud/hack/hackcloud/ifdown.sh
similarity index 100%
rename from uncloud_etcd_based/uncloud/hack/hackcloud/ifdown.sh
rename to archive/uncloud_etcd_based/uncloud/hack/hackcloud/ifdown.sh
diff --git a/uncloud_etcd_based/uncloud/hack/hackcloud/ifup.sh b/archive/uncloud_etcd_based/uncloud/hack/hackcloud/ifup.sh
similarity index 100%
rename from uncloud_etcd_based/uncloud/hack/hackcloud/ifup.sh
rename to archive/uncloud_etcd_based/uncloud/hack/hackcloud/ifup.sh
diff --git a/uncloud_etcd_based/uncloud/hack/hackcloud/mac-last b/archive/uncloud_etcd_based/uncloud/hack/hackcloud/mac-last
similarity index 100%
rename from uncloud_etcd_based/uncloud/hack/hackcloud/mac-last
rename to archive/uncloud_etcd_based/uncloud/hack/hackcloud/mac-last
diff --git a/uncloud_etcd_based/uncloud/hack/hackcloud/mac-prefix b/archive/uncloud_etcd_based/uncloud/hack/hackcloud/mac-prefix
similarity index 100%
rename from uncloud_etcd_based/uncloud/hack/hackcloud/mac-prefix
rename to archive/uncloud_etcd_based/uncloud/hack/hackcloud/mac-prefix
diff --git a/uncloud_etcd_based/uncloud/hack/hackcloud/net.sh b/archive/uncloud_etcd_based/uncloud/hack/hackcloud/net.sh
similarity index 100%
rename from uncloud_etcd_based/uncloud/hack/hackcloud/net.sh
rename to archive/uncloud_etcd_based/uncloud/hack/hackcloud/net.sh
diff --git a/uncloud_etcd_based/uncloud/hack/hackcloud/nftrules b/archive/uncloud_etcd_based/uncloud/hack/hackcloud/nftrules
similarity index 100%
rename from uncloud_etcd_based/uncloud/hack/hackcloud/nftrules
rename to archive/uncloud_etcd_based/uncloud/hack/hackcloud/nftrules
diff --git a/uncloud_etcd_based/uncloud/hack/hackcloud/radvd.conf b/archive/uncloud_etcd_based/uncloud/hack/hackcloud/radvd.conf
similarity index 100%
rename from uncloud_etcd_based/uncloud/hack/hackcloud/radvd.conf
rename to archive/uncloud_etcd_based/uncloud/hack/hackcloud/radvd.conf
diff --git a/uncloud_etcd_based/uncloud/hack/hackcloud/radvd.sh b/archive/uncloud_etcd_based/uncloud/hack/hackcloud/radvd.sh
similarity index 100%
rename from uncloud_etcd_based/uncloud/hack/hackcloud/radvd.sh
rename to archive/uncloud_etcd_based/uncloud/hack/hackcloud/radvd.sh
diff --git a/uncloud_etcd_based/uncloud/hack/hackcloud/vm.sh b/archive/uncloud_etcd_based/uncloud/hack/hackcloud/vm.sh
similarity index 100%
rename from uncloud_etcd_based/uncloud/hack/hackcloud/vm.sh
rename to archive/uncloud_etcd_based/uncloud/hack/hackcloud/vm.sh
diff --git a/uncloud_etcd_based/uncloud/hack/host.py b/archive/uncloud_etcd_based/uncloud/hack/host.py
similarity index 100%
rename from uncloud_etcd_based/uncloud/hack/host.py
rename to archive/uncloud_etcd_based/uncloud/hack/host.py
diff --git a/uncloud_etcd_based/uncloud/hack/mac.py b/archive/uncloud_etcd_based/uncloud/hack/mac.py
similarity index 100%
rename from uncloud_etcd_based/uncloud/hack/mac.py
rename to archive/uncloud_etcd_based/uncloud/hack/mac.py
diff --git a/uncloud_etcd_based/uncloud/hack/main.py b/archive/uncloud_etcd_based/uncloud/hack/main.py
similarity index 100%
rename from uncloud_etcd_based/uncloud/hack/main.py
rename to archive/uncloud_etcd_based/uncloud/hack/main.py
diff --git a/uncloud_etcd_based/uncloud/hack/net.py b/archive/uncloud_etcd_based/uncloud/hack/net.py
similarity index 100%
rename from uncloud_etcd_based/uncloud/hack/net.py
rename to archive/uncloud_etcd_based/uncloud/hack/net.py
diff --git a/uncloud_etcd_based/uncloud/hack/nftables.conf b/archive/uncloud_etcd_based/uncloud/hack/nftables.conf
similarity index 100%
rename from uncloud_etcd_based/uncloud/hack/nftables.conf
rename to archive/uncloud_etcd_based/uncloud/hack/nftables.conf
diff --git a/uncloud_etcd_based/uncloud/hack/product.py b/archive/uncloud_etcd_based/uncloud/hack/product.py
similarity index 100%
rename from uncloud_etcd_based/uncloud/hack/product.py
rename to archive/uncloud_etcd_based/uncloud/hack/product.py
diff --git a/uncloud_etcd_based/uncloud/hack/rc-scripts/ucloud-api b/archive/uncloud_etcd_based/uncloud/hack/rc-scripts/ucloud-api
similarity index 100%
rename from uncloud_etcd_based/uncloud/hack/rc-scripts/ucloud-api
rename to archive/uncloud_etcd_based/uncloud/hack/rc-scripts/ucloud-api
diff --git a/uncloud_etcd_based/uncloud/hack/rc-scripts/ucloud-host b/archive/uncloud_etcd_based/uncloud/hack/rc-scripts/ucloud-host
similarity index 100%
rename from uncloud_etcd_based/uncloud/hack/rc-scripts/ucloud-host
rename to archive/uncloud_etcd_based/uncloud/hack/rc-scripts/ucloud-host
diff --git a/uncloud_etcd_based/uncloud/hack/rc-scripts/ucloud-metadata b/archive/uncloud_etcd_based/uncloud/hack/rc-scripts/ucloud-metadata
similarity index 100%
rename from uncloud_etcd_based/uncloud/hack/rc-scripts/ucloud-metadata
rename to archive/uncloud_etcd_based/uncloud/hack/rc-scripts/ucloud-metadata
diff --git a/uncloud_etcd_based/uncloud/hack/rc-scripts/ucloud-scheduler b/archive/uncloud_etcd_based/uncloud/hack/rc-scripts/ucloud-scheduler
similarity index 100%
rename from uncloud_etcd_based/uncloud/hack/rc-scripts/ucloud-scheduler
rename to archive/uncloud_etcd_based/uncloud/hack/rc-scripts/ucloud-scheduler
diff --git a/uncloud_etcd_based/uncloud/hack/uncloud-hack-init-host b/archive/uncloud_etcd_based/uncloud/hack/uncloud-hack-init-host
similarity index 100%
rename from uncloud_etcd_based/uncloud/hack/uncloud-hack-init-host
rename to archive/uncloud_etcd_based/uncloud/hack/uncloud-hack-init-host
diff --git a/uncloud_etcd_based/uncloud/hack/uncloud-run-vm b/archive/uncloud_etcd_based/uncloud/hack/uncloud-run-vm
similarity index 100%
rename from uncloud_etcd_based/uncloud/hack/uncloud-run-vm
rename to archive/uncloud_etcd_based/uncloud/hack/uncloud-run-vm
diff --git a/uncloud_etcd_based/uncloud/hack/vm.py b/archive/uncloud_etcd_based/uncloud/hack/vm.py
similarity index 100%
rename from uncloud_etcd_based/uncloud/hack/vm.py
rename to archive/uncloud_etcd_based/uncloud/hack/vm.py
diff --git a/uncloud_etcd_based/uncloud/host/__init__.py b/archive/uncloud_etcd_based/uncloud/host/__init__.py
similarity index 100%
rename from uncloud_etcd_based/uncloud/host/__init__.py
rename to archive/uncloud_etcd_based/uncloud/host/__init__.py
diff --git a/uncloud_etcd_based/uncloud/host/main.py b/archive/uncloud_etcd_based/uncloud/host/main.py
similarity index 100%
rename from uncloud_etcd_based/uncloud/host/main.py
rename to archive/uncloud_etcd_based/uncloud/host/main.py
diff --git a/uncloud_etcd_based/uncloud/host/virtualmachine.py b/archive/uncloud_etcd_based/uncloud/host/virtualmachine.py
similarity index 100%
rename from uncloud_etcd_based/uncloud/host/virtualmachine.py
rename to archive/uncloud_etcd_based/uncloud/host/virtualmachine.py
diff --git a/uncloud_etcd_based/uncloud/imagescanner/__init__.py b/archive/uncloud_etcd_based/uncloud/imagescanner/__init__.py
similarity index 100%
rename from uncloud_etcd_based/uncloud/imagescanner/__init__.py
rename to archive/uncloud_etcd_based/uncloud/imagescanner/__init__.py
diff --git a/uncloud_etcd_based/uncloud/imagescanner/main.py b/archive/uncloud_etcd_based/uncloud/imagescanner/main.py
similarity index 100%
rename from uncloud_etcd_based/uncloud/imagescanner/main.py
rename to archive/uncloud_etcd_based/uncloud/imagescanner/main.py
diff --git a/uncloud_etcd_based/uncloud/metadata/__init__.py b/archive/uncloud_etcd_based/uncloud/metadata/__init__.py
similarity index 100%
rename from uncloud_etcd_based/uncloud/metadata/__init__.py
rename to archive/uncloud_etcd_based/uncloud/metadata/__init__.py
diff --git a/uncloud_etcd_based/uncloud/metadata/main.py b/archive/uncloud_etcd_based/uncloud/metadata/main.py
similarity index 100%
rename from uncloud_etcd_based/uncloud/metadata/main.py
rename to archive/uncloud_etcd_based/uncloud/metadata/main.py
diff --git a/uncloud_etcd_based/uncloud/network/README b/archive/uncloud_etcd_based/uncloud/network/README
similarity index 100%
rename from uncloud_etcd_based/uncloud/network/README
rename to archive/uncloud_etcd_based/uncloud/network/README
diff --git a/uncloud_django_based/uncloud/uncloud_pay/__init__.py b/archive/uncloud_etcd_based/uncloud/network/__init__.py
similarity index 100%
rename from uncloud_django_based/uncloud/uncloud_pay/__init__.py
rename to archive/uncloud_etcd_based/uncloud/network/__init__.py
diff --git a/uncloud_etcd_based/uncloud/network/create-bridge.sh b/archive/uncloud_etcd_based/uncloud/network/create-bridge.sh
similarity index 100%
rename from uncloud_etcd_based/uncloud/network/create-bridge.sh
rename to archive/uncloud_etcd_based/uncloud/network/create-bridge.sh
diff --git a/uncloud_etcd_based/uncloud/network/create-tap.sh b/archive/uncloud_etcd_based/uncloud/network/create-tap.sh
similarity index 100%
rename from uncloud_etcd_based/uncloud/network/create-tap.sh
rename to archive/uncloud_etcd_based/uncloud/network/create-tap.sh
diff --git a/uncloud_etcd_based/uncloud/network/create-vxlan.sh b/archive/uncloud_etcd_based/uncloud/network/create-vxlan.sh
similarity index 100%
rename from uncloud_etcd_based/uncloud/network/create-vxlan.sh
rename to archive/uncloud_etcd_based/uncloud/network/create-vxlan.sh
diff --git a/uncloud_etcd_based/uncloud/network/radvd-template.conf b/archive/uncloud_etcd_based/uncloud/network/radvd-template.conf
similarity index 100%
rename from uncloud_etcd_based/uncloud/network/radvd-template.conf
rename to archive/uncloud_etcd_based/uncloud/network/radvd-template.conf
diff --git a/uncloud_etcd_based/uncloud/oneshot/__init__.py b/archive/uncloud_etcd_based/uncloud/oneshot/__init__.py
similarity index 100%
rename from uncloud_etcd_based/uncloud/oneshot/__init__.py
rename to archive/uncloud_etcd_based/uncloud/oneshot/__init__.py
diff --git a/uncloud_etcd_based/uncloud/oneshot/main.py b/archive/uncloud_etcd_based/uncloud/oneshot/main.py
similarity index 100%
rename from uncloud_etcd_based/uncloud/oneshot/main.py
rename to archive/uncloud_etcd_based/uncloud/oneshot/main.py
diff --git a/uncloud_etcd_based/uncloud/oneshot/virtualmachine.py b/archive/uncloud_etcd_based/uncloud/oneshot/virtualmachine.py
similarity index 100%
rename from uncloud_etcd_based/uncloud/oneshot/virtualmachine.py
rename to archive/uncloud_etcd_based/uncloud/oneshot/virtualmachine.py
diff --git a/uncloud_etcd_based/uncloud/scheduler/__init__.py b/archive/uncloud_etcd_based/uncloud/scheduler/__init__.py
similarity index 100%
rename from uncloud_etcd_based/uncloud/scheduler/__init__.py
rename to archive/uncloud_etcd_based/uncloud/scheduler/__init__.py
diff --git a/uncloud_etcd_based/uncloud/scheduler/helper.py b/archive/uncloud_etcd_based/uncloud/scheduler/helper.py
similarity index 100%
rename from uncloud_etcd_based/uncloud/scheduler/helper.py
rename to archive/uncloud_etcd_based/uncloud/scheduler/helper.py
diff --git a/uncloud_etcd_based/uncloud/scheduler/main.py b/archive/uncloud_etcd_based/uncloud/scheduler/main.py
similarity index 100%
rename from uncloud_etcd_based/uncloud/scheduler/main.py
rename to archive/uncloud_etcd_based/uncloud/scheduler/main.py
diff --git a/uncloud_django_based/uncloud/uncloud_pay/migrations/__init__.py b/archive/uncloud_etcd_based/uncloud/scheduler/tests/__init__.py
similarity index 100%
rename from uncloud_django_based/uncloud/uncloud_pay/migrations/__init__.py
rename to archive/uncloud_etcd_based/uncloud/scheduler/tests/__init__.py
diff --git a/uncloud_etcd_based/uncloud/scheduler/tests/test_basics.py b/archive/uncloud_etcd_based/uncloud/scheduler/tests/test_basics.py
similarity index 100%
rename from uncloud_etcd_based/uncloud/scheduler/tests/test_basics.py
rename to archive/uncloud_etcd_based/uncloud/scheduler/tests/test_basics.py
diff --git a/uncloud_etcd_based/uncloud/scheduler/tests/test_dead_host_mechanism.py b/archive/uncloud_etcd_based/uncloud/scheduler/tests/test_dead_host_mechanism.py
similarity index 100%
rename from uncloud_etcd_based/uncloud/scheduler/tests/test_dead_host_mechanism.py
rename to archive/uncloud_etcd_based/uncloud/scheduler/tests/test_dead_host_mechanism.py
diff --git a/uncloud_etcd_based/uncloud/version.py b/archive/uncloud_etcd_based/uncloud/version.py
similarity index 100%
rename from uncloud_etcd_based/uncloud/version.py
rename to archive/uncloud_etcd_based/uncloud/version.py
diff --git a/uncloud_etcd_based/uncloud/vmm/__init__.py b/archive/uncloud_etcd_based/uncloud/vmm/__init__.py
similarity index 100%
rename from uncloud_etcd_based/uncloud/vmm/__init__.py
rename to archive/uncloud_etcd_based/uncloud/vmm/__init__.py
diff --git a/uncloud_django_based/uncloud/doc/README-how-to-configure-remote-uncloud-clients.org b/doc/README-how-to-configure-remote-uncloud-clients.org
similarity index 100%
rename from uncloud_django_based/uncloud/doc/README-how-to-configure-remote-uncloud-clients.org
rename to doc/README-how-to-configure-remote-uncloud-clients.org
diff --git a/uncloud_django_based/uncloud/doc/README-identifiers.org b/doc/README-identifiers.org
similarity index 100%
rename from uncloud_django_based/uncloud/doc/README-identifiers.org
rename to doc/README-identifiers.org
diff --git a/uncloud_django_based/uncloud/doc/README-object-relations.md b/doc/README-object-relations.md
similarity index 100%
rename from uncloud_django_based/uncloud/doc/README-object-relations.md
rename to doc/README-object-relations.md
diff --git a/uncloud_django_based/uncloud/doc/README-postgresql.org b/doc/README-postgresql.org
similarity index 100%
rename from uncloud_django_based/uncloud/doc/README-postgresql.org
rename to doc/README-postgresql.org
diff --git a/uncloud_django_based/uncloud/doc/README-products.md b/doc/README-products.md
similarity index 100%
rename from uncloud_django_based/uncloud/doc/README-products.md
rename to doc/README-products.md
diff --git a/uncloud_django_based/uncloud/doc/README-vpn.org b/doc/README-vpn.org
similarity index 100%
rename from uncloud_django_based/uncloud/doc/README-vpn.org
rename to doc/README-vpn.org
diff --git a/uncloud_django_based/uncloud/doc/README.md b/doc/README.md
similarity index 100%
rename from uncloud_django_based/uncloud/doc/README.md
rename to doc/README.md
diff --git a/uncloud_django_based/uncloud/manage.py b/manage.py
similarity index 100%
rename from uncloud_django_based/uncloud/manage.py
rename to manage.py
diff --git a/uncloud_django_based/uncloud/models.dot b/models.dot
similarity index 100%
rename from uncloud_django_based/uncloud/models.dot
rename to models.dot
diff --git a/uncloud_django_based/uncloud/models.png b/models.png
similarity index 100%
rename from uncloud_django_based/uncloud/models.png
rename to models.png
diff --git a/uncloud_django_based/uncloud/uncloud_service/__init__.py b/opennebula/__init__.py
similarity index 100%
rename from uncloud_django_based/uncloud/uncloud_service/__init__.py
rename to opennebula/__init__.py
diff --git a/uncloud_django_based/uncloud/opennebula/admin.py b/opennebula/admin.py
similarity index 100%
rename from uncloud_django_based/uncloud/opennebula/admin.py
rename to opennebula/admin.py
diff --git a/uncloud_django_based/uncloud/opennebula/apps.py b/opennebula/apps.py
similarity index 100%
rename from uncloud_django_based/uncloud/opennebula/apps.py
rename to opennebula/apps.py
diff --git a/uncloud_django_based/uncloud/opennebula/management/commands/opennebula-synchosts.py b/opennebula/management/commands/opennebula-synchosts.py
similarity index 100%
rename from uncloud_django_based/uncloud/opennebula/management/commands/opennebula-synchosts.py
rename to opennebula/management/commands/opennebula-synchosts.py
diff --git a/uncloud_django_based/uncloud/opennebula/management/commands/opennebula-syncvms.py b/opennebula/management/commands/opennebula-syncvms.py
similarity index 100%
rename from uncloud_django_based/uncloud/opennebula/management/commands/opennebula-syncvms.py
rename to opennebula/management/commands/opennebula-syncvms.py
diff --git a/uncloud_django_based/uncloud/opennebula/management/commands/opennebula-to-uncloud.py b/opennebula/management/commands/opennebula-to-uncloud.py
similarity index 100%
rename from uncloud_django_based/uncloud/opennebula/management/commands/opennebula-to-uncloud.py
rename to opennebula/management/commands/opennebula-to-uncloud.py
diff --git a/uncloud_django_based/uncloud/opennebula/migrations/0001_initial.py b/opennebula/migrations/0001_initial.py
similarity index 100%
rename from uncloud_django_based/uncloud/opennebula/migrations/0001_initial.py
rename to opennebula/migrations/0001_initial.py
diff --git a/uncloud_django_based/uncloud/opennebula/migrations/0002_auto_20200225_1335.py b/opennebula/migrations/0002_auto_20200225_1335.py
similarity index 100%
rename from uncloud_django_based/uncloud/opennebula/migrations/0002_auto_20200225_1335.py
rename to opennebula/migrations/0002_auto_20200225_1335.py
diff --git a/uncloud_django_based/uncloud/opennebula/migrations/0003_auto_20200225_1428.py b/opennebula/migrations/0003_auto_20200225_1428.py
similarity index 100%
rename from uncloud_django_based/uncloud/opennebula/migrations/0003_auto_20200225_1428.py
rename to opennebula/migrations/0003_auto_20200225_1428.py
diff --git a/uncloud_django_based/uncloud/opennebula/migrations/0004_auto_20200225_1816.py b/opennebula/migrations/0004_auto_20200225_1816.py
similarity index 100%
rename from uncloud_django_based/uncloud/opennebula/migrations/0004_auto_20200225_1816.py
rename to opennebula/migrations/0004_auto_20200225_1816.py
diff --git a/uncloud_django_based/uncloud/uncloud_service/migrations/__init__.py b/opennebula/migrations/__init__.py
similarity index 100%
rename from uncloud_django_based/uncloud/uncloud_service/migrations/__init__.py
rename to opennebula/migrations/__init__.py
diff --git a/uncloud_django_based/uncloud/opennebula/models.py b/opennebula/models.py
similarity index 100%
rename from uncloud_django_based/uncloud/opennebula/models.py
rename to opennebula/models.py
diff --git a/uncloud_django_based/uncloud/opennebula/serializers.py b/opennebula/serializers.py
similarity index 100%
rename from uncloud_django_based/uncloud/opennebula/serializers.py
rename to opennebula/serializers.py
diff --git a/uncloud_django_based/uncloud/opennebula/tests.py b/opennebula/tests.py
similarity index 100%
rename from uncloud_django_based/uncloud/opennebula/tests.py
rename to opennebula/tests.py
diff --git a/uncloud_django_based/uncloud/opennebula/views.py b/opennebula/views.py
similarity index 100%
rename from uncloud_django_based/uncloud/opennebula/views.py
rename to opennebula/views.py
diff --git a/uncloud_django_based/uncloud/requirements.txt b/requirements.txt
similarity index 100%
rename from uncloud_django_based/uncloud/requirements.txt
rename to requirements.txt
diff --git a/uncloud_django_based/uncloud/uncloud/.gitignore b/uncloud/.gitignore
similarity index 100%
rename from uncloud_django_based/uncloud/uncloud/.gitignore
rename to uncloud/.gitignore
diff --git a/uncloud_django_based/uncloud/uncloud/__init__.py b/uncloud/__init__.py
similarity index 100%
rename from uncloud_django_based/uncloud/uncloud/__init__.py
rename to uncloud/__init__.py
diff --git a/uncloud_django_based/uncloud/uncloud/asgi.py b/uncloud/asgi.py
similarity index 100%
rename from uncloud_django_based/uncloud/uncloud/asgi.py
rename to uncloud/asgi.py
diff --git a/uncloud_django_based/uncloud/uncloud/management/commands/uncloud.py b/uncloud/management/commands/uncloud.py
similarity index 100%
rename from uncloud_django_based/uncloud/uncloud/management/commands/uncloud.py
rename to uncloud/management/commands/uncloud.py
diff --git a/uncloud_django_based/uncloud/uncloud/models.py b/uncloud/models.py
similarity index 100%
rename from uncloud_django_based/uncloud/uncloud/models.py
rename to uncloud/models.py
diff --git a/uncloud_django_based/uncloud/uncloud/settings.py b/uncloud/settings.py
similarity index 100%
rename from uncloud_django_based/uncloud/uncloud/settings.py
rename to uncloud/settings.py
diff --git a/uncloud_django_based/uncloud/uncloud/urls.py b/uncloud/urls.py
similarity index 100%
rename from uncloud_django_based/uncloud/uncloud/urls.py
rename to uncloud/urls.py
diff --git a/uncloud_django_based/uncloud/uncloud/wsgi.py b/uncloud/wsgi.py
similarity index 100%
rename from uncloud_django_based/uncloud/uncloud/wsgi.py
rename to uncloud/wsgi.py
diff --git a/uncloud_django_based/uncloud/uncloud_storage/__init__.py b/uncloud_auth/__init__.py
similarity index 100%
rename from uncloud_django_based/uncloud/uncloud_storage/__init__.py
rename to uncloud_auth/__init__.py
diff --git a/uncloud_django_based/uncloud/uncloud_auth/admin.py b/uncloud_auth/admin.py
similarity index 100%
rename from uncloud_django_based/uncloud/uncloud_auth/admin.py
rename to uncloud_auth/admin.py
diff --git a/uncloud_django_based/uncloud/uncloud_auth/apps.py b/uncloud_auth/apps.py
similarity index 100%
rename from uncloud_django_based/uncloud/uncloud_auth/apps.py
rename to uncloud_auth/apps.py
diff --git a/uncloud_django_based/uncloud/uncloud_auth/migrations/0001_initial.py b/uncloud_auth/migrations/0001_initial.py
similarity index 100%
rename from uncloud_django_based/uncloud/uncloud_auth/migrations/0001_initial.py
rename to uncloud_auth/migrations/0001_initial.py
diff --git a/uncloud_django_based/uncloud/uncloud_auth/migrations/0002_auto_20200318_1343.py b/uncloud_auth/migrations/0002_auto_20200318_1343.py
similarity index 100%
rename from uncloud_django_based/uncloud/uncloud_auth/migrations/0002_auto_20200318_1343.py
rename to uncloud_auth/migrations/0002_auto_20200318_1343.py
diff --git a/uncloud_django_based/uncloud/uncloud_auth/migrations/0003_auto_20200318_1345.py b/uncloud_auth/migrations/0003_auto_20200318_1345.py
similarity index 100%
rename from uncloud_django_based/uncloud/uncloud_auth/migrations/0003_auto_20200318_1345.py
rename to uncloud_auth/migrations/0003_auto_20200318_1345.py
diff --git a/uncloud_django_based/uncloud/uncloud_vm/__init__.py b/uncloud_auth/migrations/__init__.py
similarity index 100%
rename from uncloud_django_based/uncloud/uncloud_vm/__init__.py
rename to uncloud_auth/migrations/__init__.py
diff --git a/uncloud_django_based/uncloud/uncloud_auth/models.py b/uncloud_auth/models.py
similarity index 100%
rename from uncloud_django_based/uncloud/uncloud_auth/models.py
rename to uncloud_auth/models.py
diff --git a/uncloud_django_based/uncloud/uncloud_auth/serializers.py b/uncloud_auth/serializers.py
similarity index 100%
rename from uncloud_django_based/uncloud/uncloud_auth/serializers.py
rename to uncloud_auth/serializers.py
diff --git a/uncloud_django_based/uncloud/uncloud_auth/views.py b/uncloud_auth/views.py
similarity index 100%
rename from uncloud_django_based/uncloud/uncloud_auth/views.py
rename to uncloud_auth/views.py
diff --git a/uncloud_django_based/uncloud/uncloud_vm/migrations/__init__.py b/uncloud_net/__init__.py
similarity index 100%
rename from uncloud_django_based/uncloud/uncloud_vm/migrations/__init__.py
rename to uncloud_net/__init__.py
diff --git a/uncloud_django_based/uncloud/uncloud_net/admin.py b/uncloud_net/admin.py
similarity index 100%
rename from uncloud_django_based/uncloud/uncloud_net/admin.py
rename to uncloud_net/admin.py
diff --git a/uncloud_django_based/uncloud/uncloud_net/apps.py b/uncloud_net/apps.py
similarity index 100%
rename from uncloud_django_based/uncloud/uncloud_net/apps.py
rename to uncloud_net/apps.py
diff --git a/uncloud_django_based/uncloud/uncloud_net/management/commands/vpn.py b/uncloud_net/management/commands/vpn.py
similarity index 100%
rename from uncloud_django_based/uncloud/uncloud_net/management/commands/vpn.py
rename to uncloud_net/management/commands/vpn.py
diff --git a/uncloud_django_based/uncloud/uncloud_net/migrations/0001_initial.py b/uncloud_net/migrations/0001_initial.py
similarity index 100%
rename from uncloud_django_based/uncloud/uncloud_net/migrations/0001_initial.py
rename to uncloud_net/migrations/0001_initial.py
diff --git a/uncloud_django_based/uncloud/uncloud_net/migrations/0002_auto_20200409_1225.py b/uncloud_net/migrations/0002_auto_20200409_1225.py
similarity index 100%
rename from uncloud_django_based/uncloud/uncloud_net/migrations/0002_auto_20200409_1225.py
rename to uncloud_net/migrations/0002_auto_20200409_1225.py
diff --git a/uncloud_django_based/uncloud/uncloud_net/migrations/0003_auto_20200417_0551.py b/uncloud_net/migrations/0003_auto_20200417_0551.py
similarity index 100%
rename from uncloud_django_based/uncloud/uncloud_net/migrations/0003_auto_20200417_0551.py
rename to uncloud_net/migrations/0003_auto_20200417_0551.py
diff --git a/uncloud_etcd_based/docs/__init__.py b/uncloud_net/migrations/__init__.py
similarity index 100%
rename from uncloud_etcd_based/docs/__init__.py
rename to uncloud_net/migrations/__init__.py
diff --git a/uncloud_django_based/uncloud/uncloud_net/models.py b/uncloud_net/models.py
similarity index 100%
rename from uncloud_django_based/uncloud/uncloud_net/models.py
rename to uncloud_net/models.py
diff --git a/uncloud_django_based/uncloud/uncloud_net/serializers.py b/uncloud_net/serializers.py
similarity index 100%
rename from uncloud_django_based/uncloud/uncloud_net/serializers.py
rename to uncloud_net/serializers.py
diff --git a/uncloud_django_based/uncloud/uncloud_net/tests.py b/uncloud_net/tests.py
similarity index 100%
rename from uncloud_django_based/uncloud/uncloud_net/tests.py
rename to uncloud_net/tests.py
diff --git a/uncloud_django_based/uncloud/uncloud_net/views.py b/uncloud_net/views.py
similarity index 100%
rename from uncloud_django_based/uncloud/uncloud_net/views.py
rename to uncloud_net/views.py
diff --git a/uncloud_etcd_based/docs/source/__init__.py b/uncloud_pay/__init__.py
similarity index 100%
rename from uncloud_etcd_based/docs/source/__init__.py
rename to uncloud_pay/__init__.py
diff --git a/uncloud_django_based/uncloud/uncloud_pay/admin.py b/uncloud_pay/admin.py
similarity index 100%
rename from uncloud_django_based/uncloud/uncloud_pay/admin.py
rename to uncloud_pay/admin.py
diff --git a/uncloud_django_based/uncloud/uncloud_pay/apps.py b/uncloud_pay/apps.py
similarity index 100%
rename from uncloud_django_based/uncloud/uncloud_pay/apps.py
rename to uncloud_pay/apps.py
diff --git a/uncloud_django_based/uncloud/uncloud_pay/helpers.py b/uncloud_pay/helpers.py
similarity index 100%
rename from uncloud_django_based/uncloud/uncloud_pay/helpers.py
rename to uncloud_pay/helpers.py
diff --git a/uncloud_django_based/uncloud/uncloud_pay/management/commands/charge-negative-balance.py b/uncloud_pay/management/commands/charge-negative-balance.py
similarity index 100%
rename from uncloud_django_based/uncloud/uncloud_pay/management/commands/charge-negative-balance.py
rename to uncloud_pay/management/commands/charge-negative-balance.py
diff --git a/uncloud_django_based/uncloud/uncloud_pay/management/commands/generate-bills.py b/uncloud_pay/management/commands/generate-bills.py
similarity index 100%
rename from uncloud_django_based/uncloud/uncloud_pay/management/commands/generate-bills.py
rename to uncloud_pay/management/commands/generate-bills.py
diff --git a/uncloud_django_based/uncloud/uncloud_pay/management/commands/handle-overdue-bills.py b/uncloud_pay/management/commands/handle-overdue-bills.py
similarity index 100%
rename from uncloud_django_based/uncloud/uncloud_pay/management/commands/handle-overdue-bills.py
rename to uncloud_pay/management/commands/handle-overdue-bills.py
diff --git a/uncloud_django_based/uncloud/uncloud_pay/management/commands/import-vat-rates.py b/uncloud_pay/management/commands/import-vat-rates.py
similarity index 100%
rename from uncloud_django_based/uncloud/uncloud_pay/management/commands/import-vat-rates.py
rename to uncloud_pay/management/commands/import-vat-rates.py
diff --git a/uncloud_django_based/uncloud/uncloud_pay/migrations/0001_initial.py b/uncloud_pay/migrations/0001_initial.py
similarity index 100%
rename from uncloud_django_based/uncloud/uncloud_pay/migrations/0001_initial.py
rename to uncloud_pay/migrations/0001_initial.py
diff --git a/uncloud_django_based/uncloud/uncloud_pay/migrations/0002_auto_20200305_1524.py b/uncloud_pay/migrations/0002_auto_20200305_1524.py
similarity index 100%
rename from uncloud_django_based/uncloud/uncloud_pay/migrations/0002_auto_20200305_1524.py
rename to uncloud_pay/migrations/0002_auto_20200305_1524.py
diff --git a/uncloud_django_based/uncloud/uncloud_pay/migrations/0003_auto_20200305_1354.py b/uncloud_pay/migrations/0003_auto_20200305_1354.py
similarity index 100%
rename from uncloud_django_based/uncloud/uncloud_pay/migrations/0003_auto_20200305_1354.py
rename to uncloud_pay/migrations/0003_auto_20200305_1354.py
diff --git a/uncloud_django_based/uncloud/uncloud_pay/migrations/0004_auto_20200409_1225.py b/uncloud_pay/migrations/0004_auto_20200409_1225.py
similarity index 100%
rename from uncloud_django_based/uncloud/uncloud_pay/migrations/0004_auto_20200409_1225.py
rename to uncloud_pay/migrations/0004_auto_20200409_1225.py
diff --git a/uncloud_django_based/uncloud/uncloud_pay/migrations/0005_auto_20200413_0924.py b/uncloud_pay/migrations/0005_auto_20200413_0924.py
similarity index 100%
rename from uncloud_django_based/uncloud/uncloud_pay/migrations/0005_auto_20200413_0924.py
rename to uncloud_pay/migrations/0005_auto_20200413_0924.py
diff --git a/uncloud_django_based/uncloud/uncloud_pay/migrations/0006_auto_20200415_1003.py b/uncloud_pay/migrations/0006_auto_20200415_1003.py
similarity index 100%
rename from uncloud_django_based/uncloud/uncloud_pay/migrations/0006_auto_20200415_1003.py
rename to uncloud_pay/migrations/0006_auto_20200415_1003.py
diff --git a/uncloud_django_based/uncloud/uncloud_pay/migrations/0006_billingaddress.py b/uncloud_pay/migrations/0006_billingaddress.py
similarity index 100%
rename from uncloud_django_based/uncloud/uncloud_pay/migrations/0006_billingaddress.py
rename to uncloud_pay/migrations/0006_billingaddress.py
diff --git a/uncloud_django_based/uncloud/uncloud_pay/migrations/0007_auto_20200418_0737.py b/uncloud_pay/migrations/0007_auto_20200418_0737.py
similarity index 100%
rename from uncloud_django_based/uncloud/uncloud_pay/migrations/0007_auto_20200418_0737.py
rename to uncloud_pay/migrations/0007_auto_20200418_0737.py
diff --git a/uncloud_django_based/uncloud/uncloud_pay/migrations/0008_auto_20200502_1921.py b/uncloud_pay/migrations/0008_auto_20200502_1921.py
similarity index 100%
rename from uncloud_django_based/uncloud/uncloud_pay/migrations/0008_auto_20200502_1921.py
rename to uncloud_pay/migrations/0008_auto_20200502_1921.py
diff --git a/uncloud_django_based/uncloud/uncloud_pay/migrations/0009_auto_20200502_2047.py b/uncloud_pay/migrations/0009_auto_20200502_2047.py
similarity index 100%
rename from uncloud_django_based/uncloud/uncloud_pay/migrations/0009_auto_20200502_2047.py
rename to uncloud_pay/migrations/0009_auto_20200502_2047.py
diff --git a/uncloud_django_based/uncloud/uncloud_pay/migrations/0010_order_description.py b/uncloud_pay/migrations/0010_order_description.py
similarity index 100%
rename from uncloud_django_based/uncloud/uncloud_pay/migrations/0010_order_description.py
rename to uncloud_pay/migrations/0010_order_description.py
diff --git a/uncloud_etcd_based/test/__init__.py b/uncloud_pay/migrations/__init__.py
similarity index 100%
rename from uncloud_etcd_based/test/__init__.py
rename to uncloud_pay/migrations/__init__.py
diff --git a/uncloud_django_based/uncloud/uncloud_pay/models.py b/uncloud_pay/models.py
similarity index 100%
rename from uncloud_django_based/uncloud/uncloud_pay/models.py
rename to uncloud_pay/models.py
diff --git a/uncloud_django_based/uncloud/uncloud_pay/serializers.py b/uncloud_pay/serializers.py
similarity index 100%
rename from uncloud_django_based/uncloud/uncloud_pay/serializers.py
rename to uncloud_pay/serializers.py
diff --git a/uncloud_django_based/uncloud/uncloud_pay/stripe.py b/uncloud_pay/stripe.py
similarity index 100%
rename from uncloud_django_based/uncloud/uncloud_pay/stripe.py
rename to uncloud_pay/stripe.py
diff --git a/uncloud_django_based/uncloud/uncloud_pay/templates/bill.html b/uncloud_pay/templates/bill.html
similarity index 100%
rename from uncloud_django_based/uncloud/uncloud_pay/templates/bill.html
rename to uncloud_pay/templates/bill.html
diff --git a/uncloud_django_based/uncloud/uncloud_pay/templates/error.html.j2 b/uncloud_pay/templates/error.html.j2
similarity index 100%
rename from uncloud_django_based/uncloud/uncloud_pay/templates/error.html.j2
rename to uncloud_pay/templates/error.html.j2
diff --git a/uncloud_django_based/uncloud/uncloud_pay/templates/stripe-payment.html.j2 b/uncloud_pay/templates/stripe-payment.html.j2
similarity index 100%
rename from uncloud_django_based/uncloud/uncloud_pay/templates/stripe-payment.html.j2
rename to uncloud_pay/templates/stripe-payment.html.j2
diff --git a/uncloud_django_based/uncloud/uncloud_pay/tests.py b/uncloud_pay/tests.py
similarity index 100%
rename from uncloud_django_based/uncloud/uncloud_pay/tests.py
rename to uncloud_pay/tests.py
diff --git a/uncloud_django_based/uncloud/uncloud_pay/views.py b/uncloud_pay/views.py
similarity index 100%
rename from uncloud_django_based/uncloud/uncloud_pay/views.py
rename to uncloud_pay/views.py
diff --git a/uncloud_etcd_based/uncloud/cli/__init__.py b/uncloud_service/__init__.py
similarity index 100%
rename from uncloud_etcd_based/uncloud/cli/__init__.py
rename to uncloud_service/__init__.py
diff --git a/uncloud_django_based/uncloud/uncloud_service/admin.py b/uncloud_service/admin.py
similarity index 100%
rename from uncloud_django_based/uncloud/uncloud_service/admin.py
rename to uncloud_service/admin.py
diff --git a/uncloud_django_based/uncloud/uncloud_service/apps.py b/uncloud_service/apps.py
similarity index 100%
rename from uncloud_django_based/uncloud/uncloud_service/apps.py
rename to uncloud_service/apps.py
diff --git a/uncloud_django_based/uncloud/uncloud_service/migrations/0001_initial.py b/uncloud_service/migrations/0001_initial.py
similarity index 100%
rename from uncloud_django_based/uncloud/uncloud_service/migrations/0001_initial.py
rename to uncloud_service/migrations/0001_initial.py
diff --git a/uncloud_django_based/uncloud/uncloud_service/migrations/0002_auto_20200418_0641.py b/uncloud_service/migrations/0002_auto_20200418_0641.py
similarity index 100%
rename from uncloud_django_based/uncloud/uncloud_service/migrations/0002_auto_20200418_0641.py
rename to uncloud_service/migrations/0002_auto_20200418_0641.py
diff --git a/uncloud_etcd_based/uncloud/client/__init__.py b/uncloud_service/migrations/__init__.py
similarity index 100%
rename from uncloud_etcd_based/uncloud/client/__init__.py
rename to uncloud_service/migrations/__init__.py
diff --git a/uncloud_django_based/uncloud/uncloud_service/models.py b/uncloud_service/models.py
similarity index 100%
rename from uncloud_django_based/uncloud/uncloud_service/models.py
rename to uncloud_service/models.py
diff --git a/uncloud_django_based/uncloud/uncloud_service/serializers.py b/uncloud_service/serializers.py
similarity index 100%
rename from uncloud_django_based/uncloud/uncloud_service/serializers.py
rename to uncloud_service/serializers.py
diff --git a/uncloud_django_based/uncloud/uncloud_service/tests.py b/uncloud_service/tests.py
similarity index 100%
rename from uncloud_django_based/uncloud/uncloud_service/tests.py
rename to uncloud_service/tests.py
diff --git a/uncloud_django_based/uncloud/uncloud_service/views.py b/uncloud_service/views.py
similarity index 100%
rename from uncloud_django_based/uncloud/uncloud_service/views.py
rename to uncloud_service/views.py
diff --git a/uncloud_etcd_based/uncloud/configure/__init__.py b/uncloud_storage/__init__.py
similarity index 100%
rename from uncloud_etcd_based/uncloud/configure/__init__.py
rename to uncloud_storage/__init__.py
diff --git a/uncloud_django_based/uncloud/uncloud_storage/admin.py b/uncloud_storage/admin.py
similarity index 100%
rename from uncloud_django_based/uncloud/uncloud_storage/admin.py
rename to uncloud_storage/admin.py
diff --git a/uncloud_django_based/uncloud/uncloud_storage/apps.py b/uncloud_storage/apps.py
similarity index 100%
rename from uncloud_django_based/uncloud/uncloud_storage/apps.py
rename to uncloud_storage/apps.py
diff --git a/uncloud_django_based/uncloud/uncloud_storage/models.py b/uncloud_storage/models.py
similarity index 100%
rename from uncloud_django_based/uncloud/uncloud_storage/models.py
rename to uncloud_storage/models.py
diff --git a/uncloud_django_based/uncloud/uncloud_storage/tests.py b/uncloud_storage/tests.py
similarity index 100%
rename from uncloud_django_based/uncloud/uncloud_storage/tests.py
rename to uncloud_storage/tests.py
diff --git a/uncloud_django_based/uncloud/uncloud_storage/views.py b/uncloud_storage/views.py
similarity index 100%
rename from uncloud_django_based/uncloud/uncloud_storage/views.py
rename to uncloud_storage/views.py
diff --git a/uncloud_etcd_based/uncloud/network/__init__.py b/uncloud_vm/__init__.py
similarity index 100%
rename from uncloud_etcd_based/uncloud/network/__init__.py
rename to uncloud_vm/__init__.py
diff --git a/uncloud_django_based/uncloud/uncloud_vm/admin.py b/uncloud_vm/admin.py
similarity index 100%
rename from uncloud_django_based/uncloud/uncloud_vm/admin.py
rename to uncloud_vm/admin.py
diff --git a/uncloud_django_based/uncloud/uncloud_vm/apps.py b/uncloud_vm/apps.py
similarity index 100%
rename from uncloud_django_based/uncloud/uncloud_vm/apps.py
rename to uncloud_vm/apps.py
diff --git a/uncloud_django_based/uncloud/uncloud_vm/management/commands/vm.py b/uncloud_vm/management/commands/vm.py
similarity index 100%
rename from uncloud_django_based/uncloud/uncloud_vm/management/commands/vm.py
rename to uncloud_vm/management/commands/vm.py
diff --git a/uncloud_django_based/uncloud/uncloud_vm/migrations/0001_initial.py b/uncloud_vm/migrations/0001_initial.py
similarity index 100%
rename from uncloud_django_based/uncloud/uncloud_vm/migrations/0001_initial.py
rename to uncloud_vm/migrations/0001_initial.py
diff --git a/uncloud_django_based/uncloud/uncloud_vm/migrations/0002_auto_20200305_1321.py b/uncloud_vm/migrations/0002_auto_20200305_1321.py
similarity index 100%
rename from uncloud_django_based/uncloud/uncloud_vm/migrations/0002_auto_20200305_1321.py
rename to uncloud_vm/migrations/0002_auto_20200305_1321.py
diff --git a/uncloud_django_based/uncloud/uncloud_vm/migrations/0003_remove_vmhost_vms.py b/uncloud_vm/migrations/0003_remove_vmhost_vms.py
similarity index 100%
rename from uncloud_django_based/uncloud/uncloud_vm/migrations/0003_remove_vmhost_vms.py
rename to uncloud_vm/migrations/0003_remove_vmhost_vms.py
diff --git a/uncloud_django_based/uncloud/uncloud_vm/migrations/0004_remove_vmproduct_vmid.py b/uncloud_vm/migrations/0004_remove_vmproduct_vmid.py
similarity index 100%
rename from uncloud_django_based/uncloud/uncloud_vm/migrations/0004_remove_vmproduct_vmid.py
rename to uncloud_vm/migrations/0004_remove_vmproduct_vmid.py
diff --git a/uncloud_django_based/uncloud/uncloud_vm/migrations/0004_vmproduct_primary_disk.py b/uncloud_vm/migrations/0004_vmproduct_primary_disk.py
similarity index 100%
rename from uncloud_django_based/uncloud/uncloud_vm/migrations/0004_vmproduct_primary_disk.py
rename to uncloud_vm/migrations/0004_vmproduct_primary_disk.py
diff --git a/uncloud_django_based/uncloud/uncloud_vm/migrations/0005_auto_20200309_1258.py b/uncloud_vm/migrations/0005_auto_20200309_1258.py
similarity index 100%
rename from uncloud_django_based/uncloud/uncloud_vm/migrations/0005_auto_20200309_1258.py
rename to uncloud_vm/migrations/0005_auto_20200309_1258.py
diff --git a/uncloud_django_based/uncloud/uncloud_vm/migrations/0005_auto_20200321_1058.py b/uncloud_vm/migrations/0005_auto_20200321_1058.py
similarity index 100%
rename from uncloud_django_based/uncloud/uncloud_vm/migrations/0005_auto_20200321_1058.py
rename to uncloud_vm/migrations/0005_auto_20200321_1058.py
diff --git a/uncloud_django_based/uncloud/uncloud_vm/migrations/0006_auto_20200322_1758.py b/uncloud_vm/migrations/0006_auto_20200322_1758.py
similarity index 100%
rename from uncloud_django_based/uncloud/uncloud_vm/migrations/0006_auto_20200322_1758.py
rename to uncloud_vm/migrations/0006_auto_20200322_1758.py
diff --git a/uncloud_django_based/uncloud/uncloud_vm/migrations/0007_vmhost_vmcluster.py b/uncloud_vm/migrations/0007_vmhost_vmcluster.py
similarity index 100%
rename from uncloud_django_based/uncloud/uncloud_vm/migrations/0007_vmhost_vmcluster.py
rename to uncloud_vm/migrations/0007_vmhost_vmcluster.py
diff --git a/uncloud_django_based/uncloud/uncloud_vm/migrations/0008_auto_20200403_1727.py b/uncloud_vm/migrations/0008_auto_20200403_1727.py
similarity index 100%
rename from uncloud_django_based/uncloud/uncloud_vm/migrations/0008_auto_20200403_1727.py
rename to uncloud_vm/migrations/0008_auto_20200403_1727.py
diff --git a/uncloud_django_based/uncloud/uncloud_vm/migrations/0009_auto_20200417_0551.py b/uncloud_vm/migrations/0009_auto_20200417_0551.py
similarity index 100%
rename from uncloud_django_based/uncloud/uncloud_vm/migrations/0009_auto_20200417_0551.py
rename to uncloud_vm/migrations/0009_auto_20200417_0551.py
diff --git a/uncloud_django_based/uncloud/uncloud_vm/migrations/0009_merge_20200413_0857.py b/uncloud_vm/migrations/0009_merge_20200413_0857.py
similarity index 100%
rename from uncloud_django_based/uncloud/uncloud_vm/migrations/0009_merge_20200413_0857.py
rename to uncloud_vm/migrations/0009_merge_20200413_0857.py
diff --git a/uncloud_django_based/uncloud/uncloud_vm/migrations/0010_auto_20200413_0924.py b/uncloud_vm/migrations/0010_auto_20200413_0924.py
similarity index 100%
rename from uncloud_django_based/uncloud/uncloud_vm/migrations/0010_auto_20200413_0924.py
rename to uncloud_vm/migrations/0010_auto_20200413_0924.py
diff --git a/uncloud_django_based/uncloud/uncloud_vm/migrations/0011_merge_20200418_0641.py b/uncloud_vm/migrations/0011_merge_20200418_0641.py
similarity index 100%
rename from uncloud_django_based/uncloud/uncloud_vm/migrations/0011_merge_20200418_0641.py
rename to uncloud_vm/migrations/0011_merge_20200418_0641.py
diff --git a/uncloud_django_based/uncloud/uncloud_vm/migrations/0012_auto_20200418_0641.py b/uncloud_vm/migrations/0012_auto_20200418_0641.py
similarity index 100%
rename from uncloud_django_based/uncloud/uncloud_vm/migrations/0012_auto_20200418_0641.py
rename to uncloud_vm/migrations/0012_auto_20200418_0641.py
diff --git a/uncloud_django_based/uncloud/uncloud_vm/migrations/0013_remove_vmproduct_primary_disk.py b/uncloud_vm/migrations/0013_remove_vmproduct_primary_disk.py
similarity index 100%
rename from uncloud_django_based/uncloud/uncloud_vm/migrations/0013_remove_vmproduct_primary_disk.py
rename to uncloud_vm/migrations/0013_remove_vmproduct_primary_disk.py
diff --git a/uncloud_etcd_based/uncloud/scheduler/tests/__init__.py b/uncloud_vm/migrations/__init__.py
similarity index 100%
rename from uncloud_etcd_based/uncloud/scheduler/tests/__init__.py
rename to uncloud_vm/migrations/__init__.py
diff --git a/uncloud_django_based/uncloud/uncloud_vm/models.py b/uncloud_vm/models.py
similarity index 100%
rename from uncloud_django_based/uncloud/uncloud_vm/models.py
rename to uncloud_vm/models.py
diff --git a/uncloud_django_based/uncloud/uncloud_vm/serializers.py b/uncloud_vm/serializers.py
similarity index 100%
rename from uncloud_django_based/uncloud/uncloud_vm/serializers.py
rename to uncloud_vm/serializers.py
diff --git a/uncloud_django_based/uncloud/uncloud_vm/tests.py b/uncloud_vm/tests.py
similarity index 100%
rename from uncloud_django_based/uncloud/uncloud_vm/tests.py
rename to uncloud_vm/tests.py
diff --git a/uncloud_django_based/uncloud/uncloud_vm/views.py b/uncloud_vm/views.py
similarity index 100%
rename from uncloud_django_based/uncloud/uncloud_vm/views.py
rename to uncloud_vm/views.py
From 1245c191c0083b92a07861709f00de8f2386bea5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timoth=C3=A9e=20Floure?=
Date: Thu, 7 May 2020 12:13:48 +0200
Subject: [PATCH 023/241] Adapt CI to new structure
---
.gitlab-ci.yml | 2 --
1 file changed, 2 deletions(-)
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index afdc4a1..33c1c06 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -15,8 +15,6 @@ run-tests:
before_script:
- dnf install -y python3-devel python3-pip python3-coverage libpq-devel openldap-devel gcc chromium
script:
- - cd uncloud_django_based/uncloud
- pip install -r requirements.txt
- - cp uncloud/secrets_sample.py uncloud/secrets.py
- coverage run --source='.' ./manage.py test
- coverage report
From b512d42058104931ff77a839e52ccd4b2c05a4b2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timoth=C3=A9e=20Floure?=
Date: Thu, 7 May 2020 12:21:49 +0200
Subject: [PATCH 024/241] Add devel environment setup instructions
---
README.md | 50 ++++++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 48 insertions(+), 2 deletions(-)
diff --git a/README.md b/README.md
index 0e32f57..4ebdd8c 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,49 @@
-# ucloud
+# Uncloud
-Checkout https://ungleich.ch/ucloud/ for the documentation of ucloud.
+Cloud management platform, the ungleich way.
+
+## Development setup
+
+Install system dependencies:
+ * On Fedora, you will need the following packages: `python3-virtualenv python3-devel libpq-devel openldap-devel gcc chromium`
+
+You will need a Postgres database running locally:
+ * Install on configure PGSQL on your base system.
+ * OR use a container! `podman run --rm -p 5432:5432 -e POSTGRES_HOST_AUTH_METHOD=trust -it postgres:latest`
+
+NOTE: you will need to configure a LDAP server and credentials for authentication. See `uncloud/settings.py`.
+
+```
+# Initialize virtualenv.
+» virtualenv .venv
+Using base prefix '/usr'
+New python executable in /home/fnux/Workspace/ungleich/uncloud/uncloud/.venv/bin/python3
+Also creating executable in /home/fnux/Workspace/ungleich/uncloud/uncloud/.venv/bin/python
+Installing setuptools, pip, wheel...
+done.
+
+# Enter virtualenv.
+» source .venv/bin/activate
+
+# Install dependencies.
+» pip install -r requirements.txt
+[...]
+
+# Run migrations.
+» ./manage.py migrate
+Operations to perform:
+ Apply all migrations: admin, auth, contenttypes, opennebula, sessions, uncloud_auth, uncloud_net, uncloud_pay, uncloud_service, uncloud_vm
+Running migrations:
+ [...]
+
+# Run webserver.
+» ./manage.py runserver
+Watching for file changes with StatReloader
+Performing system checks...
+
+System check identified no issues (0 silenced).
+May 07, 2020 - 10:17:08
+Django version 3.0.6, using settings 'uncloud.settings'
+Starting development server at http://127.0.0.1:8000/
+Quit the server with CONTROL-C.
+```
From ebd4e6fa1b06c17ab438a811df31b776be9f5dd0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timoth=C3=A9e=20Floure?=
Date: Thu, 7 May 2020 12:23:17 +0200
Subject: [PATCH 025/241] Add fancy CI badges to README
---
README.md | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/README.md b/README.md
index 4ebdd8c..ea4e87c 100644
--- a/README.md
+++ b/README.md
@@ -2,6 +2,11 @@
Cloud management platform, the ungleich way.
+
+[](https://code.ungleich.ch/uncloud/uncloud/commits/master)
+
+[](https://code.ungleich.ch/uncloud/uncloud/commits/master)
+
## Development setup
Install system dependencies:
From 221d98af4b0f9dcb08e0eff72e381118afe05f04 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timoth=C3=A9e=20Floure?=
Date: Thu, 7 May 2020 12:24:17 +0200
Subject: [PATCH 026/241] Inline CI badges
---
README.md | 1 -
1 file changed, 1 deletion(-)
diff --git a/README.md b/README.md
index ea4e87c..87f3067 100644
--- a/README.md
+++ b/README.md
@@ -4,7 +4,6 @@ Cloud management platform, the ungleich way.
[](https://code.ungleich.ch/uncloud/uncloud/commits/master)
-
[](https://code.ungleich.ch/uncloud/uncloud/commits/master)
## Development setup
From b8ac99acb68740c54bba5a79cc74931385306ab4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timoth=C3=A9e=20Floure?=
Date: Thu, 7 May 2020 12:25:05 +0200
Subject: [PATCH 027/241] On more small commit to fix README formatting
---
README.md | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/README.md b/README.md
index 87f3067..cb5a25f 100644
--- a/README.md
+++ b/README.md
@@ -9,11 +9,13 @@ Cloud management platform, the ungleich way.
## Development setup
Install system dependencies:
- * On Fedora, you will need the following packages: `python3-virtualenv python3-devel libpq-devel openldap-devel gcc chromium`
+
+* On Fedora, you will need the following packages: `python3-virtualenv python3-devel libpq-devel openldap-devel gcc chromium`
You will need a Postgres database running locally:
- * Install on configure PGSQL on your base system.
- * OR use a container! `podman run --rm -p 5432:5432 -e POSTGRES_HOST_AUTH_METHOD=trust -it postgres:latest`
+
+* Install on configure PGSQL on your base system.
+* OR use a container! `podman run --rm -p 5432:5432 -e POSTGRES_HOST_AUTH_METHOD=trust -it postgres:latest`
NOTE: you will need to configure a LDAP server and credentials for authentication. See `uncloud/settings.py`.
From 268e08c4dbe09fcdd1c1dc495e7fadd5ac54d107 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timoth=C3=A9e=20Floure?=
Date: Thu, 7 May 2020 12:31:59 +0200
Subject: [PATCH 028/241] Adapt README for SQLite
---
.gitignore | 1 +
README.md | 15 +++++++++------
2 files changed, 10 insertions(+), 6 deletions(-)
diff --git a/.gitignore b/.gitignore
index cbb171f..ab6a151 100644
--- a/.gitignore
+++ b/.gitignore
@@ -24,3 +24,4 @@ venv/
dist/
*.iso
+*.sqlite3
diff --git a/README.md b/README.md
index cb5a25f..6da7cdb 100644
--- a/README.md
+++ b/README.md
@@ -10,12 +10,7 @@ Cloud management platform, the ungleich way.
Install system dependencies:
-* On Fedora, you will need the following packages: `python3-virtualenv python3-devel libpq-devel openldap-devel gcc chromium`
-
-You will need a Postgres database running locally:
-
-* Install on configure PGSQL on your base system.
-* OR use a container! `podman run --rm -p 5432:5432 -e POSTGRES_HOST_AUTH_METHOD=trust -it postgres:latest`
+* On Fedora, you will need the following packages: `python3-virtualenv python3-devel openldap-devel gcc chromium`
NOTE: you will need to configure a LDAP server and credentials for authentication. See `uncloud/settings.py`.
@@ -53,3 +48,11 @@ Django version 3.0.6, using settings 'uncloud.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.
```
+
+### Note on PGSQL
+
+If you want to use Postgres:
+
+* Install on configure PGSQL on your base system.
+* OR use a container! `podman run --rm -p 5432:5432 -e POSTGRES_HOST_AUTH_METHOD=trust -it postgres:latest`
+
From 718abab9d2ac842f19a08bd4f0f6acf53f2a355c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timoth=C3=A9e=20Floure?=
Date: Thu, 7 May 2020 12:45:06 +0200
Subject: [PATCH 029/241] Add make-admin command to uncloud_auth
---
README.md | 6 +++++-
uncloud_auth/management/commands/make-admin.py | 16 ++++++++++++++++
uncloud_pay/views.py | 4 ++--
3 files changed, 23 insertions(+), 3 deletions(-)
create mode 100644 uncloud_auth/management/commands/make-admin.py
diff --git a/README.md b/README.md
index 6da7cdb..8c53654 100644
--- a/README.md
+++ b/README.md
@@ -6,6 +6,11 @@ Cloud management platform, the ungleich way.
[](https://code.ungleich.ch/uncloud/uncloud/commits/master)
[](https://code.ungleich.ch/uncloud/uncloud/commits/master)
+## Useful commands
+
+* `./manage.py import-vat-rates path/to/csv`
+* `./manage.py make-admin username`
+
## Development setup
Install system dependencies:
@@ -55,4 +60,3 @@ If you want to use Postgres:
* Install on configure PGSQL on your base system.
* OR use a container! `podman run --rm -p 5432:5432 -e POSTGRES_HOST_AUTH_METHOD=trust -it postgres:latest`
-
diff --git a/uncloud_auth/management/commands/make-admin.py b/uncloud_auth/management/commands/make-admin.py
new file mode 100644
index 0000000..b750bc3
--- /dev/null
+++ b/uncloud_auth/management/commands/make-admin.py
@@ -0,0 +1,16 @@
+from django.core.management.base import BaseCommand
+from django.contrib.auth import get_user_model
+import sys
+
+class Command(BaseCommand):
+ help = 'Give Admin rights to existing user'
+
+ def add_arguments(self, parser):
+ parser.add_argument('username', type=str)
+
+ def handle(self, *args, **options):
+ user = get_user_model().objects.get(username=options['username'])
+ user.is_staff = True
+ user.save()
+
+ print("{} is now admin.".format(user.username))
diff --git a/uncloud_pay/views.py b/uncloud_pay/views.py
index 54ff2f0..8bb2280 100644
--- a/uncloud_pay/views.py
+++ b/uncloud_pay/views.py
@@ -243,7 +243,7 @@ class BillingAddressViewSet(mixins.CreateModelMixin,
return Response(serializer.data)
###
-# Old admin stuff.
+# Admin stuff.
class AdminPaymentViewSet(viewsets.ModelViewSet):
serializer_class = PaymentSerializer
@@ -279,7 +279,7 @@ class AdminBillViewSet(viewsets.ModelViewSet):
return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)
class AdminOrderViewSet(viewsets.ModelViewSet):
- permission_classes = [permissions.IsAuthenticated]
+ permission_classes = [permissions.IsAdminUser]
def get_serializer(self, *args, **kwargs):
return OrderSerializer(*args, **kwargs, admin=True)
From 56d98cbb55523739375abc007bc89a96b6c288b8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timoth=C3=A9e=20Floure?=
Date: Thu, 7 May 2020 13:12:38 +0200
Subject: [PATCH 030/241] Implement Orders/Bills permissions, unpaid bill views
---
uncloud_pay/views.py | 34 +++++++++++++++++++++-------------
1 file changed, 21 insertions(+), 13 deletions(-)
diff --git a/uncloud_pay/views.py b/uncloud_pay/views.py
index 8bb2280..bb73cfb 100644
--- a/uncloud_pay/views.py
+++ b/uncloud_pay/views.py
@@ -182,8 +182,13 @@ class BillViewSet(viewsets.ReadOnlyModelViewSet):
def get_queryset(self):
return Bill.objects.filter(owner=self.request.user)
+
+ @action(detail=False, methods=['get'])
def unpaid(self, request):
- return Bill.objects.filter(owner=self.request.user, paid=False)
+ serializer = self.get_serializer(
+ Bill.get_unpaid_for(self.request.user),
+ many=True)
+ return Response(serializer.data)
class OrderViewSet(viewsets.ReadOnlyModelViewSet):
@@ -247,7 +252,7 @@ class BillingAddressViewSet(mixins.CreateModelMixin,
class AdminPaymentViewSet(viewsets.ModelViewSet):
serializer_class = PaymentSerializer
- permission_classes = [permissions.IsAuthenticated]
+ permission_classes = [permissions.IsAdminUser]
def get_queryset(self):
return Payment.objects.all()
@@ -260,25 +265,28 @@ class AdminPaymentViewSet(viewsets.ModelViewSet):
headers = self.get_success_headers(serializer.data)
return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)
-class AdminBillViewSet(viewsets.ModelViewSet):
+# Bills are generated from orders and should not be created or updated by hand.
+class AdminBillViewSet(viewsets.ReadOnlyModelViewSet):
serializer_class = BillSerializer
- permission_classes = [permissions.IsAuthenticated]
+ permission_classes = [permissions.IsAdminUser]
def get_queryset(self):
return Bill.objects.all()
+ @action(detail=False, methods=['get'])
def unpaid(self, request):
- return Bill.objects.filter(owner=self.request.user, paid=False)
+ unpaid_bills = []
+ # XXX: works but we can do better than number of users + 1 SQL requests...
+ for user in get_user_model().objects.all():
+ unpaid_bills = unpaid_bills + Bill.get_unpaid_for(self.request.user)
- def create(self, request):
- serializer = self.get_serializer(data=request.data)
- serializer.is_valid(raise_exception=True)
- serializer.save(creation_date=datetime.now())
+ serializer = self.get_serializer(unpaid_bills, many=True)
+ return Response(serializer.data)
- headers = self.get_success_headers(serializer.data)
- return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)
-
-class AdminOrderViewSet(viewsets.ModelViewSet):
+class AdminOrderViewSet(mixins.ListModelMixin,
+ mixins.RetrieveModelMixin,
+ mixins.CreateModelMixin,
+ viewsets.GenericViewSet):
permission_classes = [permissions.IsAdminUser]
def get_serializer(self, *args, **kwargs):
From 3874165189692604022b11bb3d661edb4d957c3a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timoth=C3=A9e=20Floure?=
Date: Thu, 7 May 2020 14:24:04 +0200
Subject: [PATCH 031/241] Fix bill generation
---
uncloud_pay/models.py | 21 ++++++++++-----------
1 file changed, 10 insertions(+), 11 deletions(-)
diff --git a/uncloud_pay/models.py b/uncloud_pay/models.py
index 1294a54..68016a9 100644
--- a/uncloud_pay/models.py
+++ b/uncloud_pay/models.py
@@ -521,9 +521,8 @@ class Bill(models.Model):
bill_records = []
orders = Order.objects.filter(bill=self)
for order in orders:
- for order_record in order.records:
- bill_record = BillRecord(self, order_record)
- bill_records.append(bill_record)
+ bill_record = BillRecord(self, order)
+ bill_records.append(bill_record)
return bill_records
@@ -710,18 +709,18 @@ class Bill(models.Model):
class BillRecord():
"""
- Entry of a bill, dynamically generated from order records.
+ Entry of a bill, dynamically generated from an order.
"""
- def __init__(self, bill, order_record):
+ def __init__(self, bill, order):
self.bill = bill
- self.order = order_record.order
- self.recurring_price = order_record.recurring_price
- self.recurring_period = order_record.recurring_period
- self.description = order_record.description
+ self.order = order
+ self.recurring_price = order.recurring_price
+ self.recurring_period = order.recurring_period
+ self.description = order.description
if self.order.starting_date >= self.bill.starting_date:
- self.one_time_price = order_record.one_time_price
+ self.one_time_price = order.one_time_price
else:
self.one_time_price = 0
@@ -779,7 +778,7 @@ class BillRecord():
return 0
else:
raise Exception('Unsupported recurring period: {}.'.
- format(record.recurring_period))
+ format(self.order.recurring_period))
@property
def vat_rate(self):
From ae2bad57544ab257e7c7c94e89fa0242fa8be30c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timoth=C3=A9e=20Floure?=
Date: Thu, 7 May 2020 15:38:49 +0200
Subject: [PATCH 032/241] Generate bill PDFs from /my/bill
---
uncloud/urls.py | 1 -
.../0011_billingaddress_organization.py | 19 +++
uncloud_pay/models.py | 1 +
uncloud_pay/serializers.py | 4 +-
.../templates/{bill.html => bill.html.j2} | 156 ++++++------------
uncloud_pay/views.py | 30 ++--
6 files changed, 96 insertions(+), 115 deletions(-)
create mode 100644 uncloud_pay/migrations/0011_billingaddress_organization.py
rename uncloud_pay/templates/{bill.html => bill.html.j2} (96%)
diff --git a/uncloud/urls.py b/uncloud/urls.py
index 05b1f0f..b20f136 100644
--- a/uncloud/urls.py
+++ b/uncloud/urls.py
@@ -81,7 +81,6 @@ urlpatterns = [
path('', include(router.urls)),
# web/ = stuff to view in the browser
- path('web/pdf/', payviews.MyPDFView.as_view(), name='pdf'),
path('api-auth/', include('rest_framework.urls', namespace='rest_framework')), # for login to REST API
path('openapi', get_schema_view(
title="uncloud",
diff --git a/uncloud_pay/migrations/0011_billingaddress_organization.py b/uncloud_pay/migrations/0011_billingaddress_organization.py
new file mode 100644
index 0000000..ac36eee
--- /dev/null
+++ b/uncloud_pay/migrations/0011_billingaddress_organization.py
@@ -0,0 +1,19 @@
+# Generated by Django 3.0.6 on 2020-05-07 13:07
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('uncloud_pay', '0010_order_description'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='billingaddress',
+ name='organization',
+ field=models.CharField(default='', max_length=100),
+ preserve_default=False,
+ ),
+ ]
diff --git a/uncloud_pay/models.py b/uncloud_pay/models.py
index 68016a9..92c58ab 100644
--- a/uncloud_pay/models.py
+++ b/uncloud_pay/models.py
@@ -444,6 +444,7 @@ class BillingAddress(models.Model):
uuid = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
owner = models.ForeignKey(get_user_model(), on_delete=models.CASCADE)
+ organization = models.CharField(max_length=100)
name = models.CharField(max_length=100)
street = models.CharField(max_length=100)
city = models.CharField(max_length=50)
diff --git a/uncloud_pay/serializers.py b/uncloud_pay/serializers.py
index ad50c68..1d7dcdd 100644
--- a/uncloud_pay/serializers.py
+++ b/uncloud_pay/serializers.py
@@ -95,7 +95,7 @@ class BillRecordSerializer(serializers.Serializer):
class BillingAddressSerializer(serializers.ModelSerializer):
class Meta:
model = BillingAddress
- fields = ['uuid', 'name', 'street', 'city', 'postal_code', 'country', 'vat_number']
+ fields = ['uuid', 'organization', 'name', 'street', 'city', 'postal_code', 'country', 'vat_number']
class BillSerializer(serializers.ModelSerializer):
billing_address = BillingAddressSerializer(read_only=True)
@@ -103,7 +103,7 @@ class BillSerializer(serializers.ModelSerializer):
class Meta:
model = Bill
- fields = ['reference', 'owner', 'amount', 'vat_amount', 'total',
+ fields = ['uuid', 'reference', 'owner', 'amount', 'vat_amount', 'total',
'due_date', 'creation_date', 'starting_date', 'ending_date',
'records', 'final', 'billing_address']
diff --git a/uncloud_pay/templates/bill.html b/uncloud_pay/templates/bill.html.j2
similarity index 96%
rename from uncloud_pay/templates/bill.html
rename to uncloud_pay/templates/bill.html.j2
index 8f6c217..0ea7089 100644
--- a/uncloud_pay/templates/bill.html
+++ b/uncloud_pay/templates/bill.html.j2
@@ -26,7 +26,7 @@
- Bill name
+ {{ bill.reference }} | {{ bill.uuid }}
+{% endblock %}
+
+{% block body %}
+
+
Registering Stripe Credit Card
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+{% endblock %}
diff --git a/uncloud_pay/views.py b/uncloud_pay/views.py
index edfb189..53d6ef4 100644
--- a/uncloud_pay/views.py
+++ b/uncloud_pay/views.py
@@ -1,3 +1,7 @@
+from django.contrib.auth.mixins import LoginRequiredMixin
+from django.views.generic.base import TemplateView
+
+
from django.shortcuts import render
from django.db import transaction
from django.contrib.auth import get_user_model
@@ -43,6 +47,25 @@ class OrderViewSet(viewsets.ReadOnlyModelViewSet):
def get_queryset(self):
return Order.objects.filter(owner=self.request.user)
+
+class RegisterCard(LoginRequiredMixin, TemplateView):
+ login_url = '/login/'
+
+ # This is not supposed to be "static" --
+ # the idea is to be able to switch the provider when needed
+ template_name = "uncloud_pay/stripe.html"
+
+ def get_context_data(self, **kwargs):
+ customer_id = uncloud_stripe.get_customer_id_for(self.request.user)
+ setup_intent = uncloud_stripe.create_setup_intent(customer_id)
+
+ context = super().get_context_data(**kwargs)
+ context['client_secret'] = setup_intent.client_secret
+ context['username'] = self.request.user
+ context['stripe_pk'] = uncloud_stripe.public_api_key
+ return context
+
+
class PaymentMethodViewSet(viewsets.ModelViewSet):
permission_classes = [permissions.IsAuthenticated]
From 6efedcb38155598c8c054565ad57a521a47d9de7 Mon Sep 17 00:00:00 2001
From: Nico Schottelius
Date: Fri, 25 Dec 2020 17:29:17 +0100
Subject: [PATCH 175/241] hackish way of registering works
---
uncloud/urls.py | 2 +
uncloud_pay/serializers.py | 12 +-
uncloud_pay/stripe.py | 9 --
uncloud_pay/templates/uncloud_pay/stripe.html | 107 +++++++++++-------
uncloud_pay/views.py | 6 +-
5 files changed, 80 insertions(+), 56 deletions(-)
diff --git a/uncloud/urls.py b/uncloud/urls.py
index 169be7f..9097b4c 100644
--- a/uncloud/urls.py
+++ b/uncloud/urls.py
@@ -86,9 +86,11 @@ urlpatterns = [
# web/ = stuff to view in the browser
# path('web/vpn/create/', netviews.WireGuardVPNCreateView.as_view(), name="vpncreate"),
+
path('login/', authviews.LoginView.as_view(), name="login"),
path('logout/', authviews.LogoutView.as_view(), name="logout"),
path('admin/', admin.site.urls),
path('cc/reg/', payviews.RegisterCard.as_view(), name="cc_register"),
+ path('cc/submit/', payviews.RegisterCard.as_view(), name="cc_register"),
path('', uncloudviews.UncloudIndex.as_view(), name="uncloudindex"),
]
diff --git a/uncloud_pay/serializers.py b/uncloud_pay/serializers.py
index 9214105..94f833e 100644
--- a/uncloud_pay/serializers.py
+++ b/uncloud_pay/serializers.py
@@ -5,6 +5,14 @@ from django.utils.translation import gettext_lazy as _
from .models import *
+###
+# Checked code
+
+
+################################################################################
+# Unchecked code
+
+
###
# Payments and Payment Methods.
@@ -18,7 +26,7 @@ class PaymentMethodSerializer(serializers.ModelSerializer):
class Meta:
model = PaymentMethod
- fields = ['uuid', 'source', 'description', 'primary', 'stripe_card_last4', 'active']
+ fields = [ 'source', 'description', 'primary', 'stripe_card_last4', 'active']
class UpdatePaymentMethodSerializer(serializers.ModelSerializer):
class Meta:
@@ -30,10 +38,12 @@ class ChargePaymentMethodSerializer(serializers.Serializer):
class CreatePaymentMethodSerializer(serializers.ModelSerializer):
please_visit = serializers.CharField(read_only=True)
+
class Meta:
model = PaymentMethod
fields = ['source', 'description', 'primary', 'please_visit']
+
###
# Orders & Products.
diff --git a/uncloud_pay/stripe.py b/uncloud_pay/stripe.py
index 2ed4ef2..f4c467a 100644
--- a/uncloud_pay/stripe.py
+++ b/uncloud_pay/stripe.py
@@ -7,17 +7,10 @@ from django.conf import settings
import uncloud_pay.models
-# Static stripe configuration used below.
CURRENCY = 'chf'
-# README: We use the Payment Intent API as described on
-# https://stripe.com/docs/payments/save-and-reuse
-
-# For internal use only.
stripe.api_key = settings.STRIPE_KEY
-# Helper (decorator) used to catch errors raised by stripe logic.
-# Catch errors that should not be displayed to the end user, raise again.
def handle_stripe_error(f):
def handle_problems(*args, **kwargs):
response = {
@@ -61,8 +54,6 @@ def handle_stripe_error(f):
return handle_problems
-# Actual Stripe logic.
-
def public_api_key():
return settings.STRIPE_PUBLIC_KEY
diff --git a/uncloud_pay/templates/uncloud_pay/stripe.html b/uncloud_pay/templates/uncloud_pay/stripe.html
index 3051bf0..775ed53 100644
--- a/uncloud_pay/templates/uncloud_pay/stripe.html
+++ b/uncloud_pay/templates/uncloud_pay/stripe.html
@@ -1,7 +1,9 @@
+
{% extends 'uncloud/base.html' %}
{% block header %}
+
+
+
{% endblock %}
{% block body %}
-
Registering Stripe Credit Card
+
Registering Credit Card with Stripe
+
+ By submitting I authorise to send instructions to
+ the financial institution that issued my card to take
+ payments from my card account in accordance with the
+ terms of my agreement with you.
+
-
-
-
+
+
+
+
The card will be registered with stripe.
+
-
-
-
-
{% endblock %}
diff --git a/uncloud_pay/views.py b/uncloud_pay/views.py
index 53d6ef4..78a1a15 100644
--- a/uncloud_pay/views.py
+++ b/uncloud_pay/views.py
@@ -51,12 +51,12 @@ class OrderViewSet(viewsets.ReadOnlyModelViewSet):
class RegisterCard(LoginRequiredMixin, TemplateView):
login_url = '/login/'
- # This is not supposed to be "static" --
- # the idea is to be able to switch the provider when needed
template_name = "uncloud_pay/stripe.html"
def get_context_data(self, **kwargs):
+
customer_id = uncloud_stripe.get_customer_id_for(self.request.user)
+
setup_intent = uncloud_stripe.create_setup_intent(customer_id)
context = super().get_context_data(**kwargs)
@@ -159,7 +159,7 @@ class PaymentMethodViewSet(viewsets.ModelViewSet):
# TODO: find a way to use reverse properly:
# https://www.django-rest-framework.org/api-guide/reverse/
callback_path= "payment-method/{}/activate-stripe-cc/".format(
- payment_method.uuid)
+ payment_method.id)
callback = reverse('api-root', request=request) + callback_path
# Render stripe card registration form.
From f7c68b5ca53aa9c01d98da223e7e2aa469b54223 Mon Sep 17 00:00:00 2001
From: Nico Schottelius
Date: Fri, 25 Dec 2020 17:33:01 +0100
Subject: [PATCH 176/241] Rename template
---
.../uncloud_pay/register_stripe.html | 68 ++++++++++++++
uncloud_pay/templates/uncloud_pay/stripe.html | 93 -------------------
uncloud_pay/views.py | 2 +-
3 files changed, 69 insertions(+), 94 deletions(-)
create mode 100644 uncloud_pay/templates/uncloud_pay/register_stripe.html
delete mode 100644 uncloud_pay/templates/uncloud_pay/stripe.html
diff --git a/uncloud_pay/templates/uncloud_pay/register_stripe.html b/uncloud_pay/templates/uncloud_pay/register_stripe.html
new file mode 100644
index 0000000..9fd82ae
--- /dev/null
+++ b/uncloud_pay/templates/uncloud_pay/register_stripe.html
@@ -0,0 +1,68 @@
+{% extends 'uncloud/base.html' %}
+
+{% block header %}
+
+
+
+{% endblock %}
+
+{% block body %}
+
+
Register Credit Card with Stripe
+
+ By submitting I authorise to send instructions to
+ the financial institution that issued my card to take
+ payments from my card account in accordance with the
+ terms of my agreement with you.
+
- By submitting I authorise to send instructions to
- the financial institution that issued my card to take
- payments from my card account in accordance with the
- terms of my agreement with you.
-
Register a credit card
+ (this is required to be done via Javascript so that we never see
+ your credit card, but it is sent directly to stripe)
+
+ You can list your credit card via the API.
+
Register a credit card
- (this is required to be done via Javascript so that we never see
- your credit card, but it is sent directly to stripe)
- You can list your credit card via the API.
+
+
Credit cards
+
+ Credit cards are registered with stripe. We only save a the
+ last 4 digits and the expiry date of the card to make
+ identification for you easier.
+
+
+
+
Register a credit card
+ (this is required to be done via Javascript so that we never see
+ your credit card, but it is sent directly to stripe)
+
You can list your
+ credit cards
+ By default the first credit card is used for charging
+ ("active: true") and later added cards will not be
+ used. To change this, first disable the active flag and
+ then set it on another credit card.
+
uncloud is designed to be as easy as possible to use. However,
+ there are some "real world" requirements that need to be met to
+ start using uncloud:
-
If you have forgotten your password or other issues with
+ logging in, you can contact the ungleich support
+ via support at ungleich.ch.
+
+
Secondy you will need to
+ create a billing
+ address. This is required for determining the correct
+ tax.
+
Next you will need to
+ register a credit card
+ from which payments can be made. Your credit card will not
+ be charged without your consent.
+
+
+
+
+
+
Credit cards
+
+
Credit cards are registered with stripe. We only save a the
last 4 digits and the expiry date of the card to make
identification for you easier.
-
-
-
-
Register a credit card
- (this is required to be done via Javascript so that we never see
- your credit card, but it is sent directly to stripe)
-
You can list your
- credit cards
- By default the first credit card is used for charging
- ("active: true") and later added cards will not be
- used. To change this, first disable the active flag and
- then set it on another credit card.
-
Register a credit card
+ (this is required to be done via Javascript so that we never see
+ your credit card, but it is sent directly to stripe)
+
You can list your
+ credit cards
+ By default the first credit card is used for charging
+ ("active: true") and later added cards will not be
+ used. To change this, first disable the active flag and
+ then set it on another credit card.
+
-
-
Networking
- With uncloud you can use a variety of network related services.
+
+
Billing Address, Payments and Balance
+
+
Billing addresses behave similar to credit cards: you can
+ have many of them, but only one can be active. The active
+ billing address is taken for creating new orders.
+
+
In uncloud we use the pre-paid model: you can add money to
+ your account via payments. You can always check your
+ balance. The products you use will automatically be charged from
+ your existing balance.
+
+
+
In the future you will be able opt-in to automatically
+ recharging your account at a certain time frame or whenever it
+ is below a certain amount
+ Welcome to uncloud, the Open Source cloud management
+ system by ungleich.
+ It is an API driven system with
+ some convience views provided by
+ the Django Rest
+ Framework. You can
+ freely access
+ the source code of uncloud.
+ This is a BETA service. As such, some
+ functionality might not be very sophisticated.
+
+
-
-
-
Getting started
-
-
uncloud is designed to be as easy as possible to use. However,
- there are some "real world" requirements that need to be met to
- start using uncloud:
+
+
Getting started
+
+
uncloud is designed to be as easy as possible to use. However,
+ there are some "real world" requirements that need to be met to
+ start using uncloud:
-
If you have forgotten your password or other issues with
+ logging in, you can contact the ungleich support
+ via support at ungleich.ch.
-
Secondy you will need to
- create a billing
- address. This is required for determining the correct
- tax.
-
Next you will need to
- register a credit card
- from which payments can be made. Your credit card will not
- be charged without your consent.
-
+
Secondy you will need to
+ create a billing
+ address. This is required for determining the correct
+ tax.
+
Next you will need to
+ register a credit card
+ from which payments can be made. Your credit card will not
+ be charged without your consent.
+
+
-
-
-
-
Credit cards
-
-
- Credit cards are registered with stripe. We only save a the
- last 4 digits and the expiry date of the card to make
- identification for you easier.
-
-
-
Register a credit card
- (this is required to be done via Javascript so that we never see
- your credit card, but it is sent directly to stripe)
-
You can list your
- credit cards
- By default the first credit card is used for charging
- ("active: true") and later added cards will not be
- used. To change this, first disable the active flag and
- then set it on another credit card.
+
+
Introduction to uncloud concepts
+
+
We plan to offer many services on uncloud ranging from
+ for free, for a small amount or regular charges. As transfer
+ fees are a major challenge for our business, we based uncloud
+ on the pre-paid account model. Which means
+ that you can charge your account and then use your balance to
+ pay for product usage.
+
-
-
-
Billing Address, Payments and Balance
-
-
Billing addresses behave similar to credit cards: you can
- have many of them, but only one can be active. The active
- billing address is taken for creating new orders.
-
In uncloud we use the pre-paid model: you can add money to
- your account via payments. You can always check your
- balance. The products you use will automatically be charged from
- your existing balance.
-
-
-
In the future you will be able opt-in to automatically
- recharging your account at a certain time frame or whenever it
- is below a certain amount
+ Credit cards are registered with stripe. We only save a the
+ last 4 digits and the expiry date of the card to make
+ identification for you easier.
+
+
+
Register a credit card
+ (this is required to be done via Javascript so that we never see
+ your credit card, but it is sent directly to stripe)
+
You can list your
+ credit cards
+ By default the first credit card is used for charging
+ ("active: true") and later added cards will not be
+ used. To change this, first disable the active flag and
+ then set it on another credit card.
+
-
+
+
Billing Address, Payments and Balance
+
+
Billing addresses behave similar to credit cards: you can
+ have many of them, but only one can be active. The active
+ billing address is taken for creating new orders.
-
-
Networking
-
-
- With uncloud you can use a variety of network related
- services.
-
+
In uncloud we use the pre-paid model: you can add money to
+ your account via payments. You can always check your
+ balance. The products you use will automatically be charged from
+ your existing balance.
+
- By submitting I authorise to send instructions to
- the financial institution that issued my card to take
- payments from my card account in accordance with the
+{% block bootstrap5_content %}
+
+
+
+
Register Credit Card with Stripe
+
+ By submitting I authorise to send instructions to
+ the financial institution that issued my card to take
+ payments from my card account in accordance with the
terms of my agreement with you.
-
{% endblock %}
diff --git a/uncloud_pay/templates/uncloud_pay/register_stripe.html b/uncloud_pay/templates/uncloud_pay/register_stripe.html
index 7205261..9613701 100644
--- a/uncloud_pay/templates/uncloud_pay/register_stripe.html
+++ b/uncloud_pay/templates/uncloud_pay/register_stripe.html
@@ -13,12 +13,15 @@
By submitting I authorise to send instructions to
the financial institution that issued my card to take
payments from my card account in accordance with the
- terms of my agreement with you.
+ terms of my agreement with you.
+
+
+
+
+ {% for message in messages %}
+ {% if 'vat_error' in message.tags %}
+
+ {{ message|safe }}
+
+ {% endif %}
+ {% endfor %}
+
+
+
+
+
+
+
+ {% with cards_len=cards|length %}
+
{%trans "Credit Card"%}
+
+
+ {% if cards_len > 0 %}
+ {% blocktrans %}Please select one of the cards that you used before or fill in your credit card information below. We are using Stripe for payment and do not store your information in our database.{% endblocktrans %}
+ {% else %}
+ {% blocktrans %}Please fill in your credit card information below. We are using Stripe for payment and do not store your information in our database.{% endblocktrans %}
+ {% endif %}
+
+
+ {% for card in cards %}
+
+
+
{% trans "Credit Card" %}
+
{% trans "Last" %} 4: ***** {{card.last4}}
+
{% trans "Type" %}: {{card.brand}}
+
{% trans "Expiry" %}: {{card.month}}/{{card.year}}
If you have forgotten your password or other issues with
logging in, you can contact the ungleich support
via support at ungleich.ch.
@@ -107,8 +107,11 @@