Merge pull request #227 from levivm/opennebula-integration
Opennebula integration
This commit is contained in:
		
				commit
				
					
						31b7b37eb9
					
				
			
		
					 3 changed files with 135 additions and 27 deletions
				
			
		| 
						 | 
					@ -176,13 +176,30 @@ class VirtualMachinePlan(AssignPermissionsMixin, models.Model):
 | 
				
			||||||
        self.save(update_fields=['status'])
 | 
					        self.save(update_fields=['status'])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @classmethod
 | 
					    @classmethod
 | 
				
			||||||
    def get_vm(self, email, vm_id):
 | 
					    def create_opennebula_vm(self, user, specs):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # Init opennebula manager using given user
 | 
				
			||||||
 | 
					        opennebula_client = OpenNebulaManager(
 | 
				
			||||||
 | 
					            user.email,
 | 
				
			||||||
 | 
					            user.password[0:20],
 | 
				
			||||||
 | 
					            create_user=True
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # Create a vm in opennebula using given specs
 | 
				
			||||||
 | 
					        vm = opennebula_client.create_vm(specs)
 | 
				
			||||||
 | 
					        return vm
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @classmethod
 | 
				
			||||||
 | 
					    def get_vm(self, user, vm_id):
 | 
				
			||||||
        # Get opennebula client
 | 
					        # Get opennebula client
 | 
				
			||||||
        opennebula_client = OpenNebulaManager()
 | 
					        opennebula_client = OpenNebulaManager(
 | 
				
			||||||
 | 
					            email=user.email,
 | 
				
			||||||
 | 
					            password=user.password[:20],
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # Get vm given the id
 | 
					        # Get vm given the id
 | 
				
			||||||
        vm = opennebula_client.get_vm(
 | 
					        vm = opennebula_client.get_vm(
 | 
				
			||||||
            email,
 | 
					            user.email,
 | 
				
			||||||
            vm_id
 | 
					            vm_id
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -192,13 +209,16 @@ class VirtualMachinePlan(AssignPermissionsMixin, models.Model):
 | 
				
			||||||
        return vm_data
 | 
					        return vm_data
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @classmethod
 | 
					    @classmethod
 | 
				
			||||||
    def get_vms(self, email):
 | 
					    def get_vms(self, user):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # Get opennebula client
 | 
					        # Get opennebula client
 | 
				
			||||||
        opennebula_client = OpenNebulaManager()
 | 
					        opennebula_client = OpenNebulaManager(
 | 
				
			||||||
 | 
					            email=user.email,
 | 
				
			||||||
 | 
					            password=user.password[:20],
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # Get vm pool
 | 
					        # Get vm pool
 | 
				
			||||||
        vm_pool = opennebula_client.get_vms(email)
 | 
					        vm_pool = opennebula_client.get_vms(user.email)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # Reset total price
 | 
					        # Reset total price
 | 
				
			||||||
        self.total_price = 0
 | 
					        self.total_price = 0
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -35,10 +35,34 @@ class OpenNebulaManager:
 | 
				
			||||||
        '11': 'CLONING_FAILURE',
 | 
					        '11': 'CLONING_FAILURE',
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __init__(self):
 | 
					    def __init__(self, email=None, password=None, create_user=True):
 | 
				
			||||||
        self.client = oca.Client("{0}:{1}".format(
 | 
					
 | 
				
			||||||
 | 
					        # Get oneadmin client
 | 
				
			||||||
 | 
					        self.oneadmin_client = self._get_opennebula_client(
 | 
				
			||||||
            settings.OPENNEBULA_USERNAME,
 | 
					            settings.OPENNEBULA_USERNAME,
 | 
				
			||||||
            settings.OPENNEBULA_PASSWORD),
 | 
					            settings.OPENNEBULA_PASSWORD
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if not create_user:
 | 
				
			||||||
 | 
					            return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # Get or create oppenebula user using given credentials
 | 
				
			||||||
 | 
					        self.opennebula_user = self._get_or_create_user(
 | 
				
			||||||
 | 
					            email,
 | 
				
			||||||
 | 
					            password
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # If opennebula user was created/obtained, get his client
 | 
				
			||||||
 | 
					        if self.opennebula_user:
 | 
				
			||||||
 | 
					            self.client = self._get_opennebula_client(
 | 
				
			||||||
 | 
					                email,
 | 
				
			||||||
 | 
					                password
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def _get_opennebula_client(self, username, password):
 | 
				
			||||||
 | 
					        return oca.Client("{0}:{1}".format(
 | 
				
			||||||
 | 
					            username,
 | 
				
			||||||
 | 
					            password),
 | 
				
			||||||
            "{protocol}://{domain}:{port}{endpoint}".format(
 | 
					            "{protocol}://{domain}:{port}{endpoint}".format(
 | 
				
			||||||
                protocol=settings.OPENNEBULA_PROTOCOL,
 | 
					                protocol=settings.OPENNEBULA_PROTOCOL,
 | 
				
			||||||
                domain=settings.OPENNEBULA_DOMAIN,
 | 
					                domain=settings.OPENNEBULA_DOMAIN,
 | 
				
			||||||
| 
						 | 
					@ -46,6 +70,25 @@ class OpenNebulaManager:
 | 
				
			||||||
                endpoint=settings.OPENNEBULA_ENDPOINT
 | 
					                endpoint=settings.OPENNEBULA_ENDPOINT
 | 
				
			||||||
        ))
 | 
					        ))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def _get_or_create_user(self, email, password):
 | 
				
			||||||
 | 
					        try:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            user_pool = oca.UserPool(self.oneadmin_client)
 | 
				
			||||||
 | 
					            user_pool.info()
 | 
				
			||||||
 | 
					            opennebula_user = user_pool.get_by_name(email)
 | 
				
			||||||
 | 
					            return opennebula_user
 | 
				
			||||||
 | 
					        except WrongNameError as wrong_name_err:
 | 
				
			||||||
 | 
					            # TODO: Store this password so that we can use it later to 
 | 
				
			||||||
 | 
					            # connect to opennebula
 | 
				
			||||||
 | 
					            return oca.User.allocate(self.oneadmin_client, email, password)
 | 
				
			||||||
 | 
					            logger.debug(
 | 
				
			||||||
 | 
					                "User {0} does not exist. Created the user. User id = {1}",
 | 
				
			||||||
 | 
					                email,
 | 
				
			||||||
 | 
					                opennebula_user
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					        except OpenNebulaException as err:
 | 
				
			||||||
 | 
					            logger.error("Error : {0}".format(err))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @classmethod
 | 
					    @classmethod
 | 
				
			||||||
    def get_vm_state(self, state):
 | 
					    def get_vm_state(self, state):
 | 
				
			||||||
        return self.VM_STATE.get(str(state))
 | 
					        return self.VM_STATE.get(str(state))
 | 
				
			||||||
| 
						 | 
					@ -77,6 +120,56 @@ class OpenNebulaManager:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return vm_data
 | 
					        return vm_data
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def create_vm(self, specs):
 | 
				
			||||||
 | 
					        vm_id = None
 | 
				
			||||||
 | 
					        try:
 | 
				
			||||||
 | 
					            # We do have the vm_template param set. Get and parse it
 | 
				
			||||||
 | 
					            # and check it to be in the desired range.
 | 
				
			||||||
 | 
					            # We have 8 possible VM templates for the moment which are 1x, 2x, 4x ...
 | 
				
			||||||
 | 
					            # the basic template of 10GB disk, 1GB ram, 1 vcpu, 0.1 cpu
 | 
				
			||||||
 | 
					            vm_string_formatter = """<VM>
 | 
				
			||||||
 | 
					                                      <MEMORY>{memory}</MEMORY>
 | 
				
			||||||
 | 
					                                      <VCPU>{vcpu}</VCPU>
 | 
				
			||||||
 | 
					                                      <CPU>{cpu}</CPU>
 | 
				
			||||||
 | 
					                                      <DISK>
 | 
				
			||||||
 | 
					                                        <TYPE>{disk_type}</TYPE>
 | 
				
			||||||
 | 
					                                        <SIZE>{size}</SIZE>
 | 
				
			||||||
 | 
					                                      </DISK>
 | 
				
			||||||
 | 
					                                    </VM>
 | 
				
			||||||
 | 
					                                    """
 | 
				
			||||||
 | 
					            vm_id = oca.VirtualMachine.allocate(
 | 
				
			||||||
 | 
					                self.oneadmin_client,
 | 
				
			||||||
 | 
					                vm_string_formatter.format(
 | 
				
			||||||
 | 
					                    memory=1024 * specs.get('memory'),
 | 
				
			||||||
 | 
					                    vcpu=specs.get('cores'),
 | 
				
			||||||
 | 
					                    cpu=0.1 * specs.get('cores'),
 | 
				
			||||||
 | 
					                    disk_type='fs',
 | 
				
			||||||
 | 
					                    size=10000 * specs.get('disk_size')
 | 
				
			||||||
 | 
					                )
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            self.oneadmin_client.call(
 | 
				
			||||||
 | 
					                oca.VirtualMachine.METHODS['chown'],
 | 
				
			||||||
 | 
					                vm_id,
 | 
				
			||||||
 | 
					                self.opennebula_user.id,
 | 
				
			||||||
 | 
					                self.opennebula_user.group_ids[0]
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					            # oca.VirtualMachine.chown(
 | 
				
			||||||
 | 
					            #     vm_id,
 | 
				
			||||||
 | 
					               
 | 
				
			||||||
 | 
					            # )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        except socket.timeout as socket_err:
 | 
				
			||||||
 | 
					            logger.error("Socket timeout error: {0}".format(socket_err))
 | 
				
			||||||
 | 
					        except OpenNebulaException as opennebula_err:
 | 
				
			||||||
 | 
					            logger.error("OpenNebulaException error: {0}".format(opennebula_err))
 | 
				
			||||||
 | 
					        except OSError as os_err:
 | 
				
			||||||
 | 
					            logger.error("OSError : {0}".format(os_err))
 | 
				
			||||||
 | 
					        except ValueError as value_err:
 | 
				
			||||||
 | 
					            logger.error("ValueError : {0}".format(value_err))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return vm_id
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def get_vm(self, email, vm_id):
 | 
					    def get_vm(self, email, vm_id):
 | 
				
			||||||
        # Get vm's
 | 
					        # Get vm's
 | 
				
			||||||
        vms = self.get_vms(email)
 | 
					        vms = self.get_vms(email)
 | 
				
			||||||
| 
						 | 
					@ -85,7 +178,7 @@ class OpenNebulaManager:
 | 
				
			||||||
        return vms.get_by_id(int(vm_id))
 | 
					        return vms.get_by_id(int(vm_id))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def get_vms(self, email):
 | 
					    def get_vms(self, email):
 | 
				
			||||||
        client = self.client
 | 
					        client = self.oneadmin_client
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # Get open nebula user id for given email
 | 
					        # Get open nebula user id for given email
 | 
				
			||||||
        user_pool = oca.UserPool(client)
 | 
					        user_pool = oca.UserPool(client)
 | 
				
			||||||
| 
						 | 
					@ -99,7 +192,7 @@ class OpenNebulaManager:
 | 
				
			||||||
        vm_pool.info()
 | 
					        vm_pool.info()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # TODO: this is just to test with oneadmin user, remove this
 | 
					        # TODO: this is just to test with oneadmin user, remove this
 | 
				
			||||||
        user_id = 0
 | 
					        # user_id = 0
 | 
				
			||||||
        vm_pool.info(filter=user_id)
 | 
					        vm_pool.info(filter=user_id)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return vm_pool
 | 
					        return vm_pool
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -27,7 +27,7 @@ from utils.mailer import BaseEmail
 | 
				
			||||||
from .models import VirtualMachineType, VirtualMachinePlan, HostingOrder, UserHostingKey
 | 
					from .models import VirtualMachineType, VirtualMachinePlan, HostingOrder, UserHostingKey
 | 
				
			||||||
from .forms import HostingUserSignupForm, HostingUserLoginForm, UserHostingKeyForm
 | 
					from .forms import HostingUserSignupForm, HostingUserLoginForm, UserHostingKeyForm
 | 
				
			||||||
from .mixins import ProcessVMSelectionMixin
 | 
					from .mixins import ProcessVMSelectionMixin
 | 
				
			||||||
from .opennebula_functions import HostingManageVMAdmin
 | 
					from .opennebula_functions import HostingManageVMAdmin, OpenNebulaManager
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class DjangoHostingView(ProcessVMSelectionMixin, View):
 | 
					class DjangoHostingView(ProcessVMSelectionMixin, View):
 | 
				
			||||||
| 
						 | 
					@ -340,19 +340,14 @@ class PaymentVMView(LoginRequiredMixin, FormView):
 | 
				
			||||||
            # If the Stripe payment was successed, set order status approved
 | 
					            # If the Stripe payment was successed, set order status approved
 | 
				
			||||||
            order.set_approved()
 | 
					            order.set_approved()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            # Create VM using oppenebula functions 
 | 
					            # Create a vm using logged user
 | 
				
			||||||
            # _request = namedtuple('request', 'POST user')
 | 
					            oppennebula_vm_id = VirtualMachinePlan.create_opennebula_vm(
 | 
				
			||||||
            # _request.user = request.user
 | 
					                self.request.user,
 | 
				
			||||||
            # user = namedtuple('user', 'email')
 | 
					                specs
 | 
				
			||||||
            # email 
 | 
					            )
 | 
				
			||||||
            # _request.POST = {
 | 
					 | 
				
			||||||
                # 'vm_template': vm_template
 | 
					 | 
				
			||||||
            # }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
            hosting_admin = HostingManageVMAdmin.__new__(HostingManageVMAdmin)
 | 
					 | 
				
			||||||
            hosting_admin.init_opennebula_client(request)
 | 
					 | 
				
			||||||
            oppennebula_vm_id = hosting_admin.create_vm_view(vm_type.get_specs())
 | 
					 | 
				
			||||||
            plan.oppenebula_id = oppennebula_vm_id
 | 
					            plan.oppenebula_id = oppennebula_vm_id
 | 
				
			||||||
 | 
					            plan.save()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            # Send notification to ungleich as soon as VM has been booked
 | 
					            # Send notification to ungleich as soon as VM has been booked
 | 
				
			||||||
            context = {
 | 
					            context = {
 | 
				
			||||||
| 
						 | 
					@ -415,14 +410,14 @@ class VirtualMachinesPlanListView(LoginRequiredMixin, ListView):
 | 
				
			||||||
    def get_context_data(self, **kwargs):
 | 
					    def get_context_data(self, **kwargs):
 | 
				
			||||||
        context = super(VirtualMachinesPlanListView, self).get_context_data(**kwargs)
 | 
					        context = super(VirtualMachinesPlanListView, self).get_context_data(**kwargs)
 | 
				
			||||||
        context.update({
 | 
					        context.update({
 | 
				
			||||||
            'vms_opennebula': VirtualMachinePlan.get_vms(self.request.user.email)
 | 
					            'vms_opennebula': VirtualMachinePlan.get_vms(self.request.user)
 | 
				
			||||||
        })
 | 
					        })
 | 
				
			||||||
        return context
 | 
					        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))
 | 
				
			||||||
        print(VirtualMachinePlan.get_vms(self.request.user.email))
 | 
					        # print(VirtualMachinePlan.get_vms(self.request.user.))
 | 
				
			||||||
        user = self.request.user
 | 
					        user = self.request.user
 | 
				
			||||||
        self.queryset = VirtualMachinePlan.objects.active(user)
 | 
					        self.queryset = VirtualMachinePlan.objects.active(user)
 | 
				
			||||||
        return super(VirtualMachinesPlanListView, self).get_queryset()
 | 
					        return super(VirtualMachinesPlanListView, self).get_queryset()
 | 
				
			||||||
| 
						 | 
					@ -502,10 +497,10 @@ class VirtualMachineView(PermissionRequiredMixin, LoginRequiredMixin, View):
 | 
				
			||||||
    #     return final_url
 | 
					    #     return final_url
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def get(self, request, *args, **kwargs):
 | 
					    def get(self, request, *args, **kwargs):
 | 
				
			||||||
        vm_id = self.kwargs.get('pk', 24)
 | 
					        vm_id = self.kwargs.get('pk')
 | 
				
			||||||
        try:
 | 
					        try:
 | 
				
			||||||
            opennebula_vm = VirtualMachinePlan.get_vm(
 | 
					            opennebula_vm = VirtualMachinePlan.get_vm(
 | 
				
			||||||
                self.request.user.email,
 | 
					                self.request.user,
 | 
				
			||||||
                vm_id
 | 
					                vm_id
 | 
				
			||||||
            )
 | 
					            )
 | 
				
			||||||
        except Exception as error:
 | 
					        except Exception as error:
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue