diff --git a/hosting/models.py b/hosting/models.py index 8a9daaa1..3b096d92 100644 --- a/hosting/models.py +++ b/hosting/models.py @@ -4,6 +4,7 @@ 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 @@ -171,57 +172,38 @@ class VirtualMachinePlan(AssignPermissionsMixin, models.Model): self.status = self.CANCELED_STATUS self.save(update_fields=['status']) + @classmethod + def get_vm(self, email, vm_id): + # Get opennebula client + opennebula_client = OpenNebulaManager() + + # Get vm given the id + vm = opennebula_client.get_vm( + email, + vm_id + ) + + # Parse vm data + vm_data = OpenNebulaManager.parse_vm(vm) + + return vm_data + @classmethod def get_vms(self, email): - # Get User - user_email = email - # Connect to open nebula server - # TODO: handle potential connection error - client = oca.Client("{0}:{1}".format( - settings.OPENNEBULA_USERNAME, - settings.OPENNEBULA_PASSWORD), - "{protocol}://{domain}:{port}{endpoint}".format( - protocol=settings.OPENNEBULA_PROTOCOL, - domain=settings.OPENNEBULA_DOMAIN, - port=settings.OPENNEBULA_PORT, - endpoint=settings.OPENNEBULA_ENDPOINT - )) - # Get open nebula user id for given email - user_pool = oca.UserPool(client) - user_pool.info() - # TODO: handle potential name error - user_id = user_pool.get_by_name(user_email).id + # Get opennebula client + opennebula_client = OpenNebulaManager() - # Get vm_pool for given user_id - vm_pool = oca.VirtualMachinePool(client) - vm_pool.info(filter=user_id) + # Get vm pool + vm_pool = opennebula_client.get_vms(email) # Reset total price self.total_price = 0 vms = [] # Add vm in vm_pool to context for vm in vm_pool: - name = vm.name - cores = int(vm.template.vcpu) - memory = int(vm.template.memory) / 1024 - # Check if vm has more than one disk - if 'DISK' in vm.template.multiple: - disk_size = 0 - for disk in vm.template.disks: - disk_size += int(disk.size) / 1024 - else: - disk_size = int(vm.template.disk.size) / 1024 - - #TODO: Replace with vm plan - price = 0.6 * disk_size + 2 * memory + 5 * cores - vm = {} - vm['name'] = name - vm['price'] = price - vm['disk_size'] = disk_size - vm['cores'] = cores - vm['memory'] = memory - vms.append(vm) + vm_data = OpenNebulaManager.parse_vm(vm) + vms.append(vm_data) # self.total_price += price # self.save() return vms diff --git a/hosting/opennebula_functions.py b/hosting/opennebula_functions.py index 93919a29..f043270b 100644 --- a/hosting/opennebula_functions.py +++ b/hosting/opennebula_functions.py @@ -18,6 +18,94 @@ from oca.pool import WrongNameError logger = logging.getLogger(__name__) +class OpenNebulaManager: + + VM_STATE = { + '0': 'INIT', + '1': 'PENDING', + '2': 'HOLD', + '3': 'ACTIVE', + '4': 'STOPPED', + '5': 'SUSPENDED', + '6': 'DONE', + '8': 'POWEROFF', + '9': 'UNDEPLOYED', + '10': 'CLONING', + '11': 'CLONING_FAILURE', + } + + def __init__(self): + self.client = oca.Client("{0}:{1}".format( + settings.OPENNEBULA_USERNAME, + settings.OPENNEBULA_PASSWORD), + "{protocol}://{domain}:{port}{endpoint}".format( + protocol=settings.OPENNEBULA_PROTOCOL, + domain=settings.OPENNEBULA_DOMAIN, + port=settings.OPENNEBULA_PORT, + endpoint=settings.OPENNEBULA_ENDPOINT + )) + + @classmethod + def get_vm_state(self, state): + return self.VM_STATE.get(str(state)) + + @classmethod + def parse_vm(self, vm): + name = vm.name + cores = int(vm.template.vcpu) + memory = int(vm.template.memory) / 1024 + # Check if vm has more than one disk + if 'DISK' in vm.template.multiple: + disk_size = 0 + for disk in vm.template.disks: + disk_size += int(disk.size) / 1024 + else: + disk_size = int(vm.template.disk.size) / 1024 + + #TODO: Replace with vm plan + price = 0.6 * disk_size + 2 * memory + 5 * cores + vm_data = {} + vm_data['name'] = name + vm_data['price'] = price + vm_data['disk_size'] = disk_size + vm_data['cores'] = cores + vm_data['memory'] = memory + vm_data['deploy_id'] = vm.deploy_id + vm_data['id'] = vm.id + vm_data['state'] = self.get_vm_state(vm.state) + + return vm_data + + def get_vm(self, email, vm_id): + # Get vm's + vms = self.get_vms(email) + + # Filter vm by given id + return vms.get_by_id(int(vm_id)) + + def get_vms(self, email): + client = self.client + + # Get open nebula user id for given email + user_pool = oca.UserPool(client) + user_pool.info() + + # TODO: handle potential name error + user_id = user_pool.get_by_name(email).id + + # Get vm_pool for given user_id + vm_pool = oca.VirtualMachinePool(client) + vm_pool.info() + + # TODO: this is just to test with oneadmin user, remove this + user_id = 0 + vm_pool.info(filter=user_id) + + return vm_pool + + + + class HostingManageVMAdmin(admin.ModelAdmin): client = None oneadmin_client = None diff --git a/hosting/templates/hosting/virtual_machines.html b/hosting/templates/hosting/virtual_machines.html index f566be44..2de8aa48 100644 --- a/hosting/templates/hosting/virtual_machines.html +++ b/hosting/templates/hosting/virtual_machines.html @@ -20,24 +20,24 @@ - {% for vm in vms %} - - {{vm.name}} + {% for vm in vms_opennebula %} + + {{vm.deploy_id}} {{vm.price}} CHF - - {% if vm.status == 'pending' %} - {{vm.get_status_display}} - {% elif vm.status == 'online' %} - {{vm.get_status_display}} + + {% if vm.state == 'ACTIVE' %} + {{vm.state}} + {% elif vm.state == 'POWEROFF' %} + {{vm.state}} {% else %} - {{vm.get_status_display}} + {{vm.state}} {% endif %} - - + + {% endfor %} diff --git a/hosting/views.py b/hosting/views.py index 6104f7e8..913cb794 100644 --- a/hosting/views.py +++ b/hosting/views.py @@ -1,6 +1,7 @@ from collections import namedtuple from django.shortcuts import render +from django.http import Http404 from django.core.urlresolvers import reverse_lazy, reverse from django.contrib.auth.mixins import LoginRequiredMixin from django.views.generic import View, CreateView, FormView, ListView, DetailView,\ @@ -411,6 +412,13 @@ class VirtualMachinesPlanListView(LoginRequiredMixin, ListView): paginate_by = 10 ordering = '-id' + def get_context_data(self, **kwargs): + context = super(VirtualMachinesPlanListView, self).get_context_data(**kwargs) + context.update({ + 'vms_opennebula': VirtualMachinePlan.get_vms(self.request.user.email) + }) + return context + def get_queryset(self): # hosting_admin = HostingManageVMAdmin.__new__(HostingManageVMAdmin) # print(hosting_admin.show_vms_view(self.request)) @@ -455,19 +463,60 @@ class CreateVirtualMachinesView(LoginRequiredMixin, View): # return super(VirtualMachinesPlanListView, self).get_queryset() -class VirtualMachineView(PermissionRequiredMixin, LoginRequiredMixin, UpdateView): +class VirtualMachineView(PermissionRequiredMixin, LoginRequiredMixin, View): template_name = "hosting/virtual_machine_detail.html" login_url = reverse_lazy('hosting:login') - model = VirtualMachinePlan - context_object_name = "virtual_machine" + # model = VirtualMachinePlan + # context_object_name = "virtual_machine" permission_required = ['view_virtualmachineplan', 'cancel_virtualmachineplan'] - fields = '__all__' + # fields = '__all__' - def get_success_url(self): - vm = self.get_object() - final_url = "%s%s" % (reverse('hosting:virtual_machines', kwargs={'pk': vm.id}), - '#status-v') - return final_url + # def get_context_data(self, **kwargs): + # vm_plan = get_object() + # context = super(VirtualMachineView, self).get_context_data(**kwargs) + # context.update({ + # 'opennebula_vm': VirtualMachinePlan.get_vm( + # self.request.user.email, + # opennebula_id + # ) + # }) + # return context + + # def get_object(self, queryset=None): + # # if queryset is None: + # # queryset = self.get_queryset() + # # Next, try looking up by primary key. + # vm_id = self.kwargs.get(self.pk_url_kwarg) + # try: + # return VirtualMachinePlan.get_vm( + # self.request.user.email, + # vm_id + # ) + # except Exception as error: + # raise Http404() + + # def get_success_url(self): + # vm = self.get_object() + # final_url = "%s%s" % (reverse('hosting:virtual_machines', kwargs={'pk': vm.id}), + # '#status-v') + # return final_url + + def get(self, request, *args, **kwargs): + vm_id = self.kwargs.get('pk', 24) + try: + opennebula_vm = VirtualMachinePlan.get_vm( + self.request.user.email, + vm_id + ) + except Exception as error: + print(error) + raise Http404() + + context = { + 'virtual_machine': opennebula_vm, + } + # context = {} + return render(request, self.template_name, context) def post(self, *args, **kwargs): vm = self.get_object()