- Select VM:
+ Select VM Template:
{{ order.id }} |
{{ order.created_at }} |
- {{ order.vm_plan.price }} CHF |
+ {{ order.price }} CHF |
{% if order.approved %}
{% trans "Approved"%}
{% else %}
@@ -99,4 +99,4 @@
-{% endblock %}
\ No newline at end of file
+{% endblock %}
diff --git a/hosting/templates/hosting/payment.html b/hosting/templates/hosting/payment.html
index bb80d566..459dcf0b 100644
--- a/hosting/templates/hosting/payment.html
+++ b/hosting/templates/hosting/payment.html
@@ -100,14 +100,17 @@
- Cores {{request.session.template.cores}}
+ Cores {{request.session.specs.cpu|floatformat}}
- Memory {{request.session.template.memory}} GiB
+ Memory {{request.session.specs.memory|floatformat}} GiB
- Disk space {{request.session.template.disk_size}} GiB
+ Disk space {{request.session.specs.disk_size|floatformat}} GiB
Total{{request.session.template.price }} CHF
+ class="pull-right"> {{request.session.specs.price }} CHF
diff --git a/hosting/views.py b/hosting/views.py
index a40e14b9..b1f993ee 100644
--- a/hosting/views.py
+++ b/hosting/views.py
@@ -25,14 +25,13 @@ from utils.stripe_utils import StripeUtils
from utils.forms import BillingAddressForm, PasswordResetRequestForm, UserBillingAddressForm
from utils.views import PasswordResetViewMixin, PasswordResetConfirmViewMixin, LoginViewMixin
from utils.mailer import BaseEmail
-from .models import HostingOrder, HostingBill, UserHostingKey
+from .models import HostingOrder, HostingBill, HostingPlan, UserHostingKey
from .forms import HostingUserSignupForm, HostingUserLoginForm, UserHostingKeyForm
from .mixins import ProcessVMSelectionMixin
from opennebula_api.models import OpenNebulaManager
from opennebula_api.serializers import VirtualMachineSerializer,\
- VirtualMachineTemplateSerializer,\
- ImageSerializer
+ VirtualMachineTemplateSerializer
from oca.exceptions import OpenNebulaException
@@ -407,12 +406,12 @@ class PaymentVMView(LoginRequiredMixin, FormView):
context = self.get_context_data()
- specifications = request.session.get('template')
+ template = request.session.get('template')
+ specs = request.session.get('specs')
- vm_template_id = specifications.get('id', 1)
- vm_image_id = request.session.get('image').get('id', 1)
+ vm_template_id = template.get('id', 1)
- final_price = specifications.get('price', 1)
+ final_price = specs.get('price')
token = form.cleaned_data.get('token')
@@ -455,12 +454,14 @@ class PaymentVMView(LoginRequiredMixin, FormView):
except UserHostingKey.DoesNotExist:
pass
+
# Create a vm using logged user
vm_id = manager.create_vm(
template_id=vm_template_id,
+ #XXX: Confi
+ specs=specs,
ssh_key=user_key.public_key,
- image_id=vm_image_id,
)
# Create a Hosting Order
@@ -587,11 +588,11 @@ class CreateVirtualMachinesView(LoginRequiredMixin, View):
manager = OpenNebulaManager()
templates = manager.get_templates()
- images = manager.get_images()
+ configuration_options = HostingPlan.get_serialized_configs()
context = {
'templates': VirtualMachineTemplateSerializer(templates, many=True).data,
- 'images' : ImageSerializer(images, many=True).data
+ 'configuration_options' : configuration_options,
}
return render(request, self.template_name, context)
@@ -599,10 +600,11 @@ class CreateVirtualMachinesView(LoginRequiredMixin, View):
manager = OpenNebulaManager()
template_id = request.POST.get('vm_template_id')
template = manager.get_template(template_id)
- image_id = request.POST.get('vm_image_id')
- image = manager.get_image(image_id)
+ configuration_id = int(request.POST.get('configuration'))
+ configuration = HostingPlan.objects.get(id=configuration_id)
request.session['template'] = VirtualMachineTemplateSerializer(template).data
- request.session['image'] = ImageSerializer(image).data
+
+ request.session['specs'] = configuration.serialize()
return redirect(reverse('hosting:payment'))
@@ -715,6 +717,10 @@ class HostingBillDetailView(PermissionRequiredMixin, LoginRequiredMixin, DetailV
# Get vms
queryset = manager.get_vms()
vms = VirtualMachineSerializer(queryset, many=True).data
+ # Set total price
+ bill = context['bill']
+ bill.total_price = 0.0
+ for vm in vms:
+ bill.total_price += vm['price']
context['vms'] = vms
-
return context
diff --git a/opennebula_api/models.py b/opennebula_api/models.py
index f543d0ec..eb6d64a2 100644
--- a/opennebula_api/models.py
+++ b/opennebula_api/models.py
@@ -109,37 +109,64 @@ class OpenNebulaManager():
except:
return None
- def create_vm(self, template_id, image_id=None, ssh_key=None):
- extra_template_formater = """
- {ssh_key}
-
-
- {image_id}
-
- """
+ def create_template(self, name, cores, memory, disk_size, core_price, memory_price,
+ disk_size_price, ssh='' ):
+ """Create and add a new template to opennebula.
+ :param name: A string representation describing the template.
+ Used as label in view.
+ :param cores: Amount of virtual cpu cores for the VM.
+ :param memory: Amount of RAM for the VM (GB)
+ :param disk_size: Amount of disk space for VM (GB)
+ :param core_price: Price of virtual cpu for the VM per core.
+ :param memory_price: Price of RAM for the VM per GB
+ :param disk_size_price: Price of disk space for VM per GB
+ :param ssh: User public ssh key
+ """
+
+ template_id = oca.VmTemplate.allocate(
+ self.oneadmin_client,
+ template_string_formatter.format(
+ name=name,
+ vcpu=cores,
+ cpu=0.1*cores,
+ size=1024 * disk_size,
+ memory=1024 * memory,
+ # * 10 because we set cpu to *0.1
+ cpu_cost=10*core_price,
+ memory_cost=memory_price,
+ disk_cost=disk_size_price,
+ ssh=ssh
+ )
+ )
+
+ def create_vm(self, template_id, specs, ssh_key=None):
template = self.get_template(template_id)
- vm_id = template.instantiate(name ='', pending=False, extra_template='')
- image = self.get_image(image_id)
+ vm_specs_formatter = """
+ {memory}
+ {vcpu}
+ {cpu}
+
+ fs
+ {size}
+ vd
+
+
+ {ssh}
+
+
+ """
+ vm_id = template.instantiate(name ='',
+ pending=False,
+ extra_template=vm_specs_formatter.format(
+ vcpu=int(specs['cpu']),
+ cpu=0.1* int(specs['cpu']),
+ size=1024 * int(specs['disk_size']),
+ memory=1024 * int(specs['memory']),
+ ssh=ssh_key
+ )
+ )
- image_name = "{image_name}{template_name}{vm_id}".format(
- image_name=image.name,
- template_name=template.name,
- vm_id = vm_id,
- )
-
- image_id = image.clone(name=image_name)
-
- self.oneadmin_client.call(
- oca.VmTemplate.METHODS['update'],
- vm_id,
- extra_template_formater.format(
- ssh_key=ssh_key,
- image_id=image_id
- ),
- # 0 = Replace / 1 = Merge
- 1,
- )
try:
self.oneadmin_client.call(
oca.VirtualMachine.METHODS['chown'],
@@ -176,7 +203,6 @@ class OpenNebulaManager():
try:
template_pool = oca.VmTemplatePool(self.oneadmin_client)
template_pool.info()
- #TODO: Replace with logger
except ConnectionRefusedError:
logger.info('Could not connect to host: {host} via protocol {protocol}'.format(
host=settings.OPENNEBULA_DOMAIN,
@@ -262,38 +288,3 @@ class OpenNebulaManager():
self.opennebula_user.id,
new_password
)
-
-
- def _get_image_pool(self):
- try:
- image_pool = oca.ImagePool(self.oneadmin_client)
- image_pool.info()
- #TODO: Replace with logger
- except ConnectionRefusedError:
- logger.info('Could not connect to host: {host} via protocol {protocol}'.format(
- host=settings.OPENNEBULA_DOMAIN,
- protocol=settings.OPENNEBULA_PROTOCOL)
- )
- raise ConnectionRefusedError
- return image_pool
-
- def get_images(self):
- try:
- public_images = [
- image
- for image in self._get_image_pool()
- if 'public-' in image.name
- ]
- return public_images
- except ConnectionRefusedError:
- return []
- pass
-
- def get_image(self, image_id):
- image_id = int(image_id)
- try:
- image_pool = self._get_image_pool()
- return image_pool.get_by_id(image_id)
- except:
- return None
-
diff --git a/opennebula_api/serializers.py b/opennebula_api/serializers.py
index 86da2f0b..600f6fc3 100644
--- a/opennebula_api/serializers.py
+++ b/opennebula_api/serializers.py
@@ -10,10 +10,12 @@ from .models import OpenNebulaManager
class VirtualMachineTemplateSerializer(serializers.Serializer):
"""Serializer to map the virtual machine template instance into JSON format."""
id = serializers.IntegerField(read_only=True)
- name = serializers.CharField()
+ set_name = serializers.CharField(read_only=True, label='Name')
+ name = serializers.SerializerMethodField()
cores = serializers.IntegerField(source='template.vcpu')
disk = serializers.IntegerField(write_only=True)
disk_size = serializers.SerializerMethodField()
+ set_memory = serializers.IntegerField(write_only=True, label='Memory')
memory = serializers.SerializerMethodField()
core_price = serializers.FloatField(source='template.cpu_cost')
disk_size_price = serializers.FloatField(source='template.disk_cost')
@@ -63,20 +65,28 @@ class VirtualMachineTemplateSerializer(serializers.Serializer):
def get_memory(self, obj):
return int(obj.template.memory)/1024
+ def get_name(self, obj):
+ # TODO: Filter public- away
+ return obj.name
+
class VirtualMachineSerializer(serializers.Serializer):
"""Serializer to map the virtual machine instance into JSON format."""
name = serializers.CharField(read_only=True)
- cores = serializers.IntegerField(read_only=True, source='template.vcpu')
+ cores = serializers.IntegerField(source='template.vcpu')
+ disk = serializers.IntegerField(write_only=True)
+ set_memory = serializers.IntegerField(write_only=True, label='Memory')
+ memory = serializers.SerializerMethodField()
+
disk_size = serializers.SerializerMethodField()
- memory = serializers.SerializerMethodField()
ip = serializers.CharField(read_only=True,
source='user_template.ungleich_public_ip',
default='-')
vm_id = serializers.IntegerField(read_only=True, source='id')
state = serializers.CharField(read_only=True, source='str_state')
price = serializers.SerializerMethodField()
+ ssh_key = serializers.CharField(write_only=True)
template_id = serializers.ChoiceField(
choices=[(key.id, key.name) for key in
@@ -87,13 +97,26 @@ class VirtualMachineSerializer(serializers.Serializer):
def create(self, validated_data):
owner = validated_data['owner']
+ ssh_key = validated_data['ssh_key']
+ cores = validated_data['template']['vcpu']
+ memory = validated_data['set_memory']
+ disk = validated_data['disk']
+
template_id = validated_data['template']['template_id']
+ specs = {
+ 'cpu' : cores,
+ 'disk_size' : disk,
+ 'memory' : memory,
+ }
+
try:
manager = OpenNebulaManager(email=owner.email,
password=owner.password,
)
- opennebula_id = manager.create_vm(template_id)
+ opennebula_id = manager.create_vm(template_id=template_id,
+ ssh_key=ssh_key,
+ specs=specs)
except OpenNebulaException as err:
raise serializers.ValidationError("OpenNebulaException occured. {0}".format(err))
@@ -116,9 +139,3 @@ class VirtualMachineSerializer(serializers.Serializer):
for disk in template.disks:
price += int(disk.size)/1024 * float(template.disk_cost)
return price
-
-class ImageSerializer(serializers.Serializer):
- """Serializer to map the image instance into JSON format."""
- id = serializers.IntegerField(read_only=True)
- name = serializers.CharField()
-
|