Example #1
0
 def get_context_data(self, **kwargs):
     # Get context
     context = super(DetailView, self).get_context_data(**kwargs)
     obj = self.get_object()
     owner = self.request.user
     manager = OpenNebulaManager(email=owner.email, password=owner.password)
     if self.request.GET.get('page', '') == 'payment':
         context['page_header_text'] = _('Confirm Order')
     else:
         context['page_header_text'] = _('Invoice')
     try:
         vm = manager.get_vm(obj.vm_id)
         context['vm'] = VirtualMachineSerializer(vm).data
     except WrongIdError:
         messages.error(
             self.request,
             'The VM you are looking for is unavailable at the moment. \
                         Please contact Data Center Light support.')
         self.kwargs['error'] = 'WrongIdError'
         context['error'] = 'WrongIdError'
     except ConnectionRefusedError:
         messages.error(
             self.request,
             'In order to create a VM, you need to create/upload your SSH KEY first.'
         )
     return context
Example #2
0
def get_or_create_vm_detail(user, manager, vm_id):
    """
    Returns VMDetail object related to given vm_id. Creates the object
     if it does not exist

    :param vm_id: The ID of the VM which should be greater than 0.
    :param user: The CustomUser object that owns this VM
    :param manager: The OpenNebulaManager object
    :return: The VMDetail object. None if vm_id is less than or equal to 0.
    Also, for the cases where the VMDetail does not exist and we can not
    fetch data about the VM from OpenNebula, the function returns None
    """
    if vm_id <= 0:
        return None
    try:
        vm_detail_obj = VMDetail.objects.get(vm_id=vm_id)
    except VMDetail.DoesNotExist:
        try:
            vm_obj = manager.get_vm(vm_id)
        except (WrongIdError, ConnectionRefusedError) as e:
            logger.error(str(e))
            return None
        vm = VirtualMachineSerializer(vm_obj).data
        vm_detail_obj = VMDetail.objects.create(
            user=user,
            vm_id=vm_id,
            disk_size=vm['disk_size'],
            cores=vm['cores'],
            memory=vm['memory'],
            configuration=vm['configuration'],
            ipv4=vm['ipv4'],
            ipv6=vm['ipv6'])
    return vm_detail_obj
Example #3
0
    def get(self, request, *args, **kwargs):
        vm = self.get_object()
        try:
            serializer = VirtualMachineSerializer(vm)
            context = {
                'virtual_machine': serializer.data,
            }
        except:
            pass

        return render(request, self.template_name, context)
Example #4
0
    def get(self, request, *args, **kwargs):
        vm = self.get_object()
        if vm is None:
            return redirect(reverse('hosting:virtual_machines'))
        try:
            serializer = VirtualMachineSerializer(vm)
            context = {
                'virtual_machine': serializer.data,
            }
        except:
            pass

        return render(request, self.template_name, context)
Example #5
0
    def get_queryset(self):
        owner = self.request.user
        manager = OpenNebulaManager(email=owner.email, password=owner.password)
        try:
            queryset = manager.get_vms()
            serializer = VirtualMachineSerializer(queryset, many=True)
            return serializer.data
        except ConnectionRefusedError:
            messages.error(
                self.request,
                'We could not load your VMs due to a backend connection \
                error. Please try again in a few minutes')

            self.kwargs['error'] = 'connection'
            return []
Example #6
0
    def get_context_data(self, **kwargs):
        # Get context
        context = super(DetailView, self).get_context_data(**kwargs)

        owner = self.request.user
        manager = OpenNebulaManager(email=owner.email, password=owner.password)
        # Get vms
        queryset = manager.get_vms()
        vms = VirtualMachineSerializer(queryset, many=True).data
        # Set total price
        bill = context['bill']
        bill.total_price = 0.0
        for vm in vms:
            bill.total_price += vm['price']
        context['vms'] = vms
        return context
Example #7
0
    def post(self, request, *args, **kwargs):
        template = request.session.get('template')
        specs = request.session.get('specs')
        user = request.session.get('user')
        stripe_customer_id = request.session.get('customer')
        customer = StripeCustomer.objects.filter(id=stripe_customer_id).first()
        billing_address_data = request.session.get('billing_address_data')
        billing_address_id = request.session.get('billing_address')
        billing_address = BillingAddress.objects.filter(
            id=billing_address_id).first()
        vm_template_id = template.get('id', 1)
        final_price = specs.get('price')

        # Make stripe charge to a customer
        stripe_utils = StripeUtils()
        charge_response = stripe_utils.make_charge(amount=final_price,
                                                   customer=customer.stripe_id)
        charge = charge_response.get('response_object')

        # Check if the payment was approved
        if not charge:
            context = {}
            context.update({'paymentError': charge_response.get('error')})
            return render(request, self.payment_template_name, context)

        charge = charge_response.get('response_object')

        # Create OpenNebulaManager
        manager = OpenNebulaManager(email=settings.OPENNEBULA_USERNAME,
                                    password=settings.OPENNEBULA_PASSWORD)

        # Create a vm using oneadmin, also specify the name
        vm_id = manager.create_vm(
            template_id=vm_template_id,
            specs=specs,
            vm_name="{email}-{template_name}-{date}".format(
                email=user.get('email'),
                template_name=template.get('name'),
                date=int(datetime.now().strftime("%s"))))

        # Create a Hosting Order
        order = HostingOrder.create(price=final_price,
                                    vm_id=vm_id,
                                    customer=customer,
                                    billing_address=billing_address)

        # Create a Hosting Bill
        HostingBill.create(customer=customer, billing_address=billing_address)

        # Create Billing Address for User if he does not have one
        if not customer.user.billing_addresses.count():
            billing_address_data.update({'user': customer.user.id})
            billing_address_user_form = UserBillingAddressForm(
                billing_address_data)
            billing_address_user_form.is_valid()
            billing_address_user_form.save()

        # Associate an order with a stripe payment
        order.set_stripe_charge(charge)

        # If the Stripe payment was successed, set order status approved
        order.set_approved()

        vm = VirtualMachineSerializer(manager.get_vm(vm_id)).data

        context = {
            'name': user.get('name'),
            'email': user.get('email'),
            'cores': specs.get('cpu'),
            'memory': specs.get('memory'),
            'storage': specs.get('disk_size'),
            'price': specs.get('price'),
            'template': template.get('name'),
            'vm.name': vm['name'],
            'vm.id': vm['vm_id'],
            'order.id': order.id
        }
        email_data = {
            'subject': settings.DCL_TEXT + " Order from %s" % context['email'],
            'from_email': settings.DCL_SUPPORT_FROM_ADDRESS,
            'to': ['*****@*****.**'],
            'body':
            "\n".join(["%s=%s" % (k, v) for (k, v) in context.items()]),
            'reply_to': [context['email']],
        }
        email = EmailMessage(**email_data)
        email.send()
        request.session['order_confirmation'] = True
        return HttpResponseRedirect(reverse('datacenterlight:order_success'))
Example #8
0
def create_vm_task(self, vm_template_id, user, specs, template, order_id):
    logger.debug("Running create_vm_task on {}".format(
        current_task.request.hostname))
    vm_id = None
    try:
        final_price = (specs.get('total_price')
                       if 'total_price' in specs else specs.get('price'))

        if 'pass' in user:
            on_user = user.get('email')
            on_pass = user.get('pass')
            logger.debug("Using user {user} to create VM".format(user=on_user))
            vm_name = None
        else:
            on_user = settings.OPENNEBULA_USERNAME
            on_pass = settings.OPENNEBULA_PASSWORD
            logger.debug("Using OpenNebula admin user to create VM")
            vm_name = "{email}-{template_name}-{date}".format(
                email=user.get('email'),
                template_name=template.get('name'),
                date=int(datetime.now().strftime("%s")))

        # Create OpenNebulaManager
        manager = OpenNebulaManager(email=on_user, password=on_pass)

        vm_id = manager.create_vm(
            template_id=vm_template_id,
            specs=specs,
            ssh_key=settings.ONEADMIN_USER_SSH_PUBLIC_KEY,
            vm_name=vm_name)

        if vm_id is None:
            raise Exception("Could not create VM")

        # Update HostingOrder with the created vm_id
        hosting_order = HostingOrder.objects.filter(id=order_id).first()
        error_msg = None

        try:
            hosting_order.vm_id = vm_id
            hosting_order.save()
            logger.debug("Updated hosting_order {} with vm_id={}".format(
                hosting_order.id, vm_id))
        except Exception as ex:
            error_msg = (
                "HostingOrder with id {order_id} not found. This means that "
                "the hosting order was not created and/or it is/was not "
                "associated with VM with id {vm_id}. Details {details}".format(
                    order_id=order_id, vm_id=vm_id, details=str(ex)))
            logger.error(error_msg)

        stripe_utils = StripeUtils()
        result = stripe_utils.set_subscription_metadata(
            subscription_id=hosting_order.subscription_id,
            metadata={"VM_ID": str(vm_id)})

        if result.get('error') is not None:
            emsg = "Could not update subscription metadata for {sub}".format(
                sub=hosting_order.subscription_id)
            logger.error(emsg)
            if error_msg:
                error_msg += ". " + emsg
            else:
                error_msg = emsg

        vm = VirtualMachineSerializer(manager.get_vm(vm_id)).data

        context = {
            'name': user.get('name'),
            'email': user.get('email'),
            'cores': specs.get('cpu'),
            'memory': specs.get('memory'),
            'storage': specs.get('disk_size'),
            'price': final_price,
            'template': template.get('name'),
            'vm_name': vm.get('name'),
            'vm_id': vm['vm_id'],
            'order_id': order_id
        }

        if error_msg:
            context['errors'] = error_msg
        if 'pricing_name' in specs:
            context['pricing'] = str(
                VMPricing.get_vm_pricing_by_name(name=specs['pricing_name']))
        email_data = {
            'subject': settings.DCL_TEXT + " Order from %s" % context['email'],
            'from_email': settings.DCL_SUPPORT_FROM_ADDRESS,
            'to': ['*****@*****.**'],
            'body':
            "\n".join(["%s=%s" % (k, v) for (k, v) in context.items()]),
            'reply_to': [context['email']],
        }
        email = EmailMessage(**email_data)
        email.send()

        if 'pass' in user:
            lang = 'en-us'
            if user.get('language') is not None:
                logger.debug("Language is set to {}".format(
                    user.get('language')))
                lang = user.get('language')
            translation.activate(lang)
            # Send notification to the user as soon as VM has been booked
            context = {
                'base_url':
                "{0}://{1}".format(user.get('request_scheme'),
                                   user.get('request_host')),
                'order_url':
                reverse('hosting:orders', kwargs={'pk': order_id}),
                'page_header':
                _('Your New VM %(vm_name)s at Data Center Light') % {
                    'vm_name': vm.get('name')
                },
                'vm_name':
                vm.get('name')
            }
            email_data = {
                'subject': context.get('page_header'),
                'to': user.get('email'),
                'context': context,
                'template_name': 'new_booked_vm',
                'template_path': 'hosting/emails/',
                'from_address': settings.DCL_SUPPORT_FROM_ADDRESS,
            }
            email = BaseEmail(**email_data)
            email.send()

            # try to see if we have the IPv6 of the new vm and that if the ssh
            # keys can be configured
            vm_ipv6 = manager.get_ipv6(vm_id)
            logger.debug("New VM ID is {vm_id}".format(vm_id=vm_id))
            if vm_ipv6 is not None:
                custom_user = CustomUser.objects.get(email=user.get('email'))
                get_or_create_vm_detail(custom_user, manager, vm_id)
                if custom_user is not None:
                    public_keys = get_all_public_keys(custom_user)
                    keys = [{
                        'value': key,
                        'state': True
                    } for key in public_keys]
                    if len(keys) > 0:
                        logger.debug("Calling configure on {host} for "
                                     "{num_keys} keys".format(
                                         host=vm_ipv6, num_keys=len(keys)))
                        # Let's wait until the IP responds to ping before we
                        # run the cdist configure on the host
                        did_manage_public_key = False
                        for i in range(0, 15):
                            if ping_ok(vm_ipv6):
                                logger.debug(
                                    "{} is pingable. Doing a "
                                    "manage_public_key".format(vm_ipv6))
                                sleep(10)
                                manager.manage_public_key(keys,
                                                          hosts=[vm_ipv6])
                                did_manage_public_key = True
                                break
                            else:
                                logger.debug(
                                    "Can't ping {}. Wait 5 secs".format(
                                        vm_ipv6))
                                sleep(5)
                        if not did_manage_public_key:
                            emsg = ("Waited for over 75 seconds for {} to be "
                                    "pingable. But the VM was not reachable. "
                                    "So, gave up manage_public_key. Please do "
                                    "this manually".format(vm_ipv6))
                            logger.error(emsg)
                            email_data = {
                                'subject':
                                '{} CELERY TASK INCOMPLETE: {} not '
                                'pingable for 75 seconds'.format(
                                    settings.DCL_TEXT, vm_ipv6),
                                'from_email':
                                current_task.request.hostname,
                                'to':
                                settings.DCL_ERROR_EMAILS_TO_LIST,
                                'body':
                                emsg
                            }
                            email = EmailMessage(**email_data)
                            email.send()
    except Exception as e:
        logger.error(str(e))
        try:
            retry_task(self)
        except MaxRetriesExceededError:
            msg_text = 'Finished {} retries for create_vm_task'.format(
                self.request.retries)
            logger.error(msg_text)
            # Try sending email and stop
            email_data = {
                'subject':
                '{} CELERY TASK ERROR: {}'.format(settings.DCL_TEXT, msg_text),
                'from_email':
                current_task.request.hostname,
                'to':
                settings.DCL_ERROR_EMAILS_TO_LIST,
                'body':
                ',\n'.join(str(i) for i in self.request.args)
            }
            email = EmailMessage(**email_data)
            email.send()
            return

    return vm_id
Example #9
0
    def post(self, request, *args, **kwargs):
        form = self.get_form()
        if form.is_valid():

            # Get billing address data
            billing_address_data = form.cleaned_data

            context = self.get_context_data()

            template = request.session.get('template')
            specs = request.session.get('specs')

            vm_template_id = template.get('id', 1)

            final_price = specs.get('price')

            token = form.cleaned_data.get('token')

            owner = self.request.user

            # Get or create stripe customer
            customer = StripeCustomer.get_or_create(email=owner.email,
                                                    token=token)
            if not customer:
                form.add_error("__all__", "Invalid credit card")
                return self.render_to_response(
                    self.get_context_data(form=form))

            # Create Billing Address
            billing_address = form.save()

            # Make stripe charge to a customer
            stripe_utils = StripeUtils()
            charge_response = stripe_utils.make_charge(
                amount=final_price, customer=customer.stripe_id)
            charge = charge_response.get('response_object')

            # Check if the payment was approved
            if not charge:
                context.update({
                    'paymentError': charge_response.get('error'),
                    'form': form
                })
                return render(request, self.template_name, context)

            charge = charge_response.get('response_object')

            # Create OpenNebulaManager
            manager = OpenNebulaManager(email=owner.email,
                                        password=owner.password)
            # Get user ssh key
            if not UserHostingKey.objects.filter(
                    user=self.request.user).exists():
                context.update({'sshError': 'error', 'form': form})
                return render(request, self.template_name, context)
            # For now just get first one
            user_key = UserHostingKey.objects.filter(
                user=self.request.user).first()

            # Create a vm using logged user
            vm_id = manager.create_vm(
                template_id=vm_template_id,
                # XXX: Confi
                specs=specs,
                ssh_key=user_key.public_key,
            )

            # Create a Hosting Order
            order = HostingOrder.create(price=final_price,
                                        vm_id=vm_id,
                                        customer=customer,
                                        billing_address=billing_address)

            # Create a Hosting Bill
            bill = HostingBill.create(customer=customer,
                                      billing_address=billing_address)

            # Create Billing Address for User if he does not have one
            if not customer.user.billing_addresses.count():
                billing_address_data.update({'user': customer.user.id})
                billing_address_user_form = UserBillingAddressForm(
                    billing_address_data)
                billing_address_user_form.is_valid()
                billing_address_user_form.save()

            # Associate an order with a stripe payment
            order.set_stripe_charge(charge)

            # If the Stripe payment was successed, set order status approved
            order.set_approved()

            vm = VirtualMachineSerializer(manager.get_vm(vm_id)).data

            # Send notification to ungleich as soon as VM has been booked
            context = {
                'vm': vm,
                'order': order,
                'base_url': "{0}://{1}".format(request.scheme,
                                               request.get_host())
            }
            email_data = {
                'subject': 'New VM request',
                'to': request.user.email,
                'context': context,
                'template_name': 'new_booked_vm',
                'template_path': 'hosting/emails/'
            }
            email = BaseEmail(**email_data)
            email.send()

            return HttpResponseRedirect(
                reverse('hosting:orders', kwargs={'pk': order.id}))
        else:
            return self.form_invalid(form)