Merge pull request #227 from levivm/opennebula-integration

Opennebula integration
This commit is contained in:
Levi Velázquez 2017-05-08 21:55:07 -05:00 committed by GitHub
commit 31b7b37eb9
3 changed files with 135 additions and 27 deletions

View file

@ -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

View file

@ -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

View file

@ -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: