From c816d280ee0743881ff6ac113474be816d2460ff Mon Sep 17 00:00:00 2001 From: Modulos Date: Sat, 13 May 2017 05:52:27 +0200 Subject: [PATCH] Remove opennebula_functions.py --- hosting/opennebula_functions.py | 567 -------------------------------- 1 file changed, 567 deletions(-) delete mode 100644 hosting/opennebula_functions.py diff --git a/hosting/opennebula_functions.py b/hosting/opennebula_functions.py deleted file mode 100644 index aca5424d..00000000 --- a/hosting/opennebula_functions.py +++ /dev/null @@ -1,567 +0,0 @@ -import logging -import random -import socket -import string - -import oca -from django.conf import settings -from django.conf.urls import url -from django.contrib import admin -from django.contrib import messages -from django.shortcuts import redirect -from django.template.response import TemplateResponse -from django.utils.translation import ugettext_lazy as _ -from oca.exceptions import OpenNebulaException -from oca.pool import WrongNameError - -from django import forms -# Get an instance of a logger -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, email=None, password=None): - - # Get oneadmin client - self.oneadmin_client = self._get_opennebula_client( - settings.OPENNEBULA_USERNAME, - settings.OPENNEBULA_PASSWORD - ) - - # 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=settings.OPENNEBULA_PROTOCOL, - domain=settings.OPENNEBULA_DOMAIN, - port=settings.OPENNEBULA_PORT, - 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 - opennebula_user = self.oneadmin_client.call(oca.User.METHODS['allocate'], email, - password, 'core') - logger.debug( - "User {0} does not exist. Created the user. User id = {1}", - email, - opennebula_user - ) - return opennebula_user - except OpenNebulaException as err: - logger.error("Error : {0}".format(err)) - - @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 change_user_password(self, new_password): - self.oneadmin_client.call( - oca.User.METHODS['passwd'], - self.opennebula_user.id, - new_password - ) - - 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 = """ - {memory} - {vcpu} - {cpu} - - {disk_type} - {size} - - - {ssh_key} - - - """ - 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'), - ssh_key=specs.get('ssh_key') - ) - ) - - self.oneadmin_client.call( - oca.VirtualMachine.METHODS['chown'], - vm_id, - self.opennebula_user.id, - self.opennebula_user.group_ids[0] - ) - - 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 terminate_vm(self, vm_id): - - TERMINATE_ACTION = 'terminate' - vm_terminated = False - - try: - self.oneadmin_client.call( - oca.VirtualMachine.METHODS['action'], - TERMINATE_ACTION, - int(vm_id), - ) - vm_terminated = True - 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_terminated - - def get_vm_templates(self): - template_pool = oca.VmTemplatePool(self.oneadmin_client) - template_pool.info() - return template_pool - - 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.oneadmin_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 - - def get_urls(self): - urls = super().get_urls() - my_urls = [ - url(r'^$', self.admin_site.admin_view(self.show_vms, cacheable=True), name='showvms'), - url(r'^create_vm/$', self.admin_site.admin_view(self.create_vm, cacheable=True), name='createvm'), - url(r'^delete_vm/(?P\d+)/$', self.admin_site.admin_view(self.delete_vm, cacheable=True), - name='deletevm'), - url(r'^stop_vm/(?P\d+)/$', self.admin_site.admin_view(self.stop_vm, cacheable=True), name='stopvm'), - url(r'^start_vm/(?P\d+)/$', self.admin_site.admin_view(self.start_vm, cacheable=True), - name='startvm'), - ] - return my_urls + urls - - # Function to initialize opennebula client based on the logged in - # user - def init_opennebula_client(self, request): - if self.oneadmin_client is None: - self.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 - )) - logger.debug("{0}:{1}".format(settings.OPENNEBULA_USERNAME, - settings.OPENNEBULA_PASSWORD)) - logger.debug("{protocol}://{domain}:{port}{endpoint}".format( - protocol=settings.OPENNEBULA_PROTOCOL, - domain=settings.OPENNEBULA_DOMAIN, - port=settings.OPENNEBULA_PORT, - endpoint=settings.OPENNEBULA_ENDPOINT - )) - self.create_opennebula_user(request) - if self.client is None: - opennebula_user = request.user.email - # TODO: get the password stored in django - opennebula_user_password ='19737450' - self.client = oca.Client("{0}:{1}".format(opennebula_user, opennebula_user_password), - "{protocol}://{domain}:{port}{endpoint}".format( - protocol=settings.OPENNEBULA_PROTOCOL, - domain=settings.OPENNEBULA_DOMAIN, - port=settings.OPENNEBULA_PORT, - endpoint=settings.OPENNEBULA_ENDPOINT - )) - - # Function that shows the VMs of the current user - def show_vms(self, request): - vm_pool = None - try: - self.init_opennebula_client(request) - vm_pool = oca.VirtualMachinePool(self.client) - vm_pool.info() - except socket.timeout: - messages.add_message(request, messages.ERROR, _("Socket timeout error.")) - except OpenNebulaException as opennebula_err: - messages.add_message(request, messages.ERROR, _("OpenNebulaException occurred. {0}".format(opennebula_err))) - except OSError as err: - messages.add_message(request, messages.ERROR, "OS error: {0}".format(err)) - context = dict( - # Include common variables for rendering the admin template. - self.admin_site.each_context(request), - vms=vm_pool, - form=HostingManageVMForm - ) - return TemplateResponse(request, "hosting/managevms.html", context) - - # Function that shows the VMs of the current user - def show_vms_view(self, request): - """ - Implemented by Levi for the API - """ - vm_pool = None - try: - self.init_opennebula_client(request) - vm_pool = oca.VirtualMachinePool(self.client) - vm_pool.info() - except socket.timeout as socket_err: - logger.error("Socket timeout error.".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)) - context = dict( - # Include common variables for rendering the admin template. - # self.admin_site.each_context(request), - vms=vm_pool, - ) - return context - - - def create_vm_view(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 = """ - {memory} - {vcpu} - {cpu} - - {disk_type} - {size} - - - """ - vm_id = oca.VirtualMachine.allocate( - self.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') - ) - ) - # message = _("Created with id = " + str(vm_id)) - # messages.add_message(request, messages.SUCCESS, message) - 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 - - - - # Creating VM by using method allocate(client, template) - def create_vm(self, request): - # check if the request contains the template parameter, if it is - # not set warn the user of setting this. - vm_template = request.POST.get('vm_template') - if vm_template == 'select': - messages.add_message(request, messages.ERROR, "Please select a vm template") - else: - 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_template_int = int(vm_template) - if 1 <= vm_template_int <= 8: - vm_string_formatter = """ - - - {ssh_key} - - - {memory} - {vcpu} - {cpu} - - {disk_type} - {size} - {dev_prefix} - - - """ - vm_id = oca.VirtualMachine.allocate(self.client, - vm_string_formatter.format( - ssh_key='', # public key of the user - memory=1024 * vm_template_int, # memory in MB - vcpu=vm_template_int, # vpcu - cpu=0.1 * vm_template_int, # cpu - disk_type='fs', - size=10000 * vm_template_int, - dev_prefix='vd')) # We need KVM virtual disk - message = _("Created with id = " + str(vm_id)) - messages.add_message(request, messages.SUCCESS, message) - else: - messages.add_message(request, messages.ERROR, - _("Please select an appropriate value for vm template.")) - except socket.timeout as socket_err: - messages.add_message(request, messages.ERROR, _("Socket timeout error.")) - logger.error("Socket timeout error: {0}".format(socket_err)) - except OpenNebulaException as opennebula_err: - messages.add_message(request, messages.ERROR, - _("OpenNebulaException occurred. {0}".format(opennebula_err))) - logger.error("OpenNebulaException error: {0}".format(opennebula_err)) - except OSError as os_err: - messages.add_message(request, messages.ERROR, _("OS error: {0}".format(os_err))) - logger.error("OSError : {0}".format(os_err)) - except ValueError as value_err: - messages.add_message(request, messages.ERROR, - _("Please select an appropriate value for vm template.")) - logger.error("ValueError : {0}".format(value_err)) - return redirect('admin:showvms') - - # Delete VM from the pool and DB by using method finalize() - def delete_vm(self, request, vmid): - vm_id = int(vmid) - # get the desired vm from the pool - logger.debug("Deleting vm with id {0}".format(vm_id)) - vm = self.get_vm_by_id(vm_id) - if vm is None: - messages.add_message(request, messages.ERROR, _("Did not find a vm with id = {0}".format(vm_id))) - else: - logger.debug("Deleting vm_id = " + str(vm_id) + " state = " + vm.str_state) - if vm.str_state == 'PENDING' or vm.str_state == 'POWEROFF' or vm.str_state == 'ACTIVE': - vm.delete() - messages.add_message(request, messages.SUCCESS, - _("Deleted from {0} state vm with id = {1}".format(vm.str_state, str(vm_id)))) - else: - vm.finalize() - messages.add_message(request, messages.SUCCESS, - _("Deleted (using finalize()) from {0} state vm with id = {1}".format(vm.str_state, - str(vm_id)))) - return redirect('admin:showvms') - - def stop_vm(self, request, vmid): - vm_id = int(vmid) - vm = self.get_vm_by_id(vm_id) - if vm is None: - messages.add_message(request, messages.ERROR, _("Did not find a vm with id = {0}", vm_id)) - else: - vm.stop() - messages.add_message(request, messages.SUCCESS, _("Stopped the vm with id = {0}", vm_id)) - return redirect('admin:showvms') - - def start_vm(self, request, vmid): - vm_id = int(vmid) - vm = self.get_vm_by_id(vm_id) - if vm is None: - messages.add_message(request, messages.ERROR, _("Did not find a vm with id = {0}", vm_id)) - else: - vm.resume() - messages.add_message(request, messages.SUCCESS, _("Started the vm with id = {0}", vm_id)) - return redirect('admin:showvms') - - # Retrives virtual machine pool information - def get_vm_pool(self): - vm_pool = oca.VirtualMachinePool(self.client) - vm_pool.info() - return vm_pool - - def get_vm_by_id(self, vmid): - vm_pool = self.get_vm_pool() - return vm_pool.get_by_id(vmid) - - def create_opennebula_user(self, request): - # Notes: - # 1. python-oca library's oca.User.allocate(client, user, pass) - # method does not work with python-oca version oca-4.15.0a1-py3.5 - # This is because the call is missing a fourth parameter - # auth_driver. - # To overcome this issue, we make a direct call to xml-rpc method - # 'user.allocate' passing this fourth parameter. - # - # 2. We have a dummy authentication driver in opennebula and we - # use this so as to avoid opennebula authentication. However, we - # need to supply a dummy password. Without this, we can not - # create an OpenNebula user. We use dummy string 'a' as password - # for all users. - # - # 3. We user the user's email as the user name. - # 4. If the user's email is not registered with OpenNebula, - # WrongNameError is raised. We create an OpenNebula user in - # such case. - try: - user_pool = oca.UserPool(self.oneadmin_client) - user_pool.info() - opennebula_user = user_pool.get_by_name(request.user.email) - logger.debug("User {0} exists. User id = {1}".format(request.user.email, opennebula_user.id)) - except WrongNameError as wrong_name_err: - # TODO: Store this password so that we can use it later to - # connect to opennebula - password = get_random_password() - oca.User.allocate(self.oneadmin_client, request.user.email, password) - logger.debug("User {0} does not exist. Created the user. User id = {1}", request.user.email, user_id) - except OpenNebulaException as err: - messages.add_message(request, messages.ERROR, - "Error : {0}".format(err)) - logger.error("Error : {0}".format(err)) - -def set_field_html_name(cls, new_name): - """ - This creates wrapper around the normal widget rendering, - allowing for a custom field name (new_name). - """ - old_render = cls.widget.render - def _widget_render_wrapper(name, value, attrs=None): - return old_render(new_name, value, attrs) - cls.widget.render = _widget_render_wrapper - -class HostingManageVMForm(forms.Form): - vm_templates = [] - VM_CHOICES = (('1', 'disk = 10GB, vcpu=1, ram=1GB'), - ('2', 'disk = 20GB, vcpu=2, ram=2GB'), - ('3', 'disk = 40GB, vcpu=4, ram=4GB'), - ('4', 'disk = 80GB, vcpu=8, ram=8GB'), - ('5', 'disk = 160GB, vcpu=16, ram=16GB'), - ('6', 'disk = 320GB, vcpu=32, ram=32GB'), - ('7', 'disk = 640GB, vcpu=64, ram=64GB'), - ('8', 'disk = 1280GB, vcpu=128, ram=128GB')) - #for i in range(0,8): - # factor = pow(2, i) - # vm_templates.append(VMTemplate(i, VM_CHOICES[i], 10000 * factor, factor , 0.1 * factor, 1024 * factor)) - field = forms.ChoiceField(label="Choose a VM Template ", choices=VM_CHOICES, widget=forms.Select(attrs={"id": "vm_template"})) - set_field_html_name(field, 'vm_template') - - - -class VMTemplate: - """A simple representation of a VM template. - - :param template_id: The id of the template - :param label: A string representation describing the template. Used as the label in view - :param disk: VM disk space in MB - :param vcpu: Virtual cpu for the VM - :param cpu: CPU for the VM - :param ram: The RAM for the VM - """ - def __init__(self, template_id, label, disk, vcpu, cpu, ram): - self.template_id = template_id - self.label = label - self.disk = disk - self.vcpu = vcpu - self.cpu = cpu - -# Returns random password that is needed by OpenNebula -def get_random_password(): - return ''.join(random.SystemRandom().choice(string.ascii_uppercase + string.digits) for _ in range(20))