diff --git a/hosting/models.py b/hosting/models.py index 188f1733..6be6c246 100644 --- a/hosting/models.py +++ b/hosting/models.py @@ -7,7 +7,6 @@ import oca from django.db import models from django.utils.translation import ugettext_lazy as _ from django.utils.functional import cached_property -from hosting.opennebula_functions import OpenNebulaManager from django.conf import settings @@ -18,8 +17,6 @@ from membership.models import StripeCustomer, CustomUser from utils.models import BillingAddress from utils.mixins import AssignPermissionsMixin from .managers import VMPlansManager -from oca.exceptions import OpenNebulaException -from oca.pool import WrongNameError logger = logging.getLogger(__name__) diff --git a/hosting/templates/hosting/create_virtual_machine.html b/hosting/templates/hosting/create_virtual_machine.html index 3a68421e..405b2988 100644 --- a/hosting/templates/hosting/create_virtual_machine.html +++ b/hosting/templates/hosting/create_virtual_machine.html @@ -24,16 +24,16 @@ {% endfor %} - +
diff --git a/hosting/views.py b/hosting/views.py index e09380ab..0025a40d 100644 --- a/hosting/views.py +++ b/hosting/views.py @@ -31,7 +31,9 @@ from .mixins import ProcessVMSelectionMixin from opennebula_api.models import OpenNebulaManager from opennebula_api.serializers import VirtualMachineSerializer,\ - VirtualMachineTemplateSerializer + VirtualMachineTemplateSerializer,\ + ImageSerializer + from oca.exceptions import OpenNebulaException from oca.pool import WrongNameError @@ -392,6 +394,7 @@ class PaymentVMView(LoginRequiredMixin, FormView): specifications = request.session.get('template') vm_template_id = specifications.get('id', 1) + vm_image_id = request.session.get('image').get('id', 1) final_price = specifications.get('price', 1) @@ -428,8 +431,6 @@ class PaymentVMView(LoginRequiredMixin, FormView): # Create OpenNebulaManager manager = OpenNebulaManager(email=owner.email, password=owner.password) - template = manager.get_template(vm_template_id) - # Get user ssh key try: user_key = UserHostingKey.objects.get( @@ -441,8 +442,9 @@ class PaymentVMView(LoginRequiredMixin, FormView): # Create a vm using logged user vm_id = manager.create_vm( - vm_template_id, - ssh_key=user_key.public_key + template_id=vm_template_id, + ssh_key=user_key.public_key, + image_id=vm_image_id, ) # Create a Hosting Order @@ -567,21 +569,24 @@ class CreateVirtualMachinesView(LoginRequiredMixin, View): ) return HttpResponseRedirect(reverse('hosting:key_pair')) - #TODO: Replace with OpenNebulaManager.get_apps - templates = OpenNebulaManager().get_templates() - data = VirtualMachineTemplateSerializer(templates, many=True).data + manager = OpenNebulaManager() + templates = manager.get_templates() + images = manager.get_images() context = { - 'templates': data, + 'templates': VirtualMachineTemplateSerializer(templates, many=True).data, + 'images' : ImageSerializer(images, many=True).data } - # context = {} return render(request, self.template_name, context) def post(self, request): - template_id = int(request.POST.get('vm_template_id')) - template = OpenNebulaManager().get_template(template_id) - data = VirtualMachineTemplateSerializer(template).data - request.session['template'] = data + 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) + request.session['template'] = VirtualMachineTemplateSerializer(template).data + request.session['image'] = ImageSerializer(image).data return redirect(reverse('hosting:payment')) diff --git a/opennebula_api/models.py b/opennebula_api/models.py index d9c5b7cf..f543d0ec 100644 --- a/opennebula_api/models.py +++ b/opennebula_api/models.py @@ -102,23 +102,43 @@ class OpenNebulaManager(): return [] def get_vm(self, vm_id): + vm_id = int(vm_id) try: vm_pool = self._get_vm_pool() - return vm_pool.get_by_id(int(vm_id)) + return vm_pool.get_by_id(vm_id) except: return None - #TODO: get app with id - def create_vm(self, template_id, app_id=None, ssh_key=None): - extra_template = "{ssh_key}".format( - ssh_key=ssh_key - ) - vm_id = self.oneadmin_client.call( - oca.VmTemplate.METHODS['instantiate'], - template_id, - '', - False, - extra_template + def create_vm(self, template_id, image_id=None, ssh_key=None): + extra_template_formater = """ + {ssh_key} + + + {image_id} + + """ + + template = self.get_template(template_id) + vm_id = template.instantiate(name ='', pending=False, extra_template='') + image = self.get_image(image_id) + + 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( @@ -177,8 +197,12 @@ class OpenNebulaManager(): return [] def get_template(self, template_id): - template_pool = self._get_template_pool() - return template_pool.get_by_id(template_id) + template_id = int(template_id) + try: + template_pool = self._get_template_pool() + return template_pool.get_by_id(template_id) + except: + return None @@ -238,3 +262,38 @@ 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 b73682e6..86da2f0b 100644 --- a/opennebula_api/serializers.py +++ b/opennebula_api/serializers.py @@ -31,7 +31,7 @@ class VirtualMachineTemplateSerializer(serializers.Serializer): core_price = template.pop('cpu_cost') memory_price = template.pop('memory_cost') disk_size_price = template.pop('disk_cost') - manager = OpenNebulaManager(create_user = False) + manager = OpenNebulaManager() try: opennebula_id = manager.create_template(name=name, cores=cores, @@ -92,7 +92,7 @@ class VirtualMachineSerializer(serializers.Serializer): try: manager = OpenNebulaManager(email=owner.email, password=owner.password, - create_user = True) + ) opennebula_id = manager.create_vm(template_id) except OpenNebulaException as err: raise serializers.ValidationError("OpenNebulaException occured. {0}".format(err)) @@ -117,3 +117,8 @@ class VirtualMachineSerializer(serializers.Serializer): 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() + diff --git a/opennebula_api/views.py b/opennebula_api/views.py index 20a28968..170c9716 100644 --- a/opennebula_api/views.py +++ b/opennebula_api/views.py @@ -47,8 +47,7 @@ class VmCreateView(generics.ListCreateAPIView): def get_queryset(self): owner = self.request.user manager = OpenNebulaManager(email=owner.email, - password=owner.password, - create_user=True) + password=owner.password) return manager.get_vms() def perform_create(self, serializer): @@ -64,21 +63,18 @@ class VmDetailsView(generics.RetrieveUpdateDestroyAPIView): def get_queryset(self): owner = self.request.user manager = OpenNebulaManager(email=owner.email, - password=owner.password, - create_user=True) + password=owner.password) return manager.get_vms() def get_object(self): owner = self.request.user manager = OpenNebulaManager(email=owner.email, - password=owner.password, - create_user=True) + password=owner.password) return manager.get_vm(self.kwargs.get('pk')) def perform_destroy(self, instance): owner = self.request.user manager = OpenNebulaManager(email=owner.email, - password=owner.password, - create_user = True) + password=owner.password) manager.delete_vm(instance.id)