2017-08-30 10:02:53 +00:00
|
|
|
import logging
|
2017-07-06 11:18:22 +00:00
|
|
|
import uuid
|
2017-09-13 20:54:10 +00:00
|
|
|
import json
|
|
|
|
from time import sleep
|
2017-07-06 11:18:22 +00:00
|
|
|
|
2017-09-02 11:20:09 +00:00
|
|
|
from django.conf import settings
|
|
|
|
from django.contrib import messages
|
|
|
|
from django.contrib.auth.mixins import LoginRequiredMixin
|
|
|
|
from django.contrib.auth.tokens import default_token_generator
|
2017-07-06 11:18:22 +00:00
|
|
|
from django.core.files.base import ContentFile
|
2016-04-20 06:03:32 +00:00
|
|
|
from django.core.urlresolvers import reverse_lazy, reverse
|
2017-09-13 20:54:10 +00:00
|
|
|
from django.http import Http404, HttpResponseRedirect, HttpResponse
|
|
|
|
from django.shortcuts import redirect, render
|
2017-05-12 05:56:35 +00:00
|
|
|
from django.utils.http import urlsafe_base64_decode
|
2017-09-02 11:20:09 +00:00
|
|
|
from django.utils.safestring import mark_safe
|
|
|
|
from django.utils.translation import ugettext_lazy as _
|
2017-09-13 20:54:10 +00:00
|
|
|
from django.utils.translation import ugettext
|
2017-09-02 11:20:09 +00:00
|
|
|
from django.views.generic import View, CreateView, FormView, ListView, \
|
|
|
|
DetailView, \
|
|
|
|
DeleteView, TemplateView, UpdateView
|
2016-07-11 03:08:51 +00:00
|
|
|
from guardian.mixins import PermissionRequiredMixin
|
2017-09-13 00:00:05 +00:00
|
|
|
from oca.pool import WrongIdError
|
2016-05-29 18:37:43 +00:00
|
|
|
from stored_messages.api import mark_read
|
2017-09-02 11:20:09 +00:00
|
|
|
from stored_messages.models import Message
|
|
|
|
from stored_messages.settings import stored_messages_settings
|
2016-04-19 06:04:15 +00:00
|
|
|
|
2016-04-26 06:16:03 +00:00
|
|
|
from membership.models import CustomUser, StripeCustomer
|
2017-05-12 10:07:05 +00:00
|
|
|
from opennebula_api.models import OpenNebulaManager
|
2017-06-29 16:23:25 +00:00
|
|
|
from opennebula_api.serializers import VirtualMachineSerializer, \
|
2017-05-25 09:27:49 +00:00
|
|
|
VirtualMachineTemplateSerializer
|
2017-09-02 11:20:09 +00:00
|
|
|
from utils.forms import BillingAddressForm, PasswordResetRequestForm, \
|
|
|
|
UserBillingAddressForm
|
2017-08-31 16:20:02 +00:00
|
|
|
from utils.hosting_utils import get_all_public_keys
|
2017-09-02 11:20:09 +00:00
|
|
|
from utils.mailer import BaseEmail
|
|
|
|
from utils.stripe_utils import StripeUtils
|
|
|
|
from utils.views import PasswordResetViewMixin, PasswordResetConfirmViewMixin, \
|
|
|
|
LoginViewMixin
|
|
|
|
from .forms import HostingUserSignupForm, HostingUserLoginForm, \
|
|
|
|
UserHostingKeyForm, generate_ssh_key_name
|
|
|
|
from .mixins import ProcessVMSelectionMixin
|
|
|
|
from .models import HostingOrder, HostingBill, HostingPlan, UserHostingKey
|
2017-05-13 04:59:57 +00:00
|
|
|
|
2017-08-29 08:01:05 +00:00
|
|
|
logger = logging.getLogger(__name__)
|
2017-05-13 04:59:57 +00:00
|
|
|
|
2017-08-29 15:51:58 +00:00
|
|
|
CONNECTION_ERROR = "Your VMs cannot be displayed at the moment due to a \
|
|
|
|
backend connection error. please try again in a few \
|
|
|
|
minutes."
|
2016-04-19 06:04:15 +00:00
|
|
|
|
2017-05-25 09:27:49 +00:00
|
|
|
|
2017-08-22 15:15:18 +00:00
|
|
|
class DashboardView(View):
|
|
|
|
template_name = "hosting/dashboard.html"
|
|
|
|
|
|
|
|
def get_context_data(self, **kwargs):
|
|
|
|
context = {}
|
|
|
|
return context
|
|
|
|
|
|
|
|
def get(self, request, *args, **kwargs):
|
|
|
|
context = self.get_context_data()
|
|
|
|
return render(request, self.template_name, context)
|
|
|
|
|
|
|
|
|
2016-04-22 13:36:38 +00:00
|
|
|
class DjangoHostingView(ProcessVMSelectionMixin, View):
|
2016-04-19 06:04:15 +00:00
|
|
|
template_name = "hosting/django.html"
|
|
|
|
|
|
|
|
def get_context_data(self, **kwargs):
|
2016-06-07 05:29:22 +00:00
|
|
|
HOSTING = 'django'
|
2017-05-13 05:31:29 +00:00
|
|
|
templates = OpenNebulaManager().get_templates()
|
|
|
|
data = VirtualMachineTemplateSerializer(templates, many=True).data
|
2017-05-22 03:01:26 +00:00
|
|
|
configuration_options = HostingPlan.get_serialized_configs()
|
2017-05-13 05:31:29 +00:00
|
|
|
|
|
|
|
# configuration_detail = dict(VirtualMachinePlan.VM_CONFIGURATION).get(HOSTING)
|
2016-04-22 13:36:38 +00:00
|
|
|
context = {
|
2016-06-07 05:29:22 +00:00
|
|
|
'hosting': HOSTING,
|
2016-04-22 13:36:38 +00:00
|
|
|
'hosting_long': "Django",
|
2017-05-13 05:31:29 +00:00
|
|
|
# 'configuration_detail': configuration_detail,
|
2016-04-22 13:36:38 +00:00
|
|
|
'domain': "django-hosting.ch",
|
|
|
|
'google_analytics': "UA-62285904-6",
|
2017-05-13 05:31:29 +00:00
|
|
|
'vm_types': data,
|
2016-04-22 13:36:38 +00:00
|
|
|
'email': "info@django-hosting.ch",
|
2017-05-22 03:01:26 +00:00
|
|
|
'configuration_options': configuration_options,
|
|
|
|
'templates': templates,
|
2016-04-22 13:36:38 +00:00
|
|
|
}
|
2016-05-19 06:17:16 +00:00
|
|
|
|
2016-04-19 06:04:15 +00:00
|
|
|
return context
|
|
|
|
|
|
|
|
def get(self, request, *args, **kwargs):
|
2016-05-19 06:17:16 +00:00
|
|
|
request.session['hosting_url'] = reverse('hosting:djangohosting')
|
2016-04-19 06:04:15 +00:00
|
|
|
context = self.get_context_data()
|
2016-04-23 07:22:44 +00:00
|
|
|
|
2016-04-19 06:04:15 +00:00
|
|
|
return render(request, self.template_name, context)
|
2015-07-30 17:07:29 +00:00
|
|
|
|
2015-05-27 10:21:30 +00:00
|
|
|
|
2016-04-22 13:36:38 +00:00
|
|
|
class RailsHostingView(ProcessVMSelectionMixin, View):
|
2016-04-20 06:03:32 +00:00
|
|
|
template_name = "hosting/rails.html"
|
|
|
|
|
|
|
|
def get_context_data(self, **kwargs):
|
2016-06-07 05:29:22 +00:00
|
|
|
HOSTING = 'rails'
|
2017-05-13 05:31:29 +00:00
|
|
|
|
|
|
|
templates = OpenNebulaManager().get_templates()
|
2017-05-22 03:01:26 +00:00
|
|
|
configuration_options = HostingPlan.get_serialized_configs()
|
2017-05-13 05:31:29 +00:00
|
|
|
|
2016-04-22 13:36:38 +00:00
|
|
|
context = {
|
2016-06-07 05:29:22 +00:00
|
|
|
'hosting': HOSTING,
|
2016-04-22 13:36:38 +00:00
|
|
|
'hosting_long': "Ruby On Rails",
|
|
|
|
'domain': "rails-hosting.ch",
|
|
|
|
'google_analytics': "UA-62285904-5",
|
|
|
|
'email': "info@rails-hosting.ch",
|
2017-05-22 03:01:26 +00:00
|
|
|
'configuration_options': configuration_options,
|
|
|
|
'templates': templates,
|
2016-04-22 13:36:38 +00:00
|
|
|
}
|
2016-04-20 06:03:32 +00:00
|
|
|
return context
|
|
|
|
|
|
|
|
def get(self, request, *args, **kwargs):
|
2016-05-19 06:17:16 +00:00
|
|
|
request.session['hosting_url'] = reverse('hosting:railshosting')
|
2016-04-20 06:03:32 +00:00
|
|
|
context = self.get_context_data()
|
|
|
|
return render(request, self.template_name, context)
|
|
|
|
|
|
|
|
|
2016-04-22 13:36:38 +00:00
|
|
|
class NodeJSHostingView(ProcessVMSelectionMixin, View):
|
2016-04-20 06:03:32 +00:00
|
|
|
template_name = "hosting/nodejs.html"
|
|
|
|
|
|
|
|
def get_context_data(self, **kwargs):
|
2016-06-07 05:29:22 +00:00
|
|
|
HOSTING = 'nodejs'
|
2017-05-13 05:31:29 +00:00
|
|
|
# configuration_detail = dict(VirtualMachinePlan.VM_CONFIGURATION).get(HOSTING)
|
|
|
|
templates = OpenNebulaManager().get_templates()
|
2017-05-22 03:01:26 +00:00
|
|
|
configuration_options = HostingPlan.get_serialized_configs()
|
2017-05-13 05:31:29 +00:00
|
|
|
|
2016-04-22 13:36:38 +00:00
|
|
|
context = {
|
2017-05-13 05:31:29 +00:00
|
|
|
'hosting': HOSTING,
|
2016-04-22 13:36:38 +00:00
|
|
|
'hosting_long': "NodeJS",
|
2017-05-13 05:31:29 +00:00
|
|
|
# 'configuration_detail': configuration_detail,
|
2016-04-22 13:36:38 +00:00
|
|
|
'domain': "node-hosting.ch",
|
|
|
|
'google_analytics': "UA-62285904-7",
|
|
|
|
'email': "info@node-hosting.ch",
|
2017-05-22 03:01:26 +00:00
|
|
|
'templates': templates,
|
|
|
|
'configuration_options': configuration_options,
|
|
|
|
|
2016-04-22 13:36:38 +00:00
|
|
|
}
|
2016-04-20 06:03:32 +00:00
|
|
|
return context
|
|
|
|
|
|
|
|
def get(self, request, *args, **kwargs):
|
2016-05-19 06:17:16 +00:00
|
|
|
request.session['hosting_url'] = reverse('hosting:nodejshosting')
|
2016-04-20 06:03:32 +00:00
|
|
|
context = self.get_context_data()
|
2016-04-23 07:22:44 +00:00
|
|
|
|
2016-04-20 06:03:32 +00:00
|
|
|
return render(request, self.template_name, context)
|
2016-06-30 06:23:14 +00:00
|
|
|
|
|
|
|
|
|
|
|
class HostingPricingView(ProcessVMSelectionMixin, View):
|
|
|
|
template_name = "hosting/hosting_pricing.html"
|
|
|
|
|
|
|
|
def get_context_data(self, **kwargs):
|
2017-05-13 05:31:29 +00:00
|
|
|
# configuration_options = dict(VirtualMachinePlan.VM_CONFIGURATION)
|
|
|
|
templates = OpenNebulaManager().get_templates()
|
2017-05-22 03:01:26 +00:00
|
|
|
configuration_options = HostingPlan.get_serialized_configs()
|
2017-05-13 05:31:29 +00:00
|
|
|
|
2016-06-30 06:23:14 +00:00
|
|
|
context = {
|
2017-05-13 05:31:29 +00:00
|
|
|
# 'configuration_options': configuration_options,
|
2016-06-30 06:23:14 +00:00
|
|
|
'email': "info@django-hosting.ch",
|
2017-05-22 03:01:26 +00:00
|
|
|
'templates': templates,
|
|
|
|
'configuration_options': configuration_options,
|
|
|
|
|
2016-06-30 06:23:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return context
|
|
|
|
|
|
|
|
def get(self, request, *args, **kwargs):
|
|
|
|
request.session['hosting_url'] = reverse('hosting:djangohosting')
|
|
|
|
context = self.get_context_data()
|
|
|
|
|
|
|
|
return render(request, self.template_name, context)
|
2016-04-20 06:03:32 +00:00
|
|
|
|
|
|
|
|
|
|
|
class IndexView(View):
|
|
|
|
template_name = "hosting/index.html"
|
|
|
|
|
|
|
|
def get_context_data(self, **kwargs):
|
2017-05-13 05:31:29 +00:00
|
|
|
templates = OpenNebulaManager().get_templates()
|
|
|
|
data = VirtualMachineTemplateSerializer(templates, many=True).data
|
|
|
|
|
2016-04-22 13:36:38 +00:00
|
|
|
context = {
|
|
|
|
'hosting': "nodejs",
|
|
|
|
'hosting_long': "NodeJS",
|
|
|
|
'domain': "node-hosting.ch",
|
|
|
|
'google_analytics': "UA-62285904-7",
|
|
|
|
'email': "info@node-hosting.ch",
|
2017-05-13 05:31:29 +00:00
|
|
|
'vm_types': data
|
|
|
|
# 'vm_types': VirtualMachineType.get_serialized_vm_types(),
|
2016-04-22 13:36:38 +00:00
|
|
|
}
|
2016-04-20 06:03:32 +00:00
|
|
|
return context
|
|
|
|
|
|
|
|
def get(self, request, *args, **kwargs):
|
|
|
|
context = self.get_context_data()
|
2016-04-23 07:22:44 +00:00
|
|
|
|
2016-04-20 06:03:32 +00:00
|
|
|
return render(request, self.template_name, context)
|
|
|
|
|
|
|
|
|
2016-08-20 05:57:35 +00:00
|
|
|
class LoginView(LoginViewMixin):
|
|
|
|
template_name = "hosting/login.html"
|
2016-04-20 06:03:32 +00:00
|
|
|
form_class = HostingUserLoginForm
|
2017-09-07 16:54:03 +00:00
|
|
|
success_url = reverse_lazy('hosting:dashboard')
|
2016-06-04 07:59:37 +00:00
|
|
|
|
2015-07-30 17:07:29 +00:00
|
|
|
|
2016-04-20 06:03:32 +00:00
|
|
|
class SignupView(CreateView):
|
|
|
|
template_name = 'hosting/signup.html'
|
|
|
|
form_class = HostingUserSignupForm
|
2016-05-18 22:58:28 +00:00
|
|
|
model = CustomUser
|
2017-06-03 13:03:55 +00:00
|
|
|
success_url = reverse_lazy('hosting:ssh_keys')
|
2015-07-30 17:07:29 +00:00
|
|
|
|
2016-04-20 06:03:32 +00:00
|
|
|
def get_success_url(self):
|
2017-05-25 09:27:49 +00:00
|
|
|
next_url = self.request.session.get(
|
2017-05-25 14:23:31 +00:00
|
|
|
'next', self.success_url)
|
2016-04-30 18:55:55 +00:00
|
|
|
return next_url
|
2015-07-30 17:07:29 +00:00
|
|
|
|
2016-04-20 06:03:32 +00:00
|
|
|
def form_valid(self, form):
|
|
|
|
name = form.cleaned_data.get('name')
|
|
|
|
email = form.cleaned_data.get('email')
|
|
|
|
password = form.cleaned_data.get('password')
|
2017-07-26 11:15:49 +00:00
|
|
|
this_base_url = "{0}://{1}".format(self.request.scheme,
|
|
|
|
self.request.get_host())
|
|
|
|
CustomUser.register(name, password, email,
|
|
|
|
app='dcl', base_url=this_base_url)
|
2017-06-10 23:48:06 +00:00
|
|
|
|
|
|
|
return HttpResponseRedirect(reverse_lazy('hosting:signup-validate'))
|
2015-07-28 19:22:06 +00:00
|
|
|
|
2017-06-29 14:34:40 +00:00
|
|
|
|
2017-06-10 23:48:06 +00:00
|
|
|
class SignupValidateView(TemplateView):
|
|
|
|
template_name = "hosting/signup_validate.html"
|
2017-06-29 14:34:40 +00:00
|
|
|
|
2017-06-10 23:48:06 +00:00
|
|
|
def get_context_data(self, **kwargs):
|
|
|
|
context = super(SignupValidateView, self).get_context_data(**kwargs)
|
2017-07-26 11:15:49 +00:00
|
|
|
login_url = '<a href="' + \
|
2017-08-04 15:49:35 +00:00
|
|
|
reverse('hosting:login') + '">' + str(_('login')) + '</a>'
|
2017-07-26 11:15:49 +00:00
|
|
|
home_url = '<a href="' + \
|
2017-08-04 15:49:35 +00:00
|
|
|
reverse('datacenterlight:index') + '">Data Center Light</a>'
|
2017-06-29 16:23:25 +00:00
|
|
|
message = '{signup_success_message} {lurl}</a> \
|
2017-06-17 14:08:22 +00:00
|
|
|
<br />{go_back} {hurl}.'.format(
|
2017-06-29 16:23:25 +00:00
|
|
|
signup_success_message=_(
|
|
|
|
'Thank you for signing up. We have sent an email to you. '
|
|
|
|
'Please follow the instructions in it to activate your account. Once activated, you can login using'),
|
|
|
|
go_back=_('Go back to'),
|
|
|
|
lurl=login_url,
|
|
|
|
hurl=home_url
|
|
|
|
)
|
2017-06-10 23:48:06 +00:00
|
|
|
context['message'] = mark_safe(message)
|
2017-06-17 14:08:22 +00:00
|
|
|
context['section_title'] = _('Sign up')
|
2017-06-10 23:48:06 +00:00
|
|
|
return context
|
2015-08-09 20:13:38 +00:00
|
|
|
|
2017-06-29 14:34:40 +00:00
|
|
|
|
2017-06-10 23:48:06 +00:00
|
|
|
class SignupValidatedView(SignupValidateView):
|
|
|
|
template_name = "hosting/signup_validate.html"
|
2017-06-29 14:34:40 +00:00
|
|
|
|
2017-06-10 23:48:06 +00:00
|
|
|
def get_context_data(self, **kwargs):
|
|
|
|
context = super(SignupValidateView, self).get_context_data(**kwargs)
|
|
|
|
validated = CustomUser.validate_url(self.kwargs['validate_slug'])
|
2017-07-26 11:15:49 +00:00
|
|
|
login_url = '<a href="' + \
|
2017-08-04 15:49:35 +00:00
|
|
|
reverse('hosting:login') + '">' + str(_('login')) + '</a>'
|
2017-06-29 16:23:25 +00:00
|
|
|
section_title = _('Account activation')
|
2017-06-10 23:48:06 +00:00
|
|
|
if validated:
|
2017-06-29 16:23:25 +00:00
|
|
|
message = '{account_activation_string} <br /> {login_string} {lurl}.'.format(
|
2017-07-26 11:15:49 +00:00
|
|
|
account_activation_string=_(
|
|
|
|
"Your account has been activated."),
|
2017-06-29 16:23:25 +00:00
|
|
|
login_string=_("You can now"),
|
|
|
|
lurl=login_url)
|
2017-06-10 23:48:06 +00:00
|
|
|
else:
|
2017-07-26 11:15:49 +00:00
|
|
|
home_url = '<a href="' + \
|
2017-08-22 15:15:18 +00:00
|
|
|
reverse('datacenterlight:index') + \
|
2017-08-18 20:51:34 +00:00
|
|
|
'">Data Center Light</a>'
|
2017-06-17 14:08:22 +00:00
|
|
|
message = '{sorry_message} <br />{go_back_to} {hurl}'.format(
|
2017-06-29 16:23:25 +00:00
|
|
|
sorry_message=_("Sorry. Your request is invalid."),
|
|
|
|
go_back_to=_('Go back to'),
|
|
|
|
hurl=home_url
|
|
|
|
)
|
2017-06-10 23:48:06 +00:00
|
|
|
context['message'] = mark_safe(message)
|
|
|
|
context['section_title'] = section_title
|
|
|
|
return context
|
2015-07-30 17:07:29 +00:00
|
|
|
|
|
|
|
|
Created signup view. Added login after signup.Added signup url to nosystem app urls.py. Added logout view, Added logout button on nabber, Added password reset form, Added password view , Added password reset html, Added password reset email for nosystemd app. Added confirm_reset_password.html, Added confirm_ reset password view, Added confirm reset password form, Fixed reset password token generation, Started donation view, Added donation view, Added donation.html, Added donation form, Adding donation.js lib in order to capture stripe payments for nosystem app.
2016-07-22 06:24:32 +00:00
|
|
|
class PasswordResetView(PasswordResetViewMixin):
|
2017-06-12 15:21:48 +00:00
|
|
|
site = 'dcl'
|
2016-06-21 05:10:38 +00:00
|
|
|
template_name = 'hosting/reset_password.html'
|
|
|
|
form_class = PasswordResetRequestForm
|
|
|
|
success_url = reverse_lazy('hosting:login')
|
Created signup view. Added login after signup.Added signup url to nosystem app urls.py. Added logout view, Added logout button on nabber, Added password reset form, Added password view , Added password reset html, Added password reset email for nosystemd app. Added confirm_reset_password.html, Added confirm_ reset password view, Added confirm reset password form, Fixed reset password token generation, Started donation view, Added donation view, Added donation.html, Added donation form, Adding donation.js lib in order to capture stripe payments for nosystem app.
2016-07-22 06:24:32 +00:00
|
|
|
template_email_path = 'hosting/emails/'
|
2016-06-21 05:10:38 +00:00
|
|
|
|
|
|
|
|
Created signup view. Added login after signup.Added signup url to nosystem app urls.py. Added logout view, Added logout button on nabber, Added password reset form, Added password view , Added password reset html, Added password reset email for nosystemd app. Added confirm_reset_password.html, Added confirm_ reset password view, Added confirm reset password form, Fixed reset password token generation, Started donation view, Added donation view, Added donation.html, Added donation form, Adding donation.js lib in order to capture stripe payments for nosystem app.
2016-07-22 06:24:32 +00:00
|
|
|
class PasswordResetConfirmView(PasswordResetConfirmViewMixin):
|
2016-06-21 05:10:38 +00:00
|
|
|
template_name = 'hosting/confirm_reset_password.html'
|
|
|
|
success_url = reverse_lazy('hosting:login')
|
|
|
|
|
2017-05-12 05:56:35 +00:00
|
|
|
def post(self, request, uidb64=None, token=None, *arg, **kwargs):
|
|
|
|
try:
|
|
|
|
uid = urlsafe_base64_decode(uidb64)
|
|
|
|
user = CustomUser.objects.get(pk=uid)
|
|
|
|
|
|
|
|
opennebula_client = OpenNebulaManager(
|
|
|
|
email=user.email,
|
|
|
|
password=user.password,
|
|
|
|
)
|
|
|
|
|
|
|
|
except (TypeError, ValueError, OverflowError, CustomUser.DoesNotExist):
|
|
|
|
user = None
|
|
|
|
opennebula_client = None
|
|
|
|
|
|
|
|
form = self.form_class(request.POST)
|
|
|
|
|
2017-09-02 11:20:09 +00:00
|
|
|
if user is not None and default_token_generator.check_token(user,
|
|
|
|
token):
|
2017-05-12 05:56:35 +00:00
|
|
|
if form.is_valid():
|
|
|
|
new_password = form.cleaned_data['new_password2']
|
|
|
|
user.set_password(new_password)
|
|
|
|
user.save()
|
2017-09-02 11:20:09 +00:00
|
|
|
messages.success(request, _('Password has been reset.'))
|
2017-05-12 05:56:35 +00:00
|
|
|
|
|
|
|
# Change opennebula password
|
|
|
|
opennebula_client.change_user_password(new_password)
|
|
|
|
|
|
|
|
return self.form_valid(form)
|
|
|
|
else:
|
2017-05-25 09:27:49 +00:00
|
|
|
messages.error(
|
2017-09-02 11:20:09 +00:00
|
|
|
request, _('Password reset has not been successful.'))
|
|
|
|
form.add_error(None,
|
|
|
|
_('Password reset has not been successful.'))
|
2017-05-12 05:56:35 +00:00
|
|
|
return self.form_invalid(form)
|
|
|
|
|
|
|
|
else:
|
2017-09-02 11:20:09 +00:00
|
|
|
error_msg = _('The reset password link is no longer valid.')
|
|
|
|
messages.error(request, _(error_msg))
|
|
|
|
form.add_error(None, error_msg)
|
2017-05-12 05:56:35 +00:00
|
|
|
return self.form_invalid(form)
|
|
|
|
|
2016-06-21 05:10:38 +00:00
|
|
|
|
2016-07-05 04:44:15 +00:00
|
|
|
class NotificationsView(LoginRequiredMixin, TemplateView):
|
2016-05-29 18:37:43 +00:00
|
|
|
template_name = 'hosting/notifications.html'
|
2016-07-05 04:44:15 +00:00
|
|
|
login_url = reverse_lazy('hosting:login')
|
2016-05-29 18:37:43 +00:00
|
|
|
|
|
|
|
def get_context_data(self, **kwargs):
|
|
|
|
context = super(NotificationsView, self).get_context_data(**kwargs)
|
|
|
|
backend = stored_messages_settings.STORAGE_BACKEND()
|
|
|
|
unread_notifications = backend.inbox_list(self.request.user)
|
|
|
|
read_notifications = backend.archive_list(self.request.user)
|
|
|
|
context.update({
|
|
|
|
'unread_notifications': unread_notifications,
|
|
|
|
'all_notifications': read_notifications + unread_notifications
|
|
|
|
})
|
|
|
|
return context
|
|
|
|
|
|
|
|
|
|
|
|
class MarkAsReadNotificationView(LoginRequiredMixin, UpdateView):
|
|
|
|
model = Message
|
|
|
|
success_url = reverse_lazy('hosting:notifications')
|
2016-07-05 04:44:15 +00:00
|
|
|
login_url = reverse_lazy('hosting:login')
|
2016-05-29 18:37:43 +00:00
|
|
|
fields = '__all__'
|
|
|
|
|
|
|
|
def post(self, *args, **kwargs):
|
|
|
|
message = self.get_object()
|
|
|
|
backend = stored_messages_settings.STORAGE_BACKEND()
|
|
|
|
backend.archive_store([self.request.user], message)
|
|
|
|
mark_read(self.request.user, message)
|
|
|
|
return HttpResponseRedirect(reverse('hosting:notifications'))
|
|
|
|
|
|
|
|
|
2017-06-03 11:33:05 +00:00
|
|
|
class SSHKeyDeleteView(LoginRequiredMixin, DeleteView):
|
|
|
|
login_url = reverse_lazy('hosting:login')
|
2017-06-03 13:03:55 +00:00
|
|
|
success_url = reverse_lazy('hosting:ssh_keys')
|
2017-06-03 11:33:05 +00:00
|
|
|
model = UserHostingKey
|
|
|
|
|
2017-08-04 15:24:28 +00:00
|
|
|
def get_object(self, queryset=None):
|
2017-08-04 15:49:35 +00:00
|
|
|
""" Hook to ensure UserHostingKey object is owned by request.user.
|
|
|
|
We reply with a Http404 if the user is not the owner of the key.
|
|
|
|
"""
|
2017-08-04 15:24:28 +00:00
|
|
|
obj = super(SSHKeyDeleteView, self).get_object()
|
2017-08-04 15:49:35 +00:00
|
|
|
if not obj.user == self.request.user:
|
2017-08-04 15:24:28 +00:00
|
|
|
raise Http404
|
|
|
|
return obj
|
|
|
|
|
2017-06-03 13:03:55 +00:00
|
|
|
def delete(self, request, *args, **kwargs):
|
|
|
|
owner = self.request.user
|
2017-08-30 07:42:56 +00:00
|
|
|
manager = OpenNebulaManager(
|
|
|
|
email=owner.email,
|
|
|
|
password=owner.password
|
|
|
|
)
|
2017-06-03 13:03:55 +00:00
|
|
|
pk = self.kwargs.get('pk')
|
|
|
|
# Get user ssh key
|
2017-06-09 20:36:14 +00:00
|
|
|
public_key = UserHostingKey.objects.get(pk=pk).public_key
|
2017-08-30 07:42:56 +00:00
|
|
|
manager.manage_public_key([{'value': public_key, 'state': False}])
|
2017-06-03 13:03:55 +00:00
|
|
|
|
|
|
|
return super(SSHKeyDeleteView, self).delete(request, *args, **kwargs)
|
|
|
|
|
2017-06-29 14:34:40 +00:00
|
|
|
|
2017-06-03 13:03:55 +00:00
|
|
|
class SSHKeyListView(LoginRequiredMixin, ListView):
|
|
|
|
template_name = "hosting/user_keys.html"
|
2016-07-05 04:44:15 +00:00
|
|
|
login_url = reverse_lazy('hosting:login')
|
2017-06-03 13:03:55 +00:00
|
|
|
context_object_name = "keys"
|
|
|
|
model = UserHostingKey
|
|
|
|
paginate_by = 10
|
|
|
|
ordering = '-id'
|
2016-05-20 21:11:42 +00:00
|
|
|
|
2017-06-03 13:03:55 +00:00
|
|
|
def get_queryset(self):
|
|
|
|
user = self.request.user
|
|
|
|
self.queryset = UserHostingKey.objects.filter(user=user)
|
|
|
|
return super(SSHKeyListView, self).get_queryset()
|
2017-05-04 04:19:32 +00:00
|
|
|
|
2017-06-03 13:03:55 +00:00
|
|
|
def render_to_response(self, context, **response_kwargs):
|
|
|
|
if not self.queryset:
|
2017-07-12 05:21:43 +00:00
|
|
|
return HttpResponseRedirect(reverse('hosting:choice_ssh_keys'))
|
2017-09-02 11:20:09 +00:00
|
|
|
return super(SSHKeyListView, self).render_to_response(context,
|
|
|
|
**response_kwargs)
|
2017-06-03 13:03:55 +00:00
|
|
|
|
|
|
|
|
2017-07-05 13:57:49 +00:00
|
|
|
class SSHKeyChoiceView(LoginRequiredMixin, View):
|
|
|
|
template_name = "hosting/choice_ssh_keys.html"
|
|
|
|
login_url = reverse_lazy('hosting:login')
|
|
|
|
|
|
|
|
def get(self, request, *args, **kwargs):
|
|
|
|
context = {}
|
|
|
|
return render(request, self.template_name, context)
|
|
|
|
|
2017-07-06 08:47:12 +00:00
|
|
|
def post(self, request, *args, **kwargs):
|
|
|
|
name = generate_ssh_key_name()
|
|
|
|
private_key, public_key = UserHostingKey.generate_keys()
|
2017-07-06 11:18:22 +00:00
|
|
|
content = ContentFile(private_key)
|
2017-07-26 11:15:49 +00:00
|
|
|
ssh_key = UserHostingKey.objects.create(
|
|
|
|
user=request.user, public_key=public_key, name=name)
|
2017-07-06 11:18:22 +00:00
|
|
|
filename = name + '_' + str(uuid.uuid4())[:8] + '_private.pem'
|
|
|
|
ssh_key.private_key.save(filename, content)
|
2017-08-30 10:02:53 +00:00
|
|
|
owner = self.request.user
|
|
|
|
manager = OpenNebulaManager(
|
|
|
|
email=owner.email,
|
|
|
|
password=owner.password
|
|
|
|
)
|
|
|
|
public_key_str = public_key.decode()
|
|
|
|
manager.manage_public_key([{'value': public_key_str, 'state': True}])
|
2017-07-06 08:47:12 +00:00
|
|
|
return redirect(reverse_lazy('hosting:ssh_keys'), foo='bar')
|
|
|
|
|
2017-07-05 13:57:49 +00:00
|
|
|
|
2017-06-03 13:03:55 +00:00
|
|
|
class SSHKeyCreateView(LoginRequiredMixin, FormView):
|
|
|
|
form_class = UserHostingKeyForm
|
|
|
|
model = UserHostingKey
|
|
|
|
template_name = 'hosting/user_key.html'
|
|
|
|
login_url = reverse_lazy('hosting:login')
|
|
|
|
context_object_name = "virtual_machine"
|
|
|
|
success_url = reverse_lazy('hosting:ssh_keys')
|
2017-05-04 04:19:32 +00:00
|
|
|
|
|
|
|
def get_form_kwargs(self):
|
2017-06-03 13:03:55 +00:00
|
|
|
kwargs = super(SSHKeyCreateView, self).get_form_kwargs()
|
2017-05-04 04:19:32 +00:00
|
|
|
kwargs.update({'request': self.request})
|
|
|
|
return kwargs
|
2016-05-20 21:11:42 +00:00
|
|
|
|
2017-05-04 04:19:32 +00:00
|
|
|
def form_valid(self, form):
|
|
|
|
form.save()
|
2017-07-06 11:18:22 +00:00
|
|
|
if 'dcl-generated-key-' in form.instance.name:
|
|
|
|
content = ContentFile(form.cleaned_data.get('private_key'))
|
2017-07-26 11:15:49 +00:00
|
|
|
filename = form.cleaned_data.get(
|
|
|
|
'name') + '_' + str(uuid.uuid4())[:8] + '_private.pem'
|
2017-07-06 11:18:22 +00:00
|
|
|
form.instance.private_key.save(filename, content)
|
2017-05-04 04:19:32 +00:00
|
|
|
context = self.get_context_data()
|
|
|
|
|
2017-05-24 15:58:16 +00:00
|
|
|
next_url = self.request.session.get(
|
|
|
|
'next',
|
|
|
|
reverse('hosting:create_virtual_machine')
|
|
|
|
)
|
|
|
|
|
|
|
|
if 'next' in self.request.session:
|
|
|
|
context.update({
|
|
|
|
'next_url': next_url
|
|
|
|
})
|
|
|
|
del (self.request.session['next'])
|
|
|
|
|
2017-05-04 04:19:32 +00:00
|
|
|
if form.cleaned_data.get('private_key'):
|
2016-05-24 06:19:49 +00:00
|
|
|
context.update({
|
2017-05-04 04:19:32 +00:00
|
|
|
'private_key': form.cleaned_data.get('private_key'),
|
2017-05-11 05:11:33 +00:00
|
|
|
'key_name': form.cleaned_data.get('name'),
|
2017-05-22 03:35:43 +00:00
|
|
|
'form': UserHostingKeyForm(request=self.request),
|
2016-05-24 06:19:49 +00:00
|
|
|
})
|
2017-05-04 04:19:32 +00:00
|
|
|
|
2017-05-25 13:50:10 +00:00
|
|
|
owner = self.request.user
|
2017-08-29 15:51:58 +00:00
|
|
|
manager = OpenNebulaManager(
|
|
|
|
email=owner.email,
|
|
|
|
password=owner.password
|
|
|
|
)
|
|
|
|
public_key = form.cleaned_data['public_key']
|
|
|
|
if type(public_key) is bytes:
|
|
|
|
public_key = public_key.decode()
|
2017-08-30 07:42:56 +00:00
|
|
|
manager.manage_public_key([{'value': public_key, 'state': True}])
|
2017-06-03 13:03:55 +00:00
|
|
|
return HttpResponseRedirect(self.success_url)
|
2016-05-20 21:11:42 +00:00
|
|
|
|
2017-05-11 05:11:33 +00:00
|
|
|
def post(self, request, *args, **kwargs):
|
|
|
|
form = self.get_form()
|
2017-07-06 08:47:12 +00:00
|
|
|
required = 'add_ssh' in self.request.POST
|
|
|
|
form.fields['name'].required = required
|
|
|
|
form.fields['public_key'].required = required
|
2017-05-11 05:11:33 +00:00
|
|
|
if form.is_valid():
|
|
|
|
return self.form_valid(form)
|
|
|
|
else:
|
|
|
|
return self.form_invalid(form)
|
|
|
|
|
2016-05-20 21:13:17 +00:00
|
|
|
|
2017-08-24 16:41:15 +00:00
|
|
|
class SettingsView(LoginRequiredMixin, FormView):
|
|
|
|
template_name = "hosting/settings.html"
|
|
|
|
login_url = reverse_lazy('hosting:login')
|
|
|
|
form_class = BillingAddressForm
|
|
|
|
|
2017-08-29 12:12:35 +00:00
|
|
|
def get_form(self, form_class):
|
|
|
|
"""
|
|
|
|
Check if the user already saved contact details. If so, then show
|
|
|
|
the form populated with those details, to let user change them.
|
|
|
|
"""
|
|
|
|
return form_class(
|
|
|
|
instance=self.request.user.billing_addresses.first(),
|
|
|
|
**self.get_form_kwargs())
|
2017-08-24 16:41:15 +00:00
|
|
|
|
|
|
|
def get_context_data(self, **kwargs):
|
|
|
|
context = super(SettingsView, self).get_context_data(**kwargs)
|
|
|
|
# Get user
|
|
|
|
user = self.request.user
|
|
|
|
# Get user last order
|
|
|
|
last_hosting_order = HostingOrder.objects.filter(
|
|
|
|
customer__user=user).last()
|
|
|
|
# If user has already an hosting order, get the credit card data from
|
|
|
|
# it
|
|
|
|
if last_hosting_order:
|
|
|
|
credit_card_data = last_hosting_order.get_cc_data()
|
|
|
|
context.update({
|
|
|
|
'credit_card_data': credit_card_data if credit_card_data else None,
|
|
|
|
})
|
|
|
|
context.update({
|
|
|
|
'stripe_key': settings.STRIPE_API_PUBLIC_KEY
|
|
|
|
})
|
|
|
|
|
|
|
|
return context
|
|
|
|
|
2017-08-29 12:12:35 +00:00
|
|
|
def post(self, request, *args, **kwargs):
|
|
|
|
form = self.get_form()
|
|
|
|
if form.is_valid():
|
|
|
|
billing_address_data = form.cleaned_data
|
|
|
|
billing_address_data.update({
|
|
|
|
'user': self.request.user.id
|
|
|
|
})
|
|
|
|
billing_address_user_form = UserBillingAddressForm(
|
|
|
|
instance=self.request.user.billing_addresses.first(),
|
|
|
|
data=billing_address_data)
|
|
|
|
billing_address_user_form.save()
|
|
|
|
return self.render_to_response(self.get_context_data())
|
|
|
|
else:
|
|
|
|
billing_address_data = form.cleaned_data
|
|
|
|
return self.form_invalid(form)
|
|
|
|
|
2017-08-24 16:41:15 +00:00
|
|
|
|
2016-05-12 06:57:34 +00:00
|
|
|
class PaymentVMView(LoginRequiredMixin, FormView):
|
2016-04-22 13:36:38 +00:00
|
|
|
template_name = 'hosting/payment.html'
|
2016-05-12 06:57:34 +00:00
|
|
|
login_url = reverse_lazy('hosting:login')
|
2016-04-23 07:22:44 +00:00
|
|
|
form_class = BillingAddressForm
|
2016-04-22 13:36:38 +00:00
|
|
|
|
2017-05-11 05:11:33 +00:00
|
|
|
def get_form_kwargs(self):
|
|
|
|
current_billing_address = self.request.user.billing_addresses.first()
|
|
|
|
form_kwargs = super(PaymentVMView, self).get_form_kwargs()
|
|
|
|
if not current_billing_address:
|
|
|
|
return form_kwargs
|
|
|
|
|
|
|
|
form_kwargs.update({
|
|
|
|
'initial': {
|
2017-07-16 17:03:52 +00:00
|
|
|
'cardholder_name': current_billing_address.cardholder_name,
|
2017-05-11 05:11:33 +00:00
|
|
|
'street_address': current_billing_address.street_address,
|
|
|
|
'city': current_billing_address.city,
|
|
|
|
'postal_code': current_billing_address.postal_code,
|
|
|
|
'country': current_billing_address.country,
|
|
|
|
}
|
|
|
|
})
|
|
|
|
return form_kwargs
|
|
|
|
|
2016-04-22 13:36:38 +00:00
|
|
|
def get_context_data(self, **kwargs):
|
|
|
|
context = super(PaymentVMView, self).get_context_data(**kwargs)
|
2017-05-11 05:11:33 +00:00
|
|
|
# Get user
|
|
|
|
user = self.request.user
|
|
|
|
|
|
|
|
# Get user last order
|
2017-05-25 09:27:49 +00:00
|
|
|
last_hosting_order = HostingOrder.objects.filter(
|
|
|
|
customer__user=user).last()
|
2017-05-11 05:11:33 +00:00
|
|
|
|
2017-05-25 09:27:49 +00:00
|
|
|
# If user has already an hosting order, get the credit card data from
|
|
|
|
# it
|
2017-05-11 05:11:33 +00:00
|
|
|
if last_hosting_order:
|
|
|
|
credit_card_data = last_hosting_order.get_cc_data()
|
|
|
|
context.update({
|
|
|
|
'credit_card_data': credit_card_data if credit_card_data else None,
|
|
|
|
})
|
|
|
|
|
2016-04-22 13:36:38 +00:00
|
|
|
context.update({
|
|
|
|
'stripe_key': settings.STRIPE_API_PUBLIC_KEY
|
|
|
|
})
|
2016-05-25 06:23:32 +00:00
|
|
|
|
2016-04-22 13:36:38 +00:00
|
|
|
return context
|
|
|
|
|
2017-05-12 05:56:35 +00:00
|
|
|
def get(self, request, *args, **kwargs):
|
2017-06-29 14:34:40 +00:00
|
|
|
if not UserHostingKey.objects.filter(user=self.request.user).exists():
|
2017-05-12 05:56:35 +00:00
|
|
|
messages.success(
|
|
|
|
request,
|
|
|
|
'In order to create a VM, you create/upload your SSH KEY first.'
|
|
|
|
)
|
2017-06-03 13:03:55 +00:00
|
|
|
return HttpResponseRedirect(reverse('hosting:ssh_keys'))
|
2017-05-12 05:56:35 +00:00
|
|
|
|
2017-05-24 15:58:16 +00:00
|
|
|
if 'next' in request.session:
|
|
|
|
del request.session['next']
|
|
|
|
|
2017-05-12 05:56:35 +00:00
|
|
|
return self.render_to_response(self.get_context_data())
|
|
|
|
|
2016-04-23 07:22:44 +00:00
|
|
|
def post(self, request, *args, **kwargs):
|
|
|
|
form = self.get_form()
|
|
|
|
if form.is_valid():
|
2017-05-11 05:11:33 +00:00
|
|
|
|
|
|
|
# Get billing address data
|
|
|
|
billing_address_data = form.cleaned_data
|
|
|
|
|
2016-04-27 06:54:15 +00:00
|
|
|
context = self.get_context_data()
|
2017-05-11 05:11:33 +00:00
|
|
|
|
2017-05-13 11:47:53 +00:00
|
|
|
template = request.session.get('template')
|
|
|
|
specs = request.session.get('specs')
|
2017-04-29 17:39:55 +00:00
|
|
|
|
2017-05-13 11:47:53 +00:00
|
|
|
vm_template_id = template.get('id', 1)
|
2017-04-29 17:39:55 +00:00
|
|
|
|
2017-05-13 11:47:53 +00:00
|
|
|
final_price = specs.get('price')
|
2017-04-29 17:39:55 +00:00
|
|
|
|
2016-04-26 06:16:03 +00:00
|
|
|
token = form.cleaned_data.get('token')
|
2015-08-09 20:13:38 +00:00
|
|
|
|
2017-05-12 10:07:05 +00:00
|
|
|
owner = self.request.user
|
|
|
|
|
2016-04-26 06:16:03 +00:00
|
|
|
# Get or create stripe customer
|
2017-05-12 10:07:05 +00:00
|
|
|
customer = StripeCustomer.get_or_create(email=owner.email,
|
2016-04-26 06:16:03 +00:00
|
|
|
token=token)
|
2016-05-20 22:03:17 +00:00
|
|
|
if not customer:
|
2017-08-07 14:23:58 +00:00
|
|
|
msg = _("Invalid credit card")
|
2017-08-22 15:15:18 +00:00
|
|
|
messages.add_message(
|
2017-09-02 11:20:09 +00:00
|
|
|
self.request, messages.ERROR, msg,
|
|
|
|
extra_tags='make_charge_error')
|
|
|
|
return HttpResponseRedirect(
|
|
|
|
reverse('hosting:payment') + '#payment_error')
|
2016-05-20 22:03:17 +00:00
|
|
|
|
2016-04-26 06:16:03 +00:00
|
|
|
# Create Billing Address
|
|
|
|
billing_address = form.save()
|
|
|
|
|
|
|
|
# Make stripe charge to a customer
|
|
|
|
stripe_utils = StripeUtils()
|
2016-04-27 06:54:15 +00:00
|
|
|
charge_response = stripe_utils.make_charge(amount=final_price,
|
2016-04-30 18:55:55 +00:00
|
|
|
customer=customer.stripe_id)
|
2015-09-22 11:37:22 +00:00
|
|
|
|
2016-04-30 18:55:55 +00:00
|
|
|
# Check if the payment was approved
|
2017-08-23 20:59:24 +00:00
|
|
|
if not charge_response.get('response_object'):
|
2017-08-07 14:02:47 +00:00
|
|
|
msg = charge_response.get('error')
|
2017-08-22 15:15:18 +00:00
|
|
|
messages.add_message(
|
2017-09-02 11:20:09 +00:00
|
|
|
self.request, messages.ERROR, msg,
|
|
|
|
extra_tags='make_charge_error')
|
|
|
|
return HttpResponseRedirect(
|
|
|
|
reverse('hosting:payment') + '#payment_error')
|
2016-04-26 06:16:03 +00:00
|
|
|
|
2016-04-27 06:54:15 +00:00
|
|
|
charge = charge_response.get('response_object')
|
2016-04-26 06:16:03 +00:00
|
|
|
|
2017-05-12 17:13:18 +00:00
|
|
|
# Create OpenNebulaManager
|
2017-05-12 10:07:05 +00:00
|
|
|
manager = OpenNebulaManager(email=owner.email,
|
2017-05-13 03:50:56 +00:00
|
|
|
password=owner.password)
|
2017-05-12 05:56:35 +00:00
|
|
|
# Get user ssh key
|
2017-09-02 11:20:09 +00:00
|
|
|
if not UserHostingKey.objects.filter(
|
|
|
|
user=self.request.user).exists():
|
2017-06-01 22:49:17 +00:00
|
|
|
context.update({
|
|
|
|
'sshError': 'error',
|
|
|
|
'form': form
|
|
|
|
})
|
|
|
|
return render(request, self.template_name, context)
|
2017-06-29 14:34:40 +00:00
|
|
|
|
2017-05-09 02:54:12 +00:00
|
|
|
# Create a vm using logged user
|
2017-05-12 17:13:18 +00:00
|
|
|
vm_id = manager.create_vm(
|
2017-05-13 04:59:57 +00:00
|
|
|
template_id=vm_template_id,
|
2017-05-13 11:47:53 +00:00
|
|
|
specs=specs,
|
2017-08-29 15:51:58 +00:00
|
|
|
ssh_key=settings.ONEADMIN_USER_SSH_PUBLIC_KEY,
|
2017-05-12 17:13:18 +00:00
|
|
|
)
|
|
|
|
|
2017-05-12 10:07:05 +00:00
|
|
|
# Create a Hosting Order
|
2017-05-12 17:13:18 +00:00
|
|
|
order = HostingOrder.create(
|
|
|
|
price=final_price,
|
|
|
|
vm_id=vm_id,
|
|
|
|
customer=customer,
|
|
|
|
billing_address=billing_address
|
2017-05-09 02:49:40 +00:00
|
|
|
)
|
|
|
|
|
2017-05-12 10:07:05 +00:00
|
|
|
# Create a Hosting Bill
|
2017-07-06 18:42:29 +00:00
|
|
|
HostingBill.create(
|
2017-07-26 11:15:49 +00:00
|
|
|
customer=customer, billing_address=billing_address)
|
2017-05-12 10:07:05 +00:00
|
|
|
|
2017-05-12 17:13:18 +00:00
|
|
|
# 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
|
|
|
|
})
|
2017-05-25 09:27:49 +00:00
|
|
|
billing_address_user_form = UserBillingAddressForm(
|
|
|
|
billing_address_data)
|
2017-05-12 17:13:18 +00:00
|
|
|
billing_address_user_form.is_valid()
|
|
|
|
billing_address_user_form.save()
|
2017-05-12 10:07:05 +00:00
|
|
|
|
2016-04-27 06:54:15 +00:00
|
|
|
# Associate an order with a stripe payment
|
|
|
|
order.set_stripe_charge(charge)
|
2015-07-29 23:09:23 +00:00
|
|
|
|
2016-04-27 06:54:15 +00:00
|
|
|
# If the Stripe payment was successed, set order status approved
|
|
|
|
order.set_approved()
|
2016-05-25 06:23:32 +00:00
|
|
|
|
2017-05-12 10:07:05 +00:00
|
|
|
vm = VirtualMachineSerializer(manager.get_vm(vm_id)).data
|
2017-04-29 17:39:55 +00:00
|
|
|
|
2017-09-02 16:38:25 +00:00
|
|
|
# Send notification to the user as soon as VM has been booked
|
2016-06-05 20:49:51 +00:00
|
|
|
context = {
|
2017-05-12 10:07:05 +00:00
|
|
|
'vm': vm,
|
2016-06-16 06:04:48 +00:00
|
|
|
'order': order,
|
2017-09-02 11:20:09 +00:00
|
|
|
'base_url': "{0}://{1}".format(request.scheme,
|
2017-09-02 16:38:25 +00:00
|
|
|
request.get_host()),
|
|
|
|
'page_header': _(
|
2017-09-02 19:35:57 +00:00
|
|
|
'Your New VM %(vm_name)s at Data Center Light') % {
|
2017-09-13 20:54:10 +00:00
|
|
|
'vm_name': vm.get('name')}
|
2016-06-05 20:49:51 +00:00
|
|
|
}
|
2016-05-25 06:23:32 +00:00
|
|
|
email_data = {
|
2017-09-02 16:38:25 +00:00
|
|
|
'subject': context.get('page_header'),
|
2016-06-16 06:04:48 +00:00
|
|
|
'to': request.user.email,
|
2016-06-05 20:49:51 +00:00
|
|
|
'context': context,
|
2016-05-25 06:23:32 +00:00
|
|
|
'template_name': 'new_booked_vm',
|
2017-09-02 17:17:31 +00:00
|
|
|
'template_path': 'hosting/emails/',
|
2017-09-02 18:42:58 +00:00
|
|
|
'from_address': settings.DCL_SUPPORT_FROM_ADDRESS,
|
2016-05-25 06:23:32 +00:00
|
|
|
}
|
|
|
|
email = BaseEmail(**email_data)
|
|
|
|
email.send()
|
|
|
|
|
2017-08-31 16:20:02 +00:00
|
|
|
# try to see if we have the IP and that if the ssh keys can
|
|
|
|
# be configured
|
|
|
|
new_host = manager.get_primary_ipv4(vm_id)
|
|
|
|
if new_host is not None:
|
|
|
|
public_keys = get_all_public_keys(owner)
|
|
|
|
keys = [{'value': key, 'state': True} for key in public_keys]
|
|
|
|
logger.debug(
|
|
|
|
"Calling configure on {host} for {num_keys} keys".format(
|
|
|
|
host=new_host, num_keys=len(keys)))
|
|
|
|
# Let's delay the task by 75 seconds to be sure that we run
|
|
|
|
# the cdist configure after the host is up
|
|
|
|
manager.manage_public_key(keys, hosts=[new_host], countdown=75)
|
|
|
|
|
2017-07-30 16:03:16 +00:00
|
|
|
return HttpResponseRedirect(
|
2017-09-02 11:20:09 +00:00
|
|
|
"{url}?{query_params}".format(
|
|
|
|
url=reverse('hosting:orders', kwargs={'pk': order.id}),
|
|
|
|
query_params='page=payment'))
|
2016-04-23 07:22:44 +00:00
|
|
|
else:
|
|
|
|
return self.form_invalid(form)
|
2016-04-27 06:54:15 +00:00
|
|
|
|
2016-04-30 18:55:55 +00:00
|
|
|
|
2017-09-02 11:20:09 +00:00
|
|
|
class OrdersHostingDetailView(PermissionRequiredMixin, LoginRequiredMixin,
|
|
|
|
DetailView):
|
2016-05-03 05:59:40 +00:00
|
|
|
template_name = "hosting/order_detail.html"
|
2016-05-14 06:42:42 +00:00
|
|
|
context_object_name = "order"
|
2016-04-29 06:53:24 +00:00
|
|
|
login_url = reverse_lazy('hosting:login')
|
2016-07-11 03:08:51 +00:00
|
|
|
permission_required = ['view_hostingorder']
|
2016-05-03 05:59:40 +00:00
|
|
|
model = HostingOrder
|
2016-04-27 06:54:15 +00:00
|
|
|
|
2017-05-12 10:07:05 +00:00
|
|
|
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,
|
2017-05-13 03:50:56 +00:00
|
|
|
password=owner.password)
|
2017-07-30 15:11:11 +00:00
|
|
|
if self.request.GET.get('page', '') == 'payment':
|
|
|
|
context['page_header_text'] = _('Confirm Order')
|
|
|
|
else:
|
|
|
|
context['page_header_text'] = _('Invoice')
|
2017-05-14 10:22:10 +00:00
|
|
|
try:
|
|
|
|
vm = manager.get_vm(obj.vm_id)
|
|
|
|
context['vm'] = VirtualMachineSerializer(vm).data
|
2017-06-15 02:00:47 +00:00
|
|
|
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'
|
2017-05-14 10:22:10 +00:00
|
|
|
except ConnectionRefusedError:
|
2017-06-15 02:00:47 +00:00
|
|
|
messages.error(self.request,
|
2017-09-04 16:57:59 +00:00
|
|
|
_(
|
|
|
|
'In order to create a VM, you need to create/upload your SSH KEY first.')
|
2017-05-25 09:27:49 +00:00
|
|
|
)
|
2017-05-12 17:13:18 +00:00
|
|
|
return context
|
2017-05-12 10:07:05 +00:00
|
|
|
|
2017-05-11 05:11:33 +00:00
|
|
|
|
2016-05-03 05:59:40 +00:00
|
|
|
class OrdersHostingListView(LoginRequiredMixin, ListView):
|
2016-04-29 06:53:24 +00:00
|
|
|
template_name = "hosting/orders.html"
|
|
|
|
login_url = reverse_lazy('hosting:login')
|
2016-05-03 05:59:40 +00:00
|
|
|
context_object_name = "orders"
|
|
|
|
model = HostingOrder
|
|
|
|
paginate_by = 10
|
2016-05-14 06:42:42 +00:00
|
|
|
ordering = '-id'
|
2016-04-29 06:53:24 +00:00
|
|
|
|
2016-05-03 05:59:40 +00:00
|
|
|
def get_queryset(self):
|
2016-04-29 06:53:24 +00:00
|
|
|
user = self.request.user
|
2016-05-03 05:59:40 +00:00
|
|
|
self.queryset = HostingOrder.objects.filter(customer__user=user)
|
|
|
|
return super(OrdersHostingListView, self).get_queryset()
|
2016-04-29 06:53:24 +00:00
|
|
|
|
2016-05-24 06:19:49 +00:00
|
|
|
|
|
|
|
class OrdersHostingDeleteView(LoginRequiredMixin, DeleteView):
|
2016-05-29 18:37:43 +00:00
|
|
|
login_url = reverse_lazy('hosting:login')
|
2016-05-18 22:58:28 +00:00
|
|
|
success_url = reverse_lazy('hosting:orders')
|
|
|
|
model = HostingOrder
|
2016-04-29 06:53:24 +00:00
|
|
|
|
2016-05-29 18:37:43 +00:00
|
|
|
|
2016-05-03 05:59:40 +00:00
|
|
|
class VirtualMachinesPlanListView(LoginRequiredMixin, ListView):
|
|
|
|
template_name = "hosting/virtual_machines.html"
|
|
|
|
login_url = reverse_lazy('hosting:login')
|
|
|
|
context_object_name = "vms"
|
|
|
|
paginate_by = 10
|
2016-05-14 06:42:42 +00:00
|
|
|
ordering = '-id'
|
2016-04-29 06:53:24 +00:00
|
|
|
|
2016-05-03 05:59:40 +00:00
|
|
|
def get_queryset(self):
|
2017-05-12 10:07:05 +00:00
|
|
|
owner = self.request.user
|
|
|
|
manager = OpenNebulaManager(email=owner.email,
|
2017-05-13 03:50:56 +00:00
|
|
|
password=owner.password)
|
2017-05-14 10:22:10 +00:00
|
|
|
try:
|
|
|
|
queryset = manager.get_vms()
|
|
|
|
serializer = VirtualMachineSerializer(queryset, many=True)
|
|
|
|
return serializer.data
|
|
|
|
except ConnectionRefusedError:
|
2017-05-25 09:27:49 +00:00
|
|
|
messages.error(self.request,
|
|
|
|
'We could not load your VMs due to a backend connection \
|
2017-05-14 10:22:10 +00:00
|
|
|
error. Please try again in a few minutes'
|
2017-05-25 09:27:49 +00:00
|
|
|
)
|
2017-05-14 10:22:10 +00:00
|
|
|
|
|
|
|
self.kwargs['error'] = 'connection'
|
|
|
|
return []
|
|
|
|
|
|
|
|
def get_context_data(self, **kwargs):
|
|
|
|
error = self.kwargs.get('error')
|
|
|
|
if error is not None:
|
|
|
|
print(error)
|
2017-05-25 09:27:49 +00:00
|
|
|
context = {'error': 'connection'}
|
2017-05-14 10:22:10 +00:00
|
|
|
else:
|
|
|
|
context = super(ListView, self).get_context_data(**kwargs)
|
|
|
|
return context
|
2016-05-04 05:16:41 +00:00
|
|
|
|
|
|
|
|
2017-05-04 04:19:32 +00:00
|
|
|
class CreateVirtualMachinesView(LoginRequiredMixin, View):
|
|
|
|
template_name = "hosting/create_virtual_machine.html"
|
|
|
|
login_url = reverse_lazy('hosting:login')
|
|
|
|
|
|
|
|
def get(self, request, *args, **kwargs):
|
2017-05-12 05:56:35 +00:00
|
|
|
|
2017-06-29 14:34:40 +00:00
|
|
|
if not UserHostingKey.objects.filter(user=self.request.user).exists():
|
2017-05-12 05:56:35 +00:00
|
|
|
messages.success(
|
|
|
|
request,
|
2017-09-04 16:57:59 +00:00
|
|
|
_(
|
|
|
|
'In order to create a VM, you need to create/upload your SSH KEY first.')
|
2017-05-12 05:56:35 +00:00
|
|
|
)
|
2017-06-03 13:03:55 +00:00
|
|
|
return HttpResponseRedirect(reverse('hosting:ssh_keys'))
|
2017-05-12 05:56:35 +00:00
|
|
|
|
2017-05-14 10:22:10 +00:00
|
|
|
try:
|
|
|
|
manager = OpenNebulaManager()
|
|
|
|
templates = manager.get_templates()
|
|
|
|
configuration_options = HostingPlan.get_serialized_configs()
|
|
|
|
|
|
|
|
context = {
|
2017-09-02 11:20:09 +00:00
|
|
|
'templates': VirtualMachineTemplateSerializer(templates,
|
|
|
|
many=True).data,
|
2017-05-24 15:58:16 +00:00
|
|
|
'configuration_options': configuration_options,
|
2017-05-14 10:22:10 +00:00
|
|
|
}
|
|
|
|
except:
|
2017-05-24 15:58:16 +00:00
|
|
|
messages.error(
|
|
|
|
request,
|
2017-05-14 10:22:10 +00:00
|
|
|
'We could not load the VM templates due to a backend connection \
|
|
|
|
error. Please try again in a few minutes'
|
2017-05-24 15:58:16 +00:00
|
|
|
)
|
2017-05-14 10:22:10 +00:00
|
|
|
context = {
|
2017-05-24 15:58:16 +00:00
|
|
|
'error': 'connection'
|
2017-06-29 14:34:40 +00:00
|
|
|
}
|
2017-05-12 17:13:18 +00:00
|
|
|
|
2017-05-04 04:19:32 +00:00
|
|
|
return render(request, self.template_name, context)
|
|
|
|
|
|
|
|
def post(self, request):
|
2017-05-13 04:59:57 +00:00
|
|
|
manager = OpenNebulaManager()
|
|
|
|
template_id = request.POST.get('vm_template_id')
|
|
|
|
template = manager.get_template(template_id)
|
2017-05-13 11:47:53 +00:00
|
|
|
configuration_id = int(request.POST.get('configuration'))
|
|
|
|
configuration = HostingPlan.objects.get(id=configuration_id)
|
2017-05-25 09:27:49 +00:00
|
|
|
request.session['template'] = VirtualMachineTemplateSerializer(
|
|
|
|
template).data
|
2017-05-13 11:47:53 +00:00
|
|
|
|
2017-05-25 09:27:49 +00:00
|
|
|
request.session['specs'] = configuration.serialize()
|
2017-05-04 04:19:32 +00:00
|
|
|
return redirect(reverse('hosting:payment'))
|
|
|
|
|
|
|
|
|
2017-05-12 10:07:05 +00:00
|
|
|
class VirtualMachineView(LoginRequiredMixin, View):
|
2016-05-04 05:16:41 +00:00
|
|
|
template_name = "hosting/virtual_machine_detail.html"
|
|
|
|
login_url = reverse_lazy('hosting:login')
|
2017-05-09 00:02:29 +00:00
|
|
|
|
2017-05-12 05:56:35 +00:00
|
|
|
def get_object(self):
|
2017-05-12 10:07:05 +00:00
|
|
|
owner = self.request.user
|
2017-05-12 17:13:18 +00:00
|
|
|
vm = None
|
|
|
|
manager = OpenNebulaManager(
|
|
|
|
email=owner.email,
|
2017-05-13 03:50:56 +00:00
|
|
|
password=owner.password
|
2017-05-12 17:13:18 +00:00
|
|
|
)
|
2017-05-09 02:49:40 +00:00
|
|
|
vm_id = self.kwargs.get('pk')
|
2017-05-12 05:56:35 +00:00
|
|
|
try:
|
2017-05-12 10:07:05 +00:00
|
|
|
vm = manager.get_vm(vm_id)
|
2017-05-14 10:22:10 +00:00
|
|
|
return vm
|
2017-06-17 09:16:11 +00:00
|
|
|
except WrongIdError:
|
|
|
|
messages.error(self.request,
|
|
|
|
_('We could not find the requested VM. Please \
|
|
|
|
contact Data Center Light Support.')
|
|
|
|
)
|
|
|
|
return None
|
2017-05-14 10:22:10 +00:00
|
|
|
except ConnectionRefusedError:
|
2017-05-25 09:27:49 +00:00
|
|
|
messages.error(self.request,
|
|
|
|
'We could not load your VM due to a backend connection \
|
2017-05-14 10:22:10 +00:00
|
|
|
error. Please try again in a few minutes'
|
2017-05-25 09:27:49 +00:00
|
|
|
)
|
2017-05-14 10:22:10 +00:00
|
|
|
return None
|
2017-05-12 05:56:35 +00:00
|
|
|
except Exception as error:
|
|
|
|
print(error)
|
|
|
|
raise Http404()
|
|
|
|
|
|
|
|
def get_success_url(self):
|
|
|
|
final_url = reverse('hosting:virtual_machines')
|
|
|
|
return final_url
|
2016-06-10 04:50:49 +00:00
|
|
|
|
2017-05-09 00:02:29 +00:00
|
|
|
def get(self, request, *args, **kwargs):
|
2017-05-12 17:13:18 +00:00
|
|
|
vm = self.get_object()
|
2017-06-17 09:16:11 +00:00
|
|
|
if vm is None:
|
2017-09-15 11:16:56 +00:00
|
|
|
if self.request.is_ajax():
|
2017-09-15 11:27:17 +00:00
|
|
|
storage = messages.get_messages(request)
|
2017-09-15 12:08:52 +00:00
|
|
|
for m in storage:
|
|
|
|
pass
|
2017-09-15 11:27:17 +00:00
|
|
|
storage.used = True
|
2017-09-15 11:50:42 +00:00
|
|
|
return HttpResponse(
|
|
|
|
json.dumps({'redirect': self.get_success_url()}),
|
|
|
|
content_type="application/json"
|
|
|
|
)
|
2017-09-15 11:16:56 +00:00
|
|
|
else:
|
|
|
|
return redirect(reverse('hosting:virtual_machines'))
|
2017-09-15 11:50:42 +00:00
|
|
|
elif self.request.is_ajax():
|
|
|
|
return HttpResponse()
|
2017-05-25 09:27:49 +00:00
|
|
|
try:
|
2017-05-14 10:22:10 +00:00
|
|
|
serializer = VirtualMachineSerializer(vm)
|
|
|
|
context = {
|
|
|
|
'virtual_machine': serializer.data,
|
2017-09-02 11:20:09 +00:00
|
|
|
'order': HostingOrder.objects.get(
|
|
|
|
vm_id=serializer.data['vm_id'])
|
2017-05-14 10:22:10 +00:00
|
|
|
}
|
2017-08-31 16:20:02 +00:00
|
|
|
except Exception as ex:
|
|
|
|
logger.debug("Exception generated {}".format(str(ex)))
|
2017-05-14 10:22:10 +00:00
|
|
|
pass
|
|
|
|
|
2017-05-09 00:02:29 +00:00
|
|
|
return render(request, self.template_name, context)
|
2016-06-10 04:50:49 +00:00
|
|
|
|
2017-05-12 05:56:35 +00:00
|
|
|
def post(self, request, *args, **kwargs):
|
2017-09-15 11:16:56 +00:00
|
|
|
response = {'status': False}
|
2017-05-12 17:13:18 +00:00
|
|
|
owner = self.request.user
|
2016-06-10 04:50:49 +00:00
|
|
|
vm = self.get_object()
|
2017-05-12 05:56:35 +00:00
|
|
|
|
|
|
|
opennebula_vm_id = self.kwargs.get('pk')
|
|
|
|
|
2017-05-12 17:13:18 +00:00
|
|
|
manager = OpenNebulaManager(
|
|
|
|
email=owner.email,
|
2017-05-13 03:50:56 +00:00
|
|
|
password=owner.password
|
2017-05-12 17:13:18 +00:00
|
|
|
)
|
2017-09-15 11:16:56 +00:00
|
|
|
|
2017-09-18 16:22:59 +00:00
|
|
|
try:
|
|
|
|
vm_data = VirtualMachineSerializer(manager.get_vm(vm.id)).data
|
|
|
|
except BaseException:
|
|
|
|
return redirect(
|
|
|
|
reverse('hosting:virtual_machines',
|
|
|
|
kwargs={'pk': opennebula_vm_id})
|
|
|
|
)
|
2017-09-13 20:54:10 +00:00
|
|
|
|
|
|
|
terminated = manager.delete_vm(vm.id)
|
2017-05-12 05:56:35 +00:00
|
|
|
|
|
|
|
if not terminated:
|
2017-09-13 21:29:08 +00:00
|
|
|
response['text'] = ugettext(
|
|
|
|
'Error terminating VM') + opennebula_vm_id
|
2017-09-13 20:54:10 +00:00
|
|
|
else:
|
2017-09-15 11:16:56 +00:00
|
|
|
for t in range(15):
|
2017-09-14 19:27:59 +00:00
|
|
|
try:
|
2017-09-18 16:22:59 +00:00
|
|
|
manager.get_vm(opennebula_vm_id)
|
2017-09-15 12:45:06 +00:00
|
|
|
except WrongIdError:
|
2017-09-15 11:16:56 +00:00
|
|
|
response['status'] = True
|
|
|
|
response['text'] = ugettext('Terminated')
|
2017-09-15 12:45:06 +00:00
|
|
|
break
|
|
|
|
except BaseException:
|
2017-09-14 19:27:59 +00:00
|
|
|
break
|
|
|
|
else:
|
|
|
|
sleep(2)
|
2017-09-13 20:54:10 +00:00
|
|
|
context = {
|
|
|
|
'vm': vm_data,
|
|
|
|
'base_url': "{0}://{1}".format(self.request.scheme,
|
|
|
|
self.request.get_host()),
|
|
|
|
'page_header': _('Virtual Machine Cancellation')
|
|
|
|
}
|
|
|
|
email_data = {
|
|
|
|
'subject': context['page_header'],
|
|
|
|
'to': self.request.user.email,
|
|
|
|
'context': context,
|
|
|
|
'template_name': 'vm_canceled',
|
|
|
|
'template_path': 'hosting/emails/',
|
|
|
|
'from_address': settings.DCL_SUPPORT_FROM_ADDRESS,
|
|
|
|
}
|
|
|
|
email = BaseEmail(**email_data)
|
|
|
|
email.send()
|
|
|
|
return HttpResponse(
|
|
|
|
json.dumps(response),
|
|
|
|
content_type="application/json"
|
2017-05-12 05:56:35 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
|
2017-09-02 11:20:09 +00:00
|
|
|
class HostingBillListView(PermissionRequiredMixin, LoginRequiredMixin,
|
|
|
|
ListView):
|
2017-05-05 12:59:11 +00:00
|
|
|
template_name = "hosting/bills.html"
|
|
|
|
login_url = reverse_lazy('hosting:login')
|
2017-05-14 01:19:09 +00:00
|
|
|
permission_required = ['view_hostingview']
|
2017-05-05 12:59:11 +00:00
|
|
|
context_object_name = "users"
|
|
|
|
model = StripeCustomer
|
|
|
|
paginate_by = 10
|
|
|
|
ordering = '-id'
|
|
|
|
|
2017-05-12 05:56:35 +00:00
|
|
|
|
2017-09-02 11:20:09 +00:00
|
|
|
class HostingBillDetailView(PermissionRequiredMixin, LoginRequiredMixin,
|
|
|
|
DetailView):
|
2017-05-05 12:59:11 +00:00
|
|
|
template_name = "hosting/bill_detail.html"
|
|
|
|
login_url = reverse_lazy('hosting:login')
|
|
|
|
permission_required = ['view_hostingview']
|
|
|
|
context_object_name = "bill"
|
|
|
|
model = HostingBill
|
|
|
|
|
|
|
|
def get_object(self, queryset=None):
|
2017-05-12 05:56:35 +00:00
|
|
|
# Get HostingBill for primary key (Select from customer users)
|
2017-05-05 12:59:11 +00:00
|
|
|
pk = self.kwargs['pk']
|
2017-05-07 23:56:02 +00:00
|
|
|
object = HostingBill.objects.filter(customer__id=pk).first()
|
|
|
|
if object is None:
|
|
|
|
self.template_name = 'hosting/bill_error.html'
|
|
|
|
return object
|
2017-05-05 12:59:11 +00:00
|
|
|
|
|
|
|
def get_context_data(self, **kwargs):
|
|
|
|
# Get context
|
|
|
|
context = super(DetailView, self).get_context_data(**kwargs)
|
2017-05-12 10:07:05 +00:00
|
|
|
|
|
|
|
owner = self.request.user
|
|
|
|
manager = OpenNebulaManager(email=owner.email,
|
2017-05-13 03:50:56 +00:00
|
|
|
password=owner.password)
|
2017-05-07 04:43:28 +00:00
|
|
|
# Get vms
|
2017-05-12 10:07:05 +00:00
|
|
|
queryset = manager.get_vms()
|
|
|
|
vms = VirtualMachineSerializer(queryset, many=True).data
|
2017-05-13 11:47:53 +00:00
|
|
|
# Set total price
|
|
|
|
bill = context['bill']
|
|
|
|
bill.total_price = 0.0
|
|
|
|
for vm in vms:
|
|
|
|
bill.total_price += vm['price']
|
2017-05-12 10:07:05 +00:00
|
|
|
context['vms'] = vms
|
2017-05-07 23:56:02 +00:00
|
|
|
return context
|