From b8df86342adb0bd8aff8b2ae18f8b0e03e71339c Mon Sep 17 00:00:00 2001 From: Modulos Date: Sun, 14 May 2017 01:02:22 +0200 Subject: [PATCH 01/11] Add try and except for template disks It turns out that some templates don't need a disk size if they use a image. --- opennebula_api/serializers.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/opennebula_api/serializers.py b/opennebula_api/serializers.py index 600f6fc3..17793178 100644 --- a/opennebula_api/serializers.py +++ b/opennebula_api/serializers.py @@ -50,9 +50,12 @@ class VirtualMachineTemplateSerializer(serializers.Serializer): def get_disk_size(self, obj): template = obj.template disk_size = 0 - for disk in template.disks: - disk_size += int(disk.size) - return disk_size / 1024 + try: + for disk in template.disks: + disk_size += int(disk.size) + return disk_size / 1024 + except: + return 0 def get_price(self, obj): template = obj.template From f80496a10390c806101f85a162303e4ec8abd56f Mon Sep 17 00:00:00 2001 From: Modulos Date: Sun, 14 May 2017 01:21:10 +0200 Subject: [PATCH 02/11] Quick fix remove cpu_cost etc. --- opennebula_api/serializers.py | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/opennebula_api/serializers.py b/opennebula_api/serializers.py index 17793178..48cdd7b6 100644 --- a/opennebula_api/serializers.py +++ b/opennebula_api/serializers.py @@ -17,9 +17,6 @@ class VirtualMachineTemplateSerializer(serializers.Serializer): 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') - memory_price = serializers.FloatField(source='template.memory_cost') price = serializers.SerializerMethodField() def create(self, validated_data): @@ -30,9 +27,6 @@ class VirtualMachineTemplateSerializer(serializers.Serializer): name = data.pop('name') disk_size = data.pop('disk') memory = template.pop('memory') - core_price = template.pop('cpu_cost') - memory_price = template.pop('memory_cost') - disk_size_price = template.pop('disk_cost') manager = OpenNebulaManager() try: @@ -57,12 +51,16 @@ class VirtualMachineTemplateSerializer(serializers.Serializer): except: return 0 + def get_price(self, obj): template = obj.template - price = float(template.cpu) * float(template.cpu_cost) - price += (int(template.memory)/1024 * float(template.memory_cost)) - for disk in template.disks: - price += int(disk.size)/1024 * float(template.disk_cost) + price = float(template.cpu) * 5.0 + price += (int(template.memory)/1024 * 2.0) + try: + for disk in template.disks: + price += int(disk.size)/1024 * 0.6 + except: + pass return price def get_memory(self, obj): @@ -137,8 +135,8 @@ class VirtualMachineSerializer(serializers.Serializer): def get_price(self, obj): template = obj.template - price = float(template.cpu) * float(template.cpu_cost) - price += (int(template.memory)/1024 * float(template.memory_cost)) + price = float(template.cpu) * 5.0 + price += (int(template.memory)/1024 * 2.0) for disk in template.disks: - price += int(disk.size)/1024 * float(template.disk_cost) + price += int(disk.size)/1024 * 0.6 return price From 46b918d175791f7927a04dd1a2a370513edbeff3 Mon Sep 17 00:00:00 2001 From: Modulos Date: Sun, 14 May 2017 02:17:48 +0200 Subject: [PATCH 03/11] Fix price calculation --- hosting/models.py | 2 +- opennebula_api/serializers.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/hosting/models.py b/hosting/models.py index f8f180a5..25f852f1 100644 --- a/hosting/models.py +++ b/hosting/models.py @@ -41,7 +41,7 @@ class HostingPlan(models.Model): for cfg in cls.objects.all()] def price(self): - price = self.disk_size * 0.2 + price = self.disk_size * 0.6 price += self.cpu_cores * 5 price += self.memory * 2 return price diff --git a/opennebula_api/serializers.py b/opennebula_api/serializers.py index 48cdd7b6..44b873a5 100644 --- a/opennebula_api/serializers.py +++ b/opennebula_api/serializers.py @@ -135,7 +135,7 @@ class VirtualMachineSerializer(serializers.Serializer): def get_price(self, obj): template = obj.template - price = float(template.cpu) * 5.0 + price = float(template.vcpu) * 5.0 price += (int(template.memory)/1024 * 2.0) for disk in template.disks: price += int(disk.size)/1024 * 0.6 From 921fa209ce567ed2775002b80ad52ae5cac5acba Mon Sep 17 00:00:00 2001 From: Modulos Date: Sun, 14 May 2017 02:18:16 +0200 Subject: [PATCH 04/11] Merge image into template --- opennebula_api/models.py | 56 ++++++++++++++++++++++++++++++---------- 1 file changed, 43 insertions(+), 13 deletions(-) diff --git a/opennebula_api/models.py b/opennebula_api/models.py index eb6d64a2..e225ce0f 100644 --- a/opennebula_api/models.py +++ b/opennebula_api/models.py @@ -146,26 +146,56 @@ class OpenNebulaManager(): {memory} {vcpu} {cpu} - + + {ssh} + + """ + try: + disk = template.template.disks[0] + image_id = disk.image_id + vm_specs = vm_specs_formatter.format( + vcpu=int(specs['cpu']), + cpu=0.1* int(specs['cpu']), + memory=1024 * int(specs['memory']), + ssh=ssh_key + + ) + vm_specs += """ fs {size} vd - - - {ssh} - - - """ - vm_id = template.instantiate(name ='', - pending=False, - extra_template=vm_specs_formatter.format( + {image_id} + + + """.format(size=1024 * int(specs['disk_size']), + image_id=image_id) + + except: + disk = template.template.disks[0] + image = disk.image + image_uname = disk.image_uname + + vm_specs = 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 - ) - ) + + ) + vm_specs += """ + fs + {size} + vd + {image} + {image_uname} + + + """.format(size=1024 * int(specs['disk_size']), + image=image, + image_uname=image_uname) + vm_id = template.instantiate(name ='', + pending=False, + extra_template=vm_specs, ) try: self.oneadmin_client.call( From 8a18c275c38ed866134d4922529024caf90d1dd1 Mon Sep 17 00:00:00 2001 From: Modulos Date: Sun, 14 May 2017 03:41:30 +0200 Subject: [PATCH 05/11] Display configuration in virtualmachine detail --- hosting/templates/hosting/virtual_machine_detail.html | 2 +- opennebula_api/serializers.py | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/hosting/templates/hosting/virtual_machine_detail.html b/hosting/templates/hosting/virtual_machine_detail.html index e2f38d60..0b17878d 100644 --- a/hosting/templates/hosting/virtual_machine_detail.html +++ b/hosting/templates/hosting/virtual_machine_detail.html @@ -87,7 +87,7 @@
- {% trans "Configuration"%}: {{virtual_machine.get_configuration_display}} + {% trans "Configuration"%}: {{virtual_machine.configuration}}
diff --git a/opennebula_api/serializers.py b/opennebula_api/serializers.py index 44b873a5..34e122d1 100644 --- a/opennebula_api/serializers.py +++ b/opennebula_api/serializers.py @@ -88,6 +88,7 @@ class VirtualMachineSerializer(serializers.Serializer): state = serializers.CharField(read_only=True, source='str_state') price = serializers.SerializerMethodField() ssh_key = serializers.CharField(write_only=True) + configuration = serializers.SerializerMethodField() template_id = serializers.ChoiceField( choices=[(key.id, key.name) for key in @@ -140,3 +141,7 @@ class VirtualMachineSerializer(serializers.Serializer): for disk in template.disks: price += int(disk.size)/1024 * 0.6 return price + def get_configuration(self, obj): + template_id = obj.template.template_id + template = OpenNebulaManager().get_template(template_id) + return template.name From 05e19ffb68eafda6cd76327b86940ade7f1452b6 Mon Sep 17 00:00:00 2001 From: "M.Ravi" Date: Sun, 14 May 2017 15:36:11 +0530 Subject: [PATCH 06/11] Created url for buy button on datacenterlight home page and redirection of ^hosting/ endpoint to take to hosting app's login page. --- datacenterlight/templates/datacenterlight/index.html | 2 +- dynamicweb/urls.py | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/datacenterlight/templates/datacenterlight/index.html b/datacenterlight/templates/datacenterlight/index.html index 2efe15cb..4d90769c 100755 --- a/datacenterlight/templates/datacenterlight/index.html +++ b/datacenterlight/templates/datacenterlight/index.html @@ -231,7 +231,7 @@

2 GiB RAM,

{% trans "15 GiB storage(SSD)" %}

- {% trans "Buy Now!" %} {% trans "More Info" %}

+ {% trans "Buy Now!" %} {% trans "More Info" %}

diff --git a/dynamicweb/urls.py b/dynamicweb/urls.py index adbe0242..0b1a0844 100644 --- a/dynamicweb/urls.py +++ b/dynamicweb/urls.py @@ -8,6 +8,8 @@ from django.conf import settings from hosting.views import RailsHostingView, DjangoHostingView, NodeJSHostingView from membership import urls as membership_urls from ungleich_page.views import LandingView +from django.views.generic import RedirectView +from django.core.urlresolvers import reverse_lazy import debug_toolbar urlpatterns = [ url(r'^index.html$', LandingView.as_view()), @@ -28,6 +30,7 @@ urlpatterns += i18n_patterns('', url(r'^/?$', LandingView.as_view()), url(r'^admin/', include(admin.site.urls)), url(r'^datacenterlight', include('datacenterlight.urls', namespace="datacenterlight")), + url(r'^hosting/', RedirectView.as_view(url=reverse_lazy('hosting:login')), name='redirect_hosting_login'), url(r'^alplora', include('alplora.urls', namespace="alplora")), url(r'^membership/', include(membership_urls)), url(r'^digitalglarus/', include('digitalglarus.urls', From 1e2b8b1652bb54e75ce71127ab859b776b5b286a Mon Sep 17 00:00:00 2001 From: Modulos Date: Sun, 14 May 2017 12:22:10 +0200 Subject: [PATCH 07/11] Add connection error handling --- .../hosting/create_virtual_machine.html | 13 ++- .../templates/hosting/virtual_machines.html | 11 ++- hosting/views.py | 80 +++++++++++++++---- opennebula_api/models.py | 25 ++++-- opennebula_api/serializers.py | 6 +- 5 files changed, 106 insertions(+), 29 deletions(-) diff --git a/hosting/templates/hosting/create_virtual_machine.html b/hosting/templates/hosting/create_virtual_machine.html index 67a61ead..af618740 100644 --- a/hosting/templates/hosting/create_virtual_machine.html +++ b/hosting/templates/hosting/create_virtual_machine.html @@ -5,9 +5,19 @@
+
+
+ {% if messages %} +
+ {% for message in messages %} + {{ message }} + {% endfor %} +
+ {% endif %} +
+ {% if not error %}

{% trans "New Virtual Machine"%}


-
{% csrf_token %}
@@ -34,6 +44,7 @@
+ {% endif %}
diff --git a/hosting/templates/hosting/virtual_machines.html b/hosting/templates/hosting/virtual_machines.html index 2387f89d..e7dee999 100644 --- a/hosting/templates/hosting/virtual_machines.html +++ b/hosting/templates/hosting/virtual_machines.html @@ -7,10 +7,6 @@

{% trans "Virtual Machines"%}

-

- {% trans "Create VM"%} -

-

{% if messages %} @@ -21,6 +17,12 @@
{% endif %} + {% if not error %} +

+ {% trans "Create VM"%} +

+
+ @@ -53,6 +55,7 @@ {% endfor %}
{% trans "ID"%}
+ {% endif %} {% if is_paginated %}
diff --git a/dynamicweb/urls.py b/dynamicweb/urls.py index adbe0242..0b1a0844 100644 --- a/dynamicweb/urls.py +++ b/dynamicweb/urls.py @@ -8,6 +8,8 @@ from django.conf import settings from hosting.views import RailsHostingView, DjangoHostingView, NodeJSHostingView from membership import urls as membership_urls from ungleich_page.views import LandingView +from django.views.generic import RedirectView +from django.core.urlresolvers import reverse_lazy import debug_toolbar urlpatterns = [ url(r'^index.html$', LandingView.as_view()), @@ -28,6 +30,7 @@ urlpatterns += i18n_patterns('', url(r'^/?$', LandingView.as_view()), url(r'^admin/', include(admin.site.urls)), url(r'^datacenterlight', include('datacenterlight.urls', namespace="datacenterlight")), + url(r'^hosting/', RedirectView.as_view(url=reverse_lazy('hosting:login')), name='redirect_hosting_login'), url(r'^alplora', include('alplora.urls', namespace="alplora")), url(r'^membership/', include(membership_urls)), url(r'^digitalglarus/', include('digitalglarus.urls', From 0353f726766c6a79a1dd05a37e44a3a1f1eb12ad Mon Sep 17 00:00:00 2001 From: Modulos Date: Sun, 14 May 2017 12:44:36 +0200 Subject: [PATCH 09/11] Try connection --- opennebula_api/models.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/opennebula_api/models.py b/opennebula_api/models.py index e225ce0f..ac2da393 100644 --- a/opennebula_api/models.py +++ b/opennebula_api/models.py @@ -84,8 +84,11 @@ class OpenNebulaManager(): vm_pool.info() except AttributeError: logger.info('Could not connect via client, using oneadmin instead') - vm_pool = oca.VirtualMachinePool(self.oneadmin_client) - vm_pool.info(filter=-2) + try: + vm_pool = oca.VirtualMachinePool(self.oneadmin_client) + vm_pool.info(filter=-2) + except: + raise ConnectionRefusedError except ConnectionRefusedError: logger.info('Could not connect to host: {host} via protocol {protocol}'.format( From 62be9ae7890ee0cad38d541f0c0efdfaa3f23e09 Mon Sep 17 00:00:00 2001 From: "M.Ravi" Date: Sun, 14 May 2017 17:39:10 +0530 Subject: [PATCH 10/11] Added ServiceUnvailable error handling for the case when we have no connection to OpenNebula. --- opennebula_api/views.py | 46 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 41 insertions(+), 5 deletions(-) diff --git a/opennebula_api/views.py b/opennebula_api/views.py index 170c9716..d982f7bb 100644 --- a/opennebula_api/views.py +++ b/opennebula_api/views.py @@ -12,6 +12,12 @@ from guardian.mixins import PermissionRequiredMixin from .serializers import VirtualMachineTemplateSerializer, \ VirtualMachineSerializer from .models import OpenNebulaManager +from rest_framework.exceptions import APIException + +class ServiceUnavailable(APIException): + status_code = 503 + default_detail = 'Service temporarily unavailable, try again later.' + default_code = 'service_unavailable' class TemplateCreateView(generics.ListCreateAPIView): @@ -37,7 +43,14 @@ class TemplateDetailsView(generics.RetrieveUpdateDestroyAPIView): def get_queryset(self): manager = OpenNebulaManager() - return manager.get_templates() + # We may have ConnectionRefusedError if we don't have a + # connection to OpenNebula. For now, we raise ServiceUnavailable + try: + templates = manager.get_templates() + except ConnectionRefusedError: + raise ServiceUnavailable + + return templates class VmCreateView(generics.ListCreateAPIView): """This class handles the GET and POST requests.""" @@ -48,7 +61,13 @@ class VmCreateView(generics.ListCreateAPIView): owner = self.request.user manager = OpenNebulaManager(email=owner.email, password=owner.password) - return manager.get_vms() + # We may have ConnectionRefusedError if we don't have a + # connection to OpenNebula. For now, we raise ServiceUnavailable + try: + vms = manager.get_vms() + except ConnectionRefusedError: + raise ServiceUnavailable + return vms def perform_create(self, serializer): """Save the post data when creating a new template.""" @@ -64,17 +83,34 @@ class VmDetailsView(generics.RetrieveUpdateDestroyAPIView): owner = self.request.user manager = OpenNebulaManager(email=owner.email, password=owner.password) - return manager.get_vms() + # We may have ConnectionRefusedError if we don't have a + # connection to OpenNebula. For now, we raise ServiceUnavailable + try: + vms = manager.get_vms() + except ConnectionRefusedError: + raise ServiceUnavailable + return vms def get_object(self): owner = self.request.user manager = OpenNebulaManager(email=owner.email, password=owner.password) - return manager.get_vm(self.kwargs.get('pk')) + # We may have ConnectionRefusedError if we don't have a + # connection to OpenNebula. For now, we raise ServiceUnavailable + try: + vm = manager.get_vm(self.kwargs.get('pk')) + except ConnectionRefusedError: + raise ServiceUnavailable + return vm def perform_destroy(self, instance): owner = self.request.user manager = OpenNebulaManager(email=owner.email, password=owner.password) - manager.delete_vm(instance.id) + # We may have ConnectionRefusedError if we don't have a + # connection to OpenNebula. For now, we raise ServiceUnavailable + try: + manager.delete_vm(instance.id) + except ConnectionRefusedError: + raise ServiceUnavailable From 1ca884e1f6f2c6a403d72f4ea3922da4fafcfab6 Mon Sep 17 00:00:00 2001 From: "M.Ravi" Date: Sun, 14 May 2017 21:09:16 +0530 Subject: [PATCH 11/11] Removed 'More info' button from datacenterlight index page. --- datacenterlight/templates/datacenterlight/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/datacenterlight/templates/datacenterlight/index.html b/datacenterlight/templates/datacenterlight/index.html index 4d90769c..12d5fd47 100755 --- a/datacenterlight/templates/datacenterlight/index.html +++ b/datacenterlight/templates/datacenterlight/index.html @@ -231,7 +231,7 @@

2 GiB RAM,

{% trans "15 GiB storage(SSD)" %}

- {% trans "Buy Now!" %} {% trans "More Info" %}

+ {% trans "Buy Now!" %}