Merge branch 'opennebula-integration' into vm_bill
This commit is contained in:
		
				commit
				
					
						3ee075fad9
					
				
			
		
					 4 changed files with 180 additions and 84 deletions
				
			
		| 
						 | 
					@ -5,7 +5,7 @@ import oca
 | 
				
			||||||
from django.db import models
 | 
					from django.db import models
 | 
				
			||||||
from django.utils.translation import ugettext_lazy as _
 | 
					from django.utils.translation import ugettext_lazy as _
 | 
				
			||||||
from django.utils.functional import cached_property
 | 
					from django.utils.functional import cached_property
 | 
				
			||||||
from django.conf import settings
 | 
					from hosting.opennebula_functions import OpenNebulaManager
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from django.conf import settings
 | 
					from django.conf import settings
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -177,79 +177,38 @@ class VirtualMachinePlan(AssignPermissionsMixin, models.Model):
 | 
				
			||||||
        self.status = self.CANCELED_STATUS
 | 
					        self.status = self.CANCELED_STATUS
 | 
				
			||||||
        self.save(update_fields=['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
 | 
					    @classmethod
 | 
				
			||||||
    def get_vms(self, email):
 | 
					    def get_vms(self, email):
 | 
				
			||||||
        # Get User
 | 
					 | 
				
			||||||
        user_email = email
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # Connect to open nebula server
 | 
					        # Get opennebula client
 | 
				
			||||||
        # TODO: handle potential connection error
 | 
					        opennebula_client = OpenNebulaManager()
 | 
				
			||||||
        oneadmin_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(oneadmin_client)
 | 
					 | 
				
			||||||
        user_pool.info()
 | 
					 | 
				
			||||||
        try:
 | 
					 | 
				
			||||||
            user = user_pool.get_by_name(user_email)
 | 
					 | 
				
			||||||
            user_id = user.id
 | 
					 | 
				
			||||||
            logger.debug("User {user} exists.".format(user=user_email))
 | 
					 | 
				
			||||||
        except WrongNameError as wrong_name_err:
 | 
					 | 
				
			||||||
            # User does not exist. So, we create this user in OpenNebula
 | 
					 | 
				
			||||||
            password = get_user_opennebula_password()
 | 
					 | 
				
			||||||
            # We use the core authenticator driver for the new user
 | 
					 | 
				
			||||||
            user_id = oneadmin_client.call('user.allocate', 
 | 
					 | 
				
			||||||
                                           user_email, password,
 | 
					 | 
				
			||||||
                                           'core')
 | 
					 | 
				
			||||||
            logger.debug("User {0} does not exist. Created the user. User id = {1}", user_email, user_id)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # We should now have an OpenNebula user corresponding to user_email
 | 
					        # Get vm pool
 | 
				
			||||||
        # It is now ok to now perform opennebula functions with this user's client
 | 
					        vm_pool = opennebula_client.get_vms(email)
 | 
				
			||||||
        client = oca.Client("{0}:{1}".format(
 | 
					 | 
				
			||||||
            user_email,
 | 
					 | 
				
			||||||
            get_user_opennebula_password()),
 | 
					 | 
				
			||||||
            "{protocol}://{domain}:{port}{endpoint}".format(
 | 
					 | 
				
			||||||
                protocol=settings.OPENNEBULA_PROTOCOL,
 | 
					 | 
				
			||||||
                domain=settings.OPENNEBULA_DOMAIN,
 | 
					 | 
				
			||||||
                port=settings.OPENNEBULA_PORT,
 | 
					 | 
				
			||||||
                endpoint=settings.OPENNEBULA_ENDPOINT
 | 
					 | 
				
			||||||
        ))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        # Get vm_pool for given user_id
 | 
					 | 
				
			||||||
        vm_pool = oca.VirtualMachinePool(client)
 | 
					 | 
				
			||||||
        vm_pool.info(filter=user_id)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # Reset total price
 | 
					        # Reset total price
 | 
				
			||||||
        self.total_price = 0
 | 
					        self.total_price = 0
 | 
				
			||||||
        vms = []
 | 
					        vms = []
 | 
				
			||||||
        # Add vm in vm_pool to context
 | 
					        # Add vm in vm_pool to context
 | 
				
			||||||
        for vm in vm_pool:
 | 
					        for vm in vm_pool:
 | 
				
			||||||
            name = vm.name
 | 
					            vm_data = OpenNebulaManager.parse_vm(vm)
 | 
				
			||||||
            cores = int(vm.template.vcpu)
 | 
					            vms.append(vm_data)
 | 
				
			||||||
            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)
 | 
					 | 
				
			||||||
            # self.total_price += price
 | 
					            # self.total_price += price
 | 
				
			||||||
        # self.save()
 | 
					        # self.save()
 | 
				
			||||||
        return vms
 | 
					        return vms
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -19,6 +19,94 @@ from django import forms
 | 
				
			||||||
logger = logging.getLogger(__name__)
 | 
					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):
 | 
					class HostingManageVMAdmin(admin.ModelAdmin):
 | 
				
			||||||
    client = None
 | 
					    client = None
 | 
				
			||||||
    oneadmin_client = None
 | 
					    oneadmin_client = None
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -20,18 +20,18 @@
 | 
				
			||||||
				</tr>
 | 
									</tr>
 | 
				
			||||||
				</thead>
 | 
									</thead>
 | 
				
			||||||
				<tbody> 
 | 
									<tbody> 
 | 
				
			||||||
					{% for vm in vms %}
 | 
										{% for vm in vms_opennebula %}
 | 
				
			||||||
					<tr>
 | 
										<tr>
 | 
				
			||||||
						<td scope="row">{{vm.name}}</td> 
 | 
											<td scope="row">{{vm.deploy_id}}</td> 
 | 
				
			||||||
						<td>{{vm.price}} CHF</td> 
 | 
											<td>{{vm.price}} CHF</td> 
 | 
				
			||||||
						<td>
 | 
											<td>
 | 
				
			||||||
                           
 | 
					                           
 | 
				
			||||||
							{% if vm.status == 'pending' %}
 | 
												{% if vm.state == 'ACTIVE' %}
 | 
				
			||||||
								<span class="h3 label label-warning"><strong>{{vm.get_status_display}}</strong></span>
 | 
													<span class="h3 label label-success"><strong> {{vm.state}}</strong></span>
 | 
				
			||||||
							{% elif  vm.status == 'online' %}
 | 
												{% elif  vm.state == 'POWEROFF' %}
 | 
				
			||||||
								<span class="h3 label label-success"><strong>{{vm.get_status_display}}</strong></span>
 | 
													<span class="h3 label label-danger"><strong>{{vm.state}}</strong></span>
 | 
				
			||||||
							{% else %}
 | 
												{% else %}
 | 
				
			||||||
								<span class="h3 label label-danger"><strong>{{vm.get_status_display}}</strong></span>
 | 
													<span class="h3 label label-warning"><strong>{{vm.state}}</strong></span>
 | 
				
			||||||
							{% endif %}  
 | 
												{% endif %}  
 | 
				
			||||||
 | 
					
 | 
				
			||||||
						</td> 
 | 
											</td> 
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,6 +1,7 @@
 | 
				
			||||||
from collections import namedtuple
 | 
					from collections import namedtuple
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from django.shortcuts import render
 | 
					from django.shortcuts import render
 | 
				
			||||||
 | 
					from django.http import Http404
 | 
				
			||||||
from django.core.urlresolvers import reverse_lazy, reverse
 | 
					from django.core.urlresolvers import reverse_lazy, reverse
 | 
				
			||||||
from django.contrib.auth.mixins import LoginRequiredMixin
 | 
					from django.contrib.auth.mixins import LoginRequiredMixin
 | 
				
			||||||
from django.views.generic import View, CreateView, FormView, ListView, DetailView,\
 | 
					from django.views.generic import View, CreateView, FormView, ListView, DetailView,\
 | 
				
			||||||
| 
						 | 
					@ -414,6 +415,13 @@ class VirtualMachinesPlanListView(LoginRequiredMixin, ListView):
 | 
				
			||||||
    paginate_by = 10
 | 
					    paginate_by = 10
 | 
				
			||||||
    ordering = '-id'
 | 
					    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):
 | 
					    def get_queryset(self):
 | 
				
			||||||
        # hosting_admin = HostingManageVMAdmin.__new__(HostingManageVMAdmin)
 | 
					        # hosting_admin = HostingManageVMAdmin.__new__(HostingManageVMAdmin)
 | 
				
			||||||
        # print(hosting_admin.show_vms_view(self.request))
 | 
					        # print(hosting_admin.show_vms_view(self.request))
 | 
				
			||||||
| 
						 | 
					@ -458,19 +466,60 @@ class CreateVirtualMachinesView(LoginRequiredMixin, View):
 | 
				
			||||||
    #     return super(VirtualMachinesPlanListView, self).get_queryset()
 | 
					    #     return super(VirtualMachinesPlanListView, self).get_queryset()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class VirtualMachineView(PermissionRequiredMixin, LoginRequiredMixin, UpdateView):
 | 
					class VirtualMachineView(PermissionRequiredMixin, LoginRequiredMixin, View):
 | 
				
			||||||
    template_name = "hosting/virtual_machine_detail.html"
 | 
					    template_name = "hosting/virtual_machine_detail.html"
 | 
				
			||||||
    login_url = reverse_lazy('hosting:login')
 | 
					    login_url = reverse_lazy('hosting:login')
 | 
				
			||||||
    model = VirtualMachinePlan
 | 
					    # model = VirtualMachinePlan
 | 
				
			||||||
    context_object_name = "virtual_machine"
 | 
					    # context_object_name = "virtual_machine"
 | 
				
			||||||
    permission_required = ['view_virtualmachineplan', 'cancel_virtualmachineplan']
 | 
					    permission_required = ['view_virtualmachineplan', 'cancel_virtualmachineplan']
 | 
				
			||||||
    fields = '__all__'
 | 
					    # fields = '__all__'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def get_success_url(self):
 | 
					    # def get_context_data(self, **kwargs):
 | 
				
			||||||
        vm = self.get_object()
 | 
					    #     vm_plan = get_object()
 | 
				
			||||||
        final_url = "%s%s" % (reverse('hosting:virtual_machines', kwargs={'pk': vm.id}),
 | 
					    #     context = super(VirtualMachineView, self).get_context_data(**kwargs)
 | 
				
			||||||
                              '#status-v')
 | 
					    #     context.update({
 | 
				
			||||||
        return final_url
 | 
					    #         '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):
 | 
					    def post(self, *args, **kwargs):
 | 
				
			||||||
        vm = self.get_object()
 | 
					        vm = self.get_object()
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue