From 3bb7f09d41a4f05550f4652a103aa341ad0e175d Mon Sep 17 00:00:00 2001 From: PCoder Date: Sat, 23 Sep 2017 03:16:18 +0530 Subject: [PATCH 01/47] Refactored obtaining vm price to utils.hosting_utils.get_vm_price --- utils/hosting_utils.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/utils/hosting_utils.py b/utils/hosting_utils.py index 7c1a83ad..dae8e412 100644 --- a/utils/hosting_utils.py +++ b/utils/hosting_utils.py @@ -9,3 +9,16 @@ def get_all_public_keys(customer): """ return UserHostingKey.objects.filter(user_id=customer.id).values_list( "public_key", flat=True) + + +def get_vm_price(cpu, memory, disk_size): + """ + A helper function that computes price of a VM from given cpu, ram and + ssd parameters + + :param cpu: Number of cores of the VM + :param memory: RAM of the VM + :param disk_size: Disk space of the VM + :return: The price of the VM + """ + return (cpu * 5) + (memory * 2) + (disk_size * 0.6) From 285d66466052f84ac5348f3fd1582c60556108ed Mon Sep 17 00:00:00 2001 From: PCoder Date: Sat, 23 Sep 2017 03:17:21 +0530 Subject: [PATCH 02/47] Refactored obtaining stripe plan name to utils.stripe_utils.get_stripe_plan_name --- utils/stripe_utils.py | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/utils/stripe_utils.py b/utils/stripe_utils.py index f35a6b9c..cb4f6eff 100644 --- a/utils/stripe_utils.py +++ b/utils/stripe_utils.py @@ -238,7 +238,7 @@ class StripeUtils(object): @staticmethod def get_stripe_plan_id(cpu, ram, ssd, version, app='dcl', hdd=None): """ - Returns the stripe plan id string of the form + Returns the Stripe plan id string of the form `dcl-v1-cpu-2-ram-5gb-ssd-10gb` based on the input parameters :param cpu: The number of cores @@ -260,3 +260,14 @@ class StripeUtils(object): version=version, plan=dcl_plan_string) return stripe_plan_id_string + + @staticmethod + def get_stripe_plan_name(cpu, memory, disk_size): + """ + Returns the Stripe plan name + :return: + """ + return "{cpu} Cores, {memory} GB RAM, {disk_size} GB SSD".format( + cpu=cpu, + memory=memory, + disk_size=disk_size) From 99e5cf5587e203152b0d737c4273a98bffb4fa01 Mon Sep 17 00:00:00 2001 From: PCoder Date: Sat, 23 Sep 2017 03:18:05 +0530 Subject: [PATCH 03/47] Using refactored get_vm_price and get_vm_plan_name functions --- datacenterlight/tests.py | 12 ++++++------ datacenterlight/views.py | 12 ++++++------ hosting/views.py | 16 ++++++++-------- 3 files changed, 20 insertions(+), 20 deletions(-) diff --git a/datacenterlight/tests.py b/datacenterlight/tests.py index c34c56ba..edde2db8 100644 --- a/datacenterlight/tests.py +++ b/datacenterlight/tests.py @@ -12,6 +12,7 @@ from datacenterlight.models import VMTemplate from datacenterlight.tasks import create_vm_task from membership.models import StripeCustomer from opennebula_api.serializers import VMTemplateSerializer +from utils.hosting_utils import get_vm_price from utils.models import BillingAddress from utils.stripe_utils import StripeUtils @@ -94,12 +95,11 @@ class CeleryTaskTestCase(TestCase): cpu = specs.get('cpu') memory = specs.get('memory') disk_size = specs.get('disk_size') - amount_to_be_charged = (cpu * 5) + (memory * 2) + (disk_size * 0.6) - plan_name = "{cpu} Cores, {memory} GB RAM, {disk_size} GB SSD".format( - cpu=cpu, - memory=memory, - disk_size=disk_size) - + amount_to_be_charged = get_vm_price(cpu=cpu, memory=memory, + disk_size=disk_size) + plan_name = StripeUtils.get_stripe_plan_name(cpu=cpu, + memory=memory, + disk_size=disk_size) stripe_plan_id = StripeUtils.get_stripe_plan_id(cpu=cpu, ram=memory, ssd=disk_size, diff --git a/datacenterlight/views.py b/datacenterlight/views.py index 0521ffef..152e3e75 100644 --- a/datacenterlight/views.py +++ b/datacenterlight/views.py @@ -17,6 +17,7 @@ from opennebula_api.models import OpenNebulaManager from opennebula_api.serializers import VirtualMachineTemplateSerializer, \ VMTemplateSerializer from utils.forms import BillingAddressForm +from utils.hosting_utils import get_vm_price from utils.mailer import BaseEmail from utils.stripe_utils import StripeUtils from utils.tasks import send_plain_email_task @@ -532,12 +533,11 @@ class OrderConfirmationView(DetailView): cpu = specs.get('cpu') memory = specs.get('memory') disk_size = specs.get('disk_size') - amount_to_be_charged = (cpu * 5) + (memory * 2) + (disk_size * 0.6) - plan_name = "{cpu} Cores, {memory} GB RAM, {disk_size} GB SSD".format( - cpu=cpu, - memory=memory, - disk_size=disk_size) - + amount_to_be_charged = get_vm_price(cpu=cpu, memory=memory, + disk_size=disk_size) + plan_name = StripeUtils.get_stripe_plan_name(cpu=cpu, + memory=memory, + disk_size=disk_size) stripe_plan_id = StripeUtils.get_stripe_plan_id(cpu=cpu, ram=memory, ssd=disk_size, diff --git a/hosting/views.py b/hosting/views.py index e1d2feb2..f91b2e5c 100644 --- a/hosting/views.py +++ b/hosting/views.py @@ -35,6 +35,7 @@ from utils.mailer import BaseEmail from utils.stripe_utils import StripeUtils from utils.views import PasswordResetViewMixin, PasswordResetConfirmViewMixin, \ LoginViewMixin +from utils.hosting_utils import get_vm_price from .forms import HostingUserSignupForm, HostingUserLoginForm, \ UserHostingKeyForm, generate_ssh_key_name from .mixins import ProcessVMSelectionMixin @@ -724,12 +725,11 @@ class OrdersHostingDetailView(LoginRequiredMixin, cpu = specs.get('cpu') memory = specs.get('memory') disk_size = specs.get('disk_size') - amount_to_be_charged = (cpu * 5) + (memory * 2) + (disk_size * 0.6) - plan_name = "{cpu} Cores, {memory} GB RAM, {disk_size} GB SSD".format( - cpu=cpu, - memory=memory, - disk_size=disk_size) - + amount_to_be_charged = get_vm_price(cpu=cpu, memory=memory, + disk_size=disk_size) + plan_name = StripeUtils.get_stripe_plan_name(cpu=cpu, + memory=memory, + disk_size=disk_size) stripe_plan_id = StripeUtils.get_stripe_plan_id(cpu=cpu, ram=memory, ssd=disk_size, @@ -775,8 +775,8 @@ class OrdersHostingDetailView(LoginRequiredMixin, 'redirect': reverse('hosting:virtual_machines'), 'msg_title': str(_('Thank you for the order.')), 'msg_body': str(_('Your VM will be up and running in a few moments.' - ' We will send you a confirmation email as soon as' - ' it is ready.')) + ' We will send you a confirmation email as soon as' + ' it is ready.')) } return HttpResponse(json.dumps(response), From 9ab7622a9c245c9c712e8f1ca3840487200fa3bf Mon Sep 17 00:00:00 2001 From: PCoder Date: Sat, 23 Sep 2017 03:25:48 +0530 Subject: [PATCH 04/47] Reformatted stripe_utils.py --- utils/stripe_utils.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/utils/stripe_utils.py b/utils/stripe_utils.py index cb4f6eff..98f85d62 100644 --- a/utils/stripe_utils.py +++ b/utils/stripe_utils.py @@ -256,9 +256,10 @@ class StripeUtils(object): if hdd is not None: dcl_plan_string = '{dcl_plan_string}-hdd-{hdd}gb'.format( dcl_plan_string=dcl_plan_string, hdd=hdd) - stripe_plan_id_string = '{app}-v{version}-{plan}'.format(app=app, - version=version, - plan=dcl_plan_string) + stripe_plan_id_string = '{app}-v{version}-{plan}'.format( + app=app, + version=version, + plan=dcl_plan_string) return stripe_plan_id_string @staticmethod @@ -268,6 +269,6 @@ class StripeUtils(object): :return: """ return "{cpu} Cores, {memory} GB RAM, {disk_size} GB SSD".format( - cpu=cpu, - memory=memory, - disk_size=disk_size) + cpu=cpu, + memory=memory, + disk_size=disk_size) From 8de4a751079a6499e2eac508884cc1571d996add Mon Sep 17 00:00:00 2001 From: PCoder Date: Sat, 23 Sep 2017 12:48:21 +0530 Subject: [PATCH 05/47] Removed some occurrences of price --- datacenterlight/views.py | 1 - 1 file changed, 1 deletion(-) diff --git a/datacenterlight/views.py b/datacenterlight/views.py index 0521ffef..0b494d85 100644 --- a/datacenterlight/views.py +++ b/datacenterlight/views.py @@ -334,7 +334,6 @@ class IndexView(CreateView): 'cpu': cores, 'memory': memory, 'disk_size': storage, - 'price': price } this_user = { From 0bc2b22f6262c997222fbb122bd61f3fb6fa4fea Mon Sep 17 00:00:00 2001 From: PCoder Date: Sat, 23 Sep 2017 13:09:14 +0530 Subject: [PATCH 06/47] Reformatted datacenterlight/tasks.py --- datacenterlight/tasks.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/datacenterlight/tasks.py b/datacenterlight/tasks.py index 1335869b..e8b29601 100644 --- a/datacenterlight/tasks.py +++ b/datacenterlight/tasks.py @@ -52,7 +52,8 @@ def create_vm_task(self, vm_template_id, user, specs, template, stripe_customer_id, billing_address_data, billing_address_id, charge, cc_details): - logger.debug("Running create_vm_task on {}".format(current_task.request.hostname)) + logger.debug( + "Running create_vm_task on {}".format(current_task.request.hostname)) vm_id = None try: final_price = specs.get('price') @@ -142,9 +143,10 @@ def create_vm_task(self, vm_template_id, user, specs, template, email.send() if 'pass' in user: - lang = 'en-us' + lang = 'en-us' if user.get('language') is not None: - logger.debug("Language is set to {}".format(user.get('language'))) + 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 From 93d36306fb5ca6a18f73a48e3eaac7c66c55ef6e Mon Sep 17 00:00:00 2001 From: PCoder Date: Sat, 23 Sep 2017 13:21:01 +0530 Subject: [PATCH 07/47] Removed total and price fields used in dcl flow --- datacenterlight/static/datacenterlight/js/main.js | 4 +--- .../templates/datacenterlight/calculator_form.html | 1 - datacenterlight/views.py | 2 +- 3 files changed, 2 insertions(+), 5 deletions(-) diff --git a/datacenterlight/static/datacenterlight/js/main.js b/datacenterlight/static/datacenterlight/js/main.js index c508d76d..82a21235 100644 --- a/datacenterlight/static/datacenterlight/js/main.js +++ b/datacenterlight/static/datacenterlight/js/main.js @@ -156,9 +156,7 @@ function _calcPricing() { var total = (cardPricing['cpu'].value * 5) + (2 * cardPricing['ram'].value) + (0.6 * cardPricing['storage'].value); total = parseFloat(total.toFixed(2)); - $("#total").text(total); - $('input[name=total]').val(total); } function form_success() { @@ -192,4 +190,4 @@ }); }) } -})(jQuery); \ No newline at end of file +})(jQuery); diff --git a/datacenterlight/templates/datacenterlight/calculator_form.html b/datacenterlight/templates/datacenterlight/calculator_form.html index cdba4809..23d0defd 100644 --- a/datacenterlight/templates/datacenterlight/calculator_form.html +++ b/datacenterlight/templates/datacenterlight/calculator_form.html @@ -77,7 +77,6 @@ {% endfor %} - diff --git a/datacenterlight/views.py b/datacenterlight/views.py index d329cb05..c7848e3d 100644 --- a/datacenterlight/views.py +++ b/datacenterlight/views.py @@ -275,7 +275,6 @@ class IndexView(CreateView): memory_field = forms.IntegerField(validators=[self.validate_memory]) storage = request.POST.get('storage') storage_field = forms.IntegerField(validators=[self.validate_storage]) - price = request.POST.get('total') template_id = int(request.POST.get('config')) template = VMTemplate.objects.filter( opennebula_vm_template_id=template_id).first() @@ -534,6 +533,7 @@ class OrderConfirmationView(DetailView): disk_size = specs.get('disk_size') amount_to_be_charged = get_vm_price(cpu=cpu, memory=memory, disk_size=disk_size) + specs['price'] = amount_to_be_charged plan_name = StripeUtils.get_stripe_plan_name(cpu=cpu, memory=memory, disk_size=disk_size) From b428a0933e13bdc3c115dcb5aa8aabde4ad2761b Mon Sep 17 00:00:00 2001 From: PCoder Date: Sat, 23 Sep 2017 21:23:48 +0530 Subject: [PATCH 08/47] Deleted datacenterlight pricing.html --- .../templates/datacenterlight/pricing.html | 96 ------------------- 1 file changed, 96 deletions(-) delete mode 100644 datacenterlight/templates/datacenterlight/pricing.html diff --git a/datacenterlight/templates/datacenterlight/pricing.html b/datacenterlight/templates/datacenterlight/pricing.html deleted file mode 100644 index 0724a6ce..00000000 --- a/datacenterlight/templates/datacenterlight/pricing.html +++ /dev/null @@ -1,96 +0,0 @@ -{% extends "datacenterlight/base.html" %} -{% load staticfiles i18n%} -{% get_current_language as LANGUAGE_CODE %} - -{% block content %} -
- -
-

{% trans "We are cutting down the costs significantly!" %}

-
- -
- -
-
- -
-
- {% csrf_token %} - -
-

{% trans "VM hosting" %}

-
-
- 15 - CHF -
-

{% trans "VAT included" %}

-
-
-
-
-

{% trans "Hosted in Switzerland" %}

-
-
- - - Core - -
-
- - - GB RAM - -
-
- - - {% trans "GB Storage (SSD)" %} - -
- - - -
- - -
- - - - - -
- - -
-
-
- -
-

{% trans "Simple and affordable: Try our virtual machine with featherlight price." %}

- -
-

{% trans "Our VMs are hosted in Glarus, Switzerland, and our website is currently running in BETA mode. If you want more information that you did not find on our website, or if your order is more detailed, or if you encounter any technical hiccups, please contact us at support@datacenterlight.ch, our team will get in touch with you asap." %}

-
-
-
-{% endblock %} - - - From 8781905fc6df9c5002dc0584b8c2c51b465cca0f Mon Sep 17 00:00:00 2001 From: PCoder Date: Sat, 23 Sep 2017 21:24:42 +0530 Subject: [PATCH 09/47] Removed DataCenterLight PricingView --- datacenterlight/urls.py | 3 +-- datacenterlight/views.py | 55 +--------------------------------------- 2 files changed, 2 insertions(+), 56 deletions(-) diff --git a/datacenterlight/urls.py b/datacenterlight/urls.py index 772e691d..a8d8f49d 100644 --- a/datacenterlight/urls.py +++ b/datacenterlight/urls.py @@ -1,7 +1,7 @@ from django.conf.urls import url from .views import IndexView, BetaProgramView, LandingProgramView, \ - BetaAccessView, PricingView, SuccessView, \ + BetaAccessView, SuccessView, \ PaymentOrderView, OrderConfirmationView, \ WhyDataCenterLightView, ContactUsView @@ -15,7 +15,6 @@ urlpatterns = [ name='whydatacenterlight'), url(r'^beta-program/?$', BetaProgramView.as_view(), name='beta'), url(r'^landing/?$', LandingProgramView.as_view(), name='landing'), - url(r'^pricing/?$', PricingView.as_view(), name='pricing'), url(r'^payment/?$', PaymentOrderView.as_view(), name='payment'), url(r'^order-confirmation/?$', OrderConfirmationView.as_view(), name='order_confirmation'), diff --git a/datacenterlight/views.py b/datacenterlight/views.py index c7848e3d..a2baf717 100644 --- a/datacenterlight/views.py +++ b/datacenterlight/views.py @@ -4,7 +4,6 @@ from django.contrib import messages from django.core.exceptions import ValidationError from django.core.urlresolvers import reverse from django.http import HttpResponseRedirect -from django.shortcuts import redirect from django.shortcuts import render from django.utils.translation import ugettext_lazy as _ from django.views.decorators.cache import cache_control @@ -13,9 +12,7 @@ from django.views.generic import FormView, CreateView, TemplateView, DetailView from datacenterlight.tasks import create_vm_task from hosting.models import HostingOrder from membership.models import CustomUser, StripeCustomer -from opennebula_api.models import OpenNebulaManager -from opennebula_api.serializers import VirtualMachineTemplateSerializer, \ - VMTemplateSerializer +from opennebula_api.serializers import VMTemplateSerializer from utils.forms import BillingAddressForm from utils.hosting_utils import get_vm_price from utils.mailer import BaseEmail @@ -89,56 +86,6 @@ class SuccessView(TemplateView): return render(request, self.template_name) -class PricingView(TemplateView): - template_name = "datacenterlight/pricing.html" - - def get(self, request, *args, **kwargs): - try: - manager = OpenNebulaManager() - templates = manager.get_templates() - - context = { - 'templates': VirtualMachineTemplateSerializer(templates, - many=True).data, - } - except: - messages.error(request, - 'We have a temporary problem to connect to our backend. \ - Please try again in a few minutes' - ) - context = { - 'error': 'connection' - } - - return render(request, self.template_name, context) - - def post(self, request): - - cores = request.POST.get('cpu') - memory = request.POST.get('ram') - storage = request.POST.get('storage') - price = request.POST.get('total') - - template_id = int(request.POST.get('config')) - manager = OpenNebulaManager() - template = manager.get_template(template_id) - - request.session['template'] = VirtualMachineTemplateSerializer( - template).data - - if not request.user.is_authenticated(): - request.session['next'] = reverse('hosting:payment') - - request.session['specs'] = { - 'cpu': cores, - 'memory': memory, - 'disk_size': storage, - 'price': price, - } - - return redirect(reverse('hosting:payment')) - - class BetaAccessView(FormView): template_name = "datacenterlight/beta_access.html" form_class = BetaAccessForm From 09dc0cde1313072ee7be54371b7cb04823ff0eb8 Mon Sep 17 00:00:00 2001 From: PCoder Date: Sun, 24 Sep 2017 04:38:54 +0530 Subject: [PATCH 10/47] Removed unwanted js code that was causing error --- hosting/templates/hosting/choice_ssh_keys.html | 15 --------------- hosting/templates/hosting/user_keys.html | 16 ---------------- 2 files changed, 31 deletions(-) diff --git a/hosting/templates/hosting/choice_ssh_keys.html b/hosting/templates/hosting/choice_ssh_keys.html index 3a377388..87224156 100644 --- a/hosting/templates/hosting/choice_ssh_keys.html +++ b/hosting/templates/hosting/choice_ssh_keys.html @@ -47,20 +47,5 @@ window.location.href = '{{next_url}}'; {% endif %} - - - - - {%endblock%} diff --git a/hosting/templates/hosting/user_keys.html b/hosting/templates/hosting/user_keys.html index 1cfb880c..6810efdf 100644 --- a/hosting/templates/hosting/user_keys.html +++ b/hosting/templates/hosting/user_keys.html @@ -101,21 +101,5 @@ window.location.href = '{{next_url}}'; {% endif %} - - - - - {%endblock%} From 0974376e9f5df6298324afaba5441dcce4210133 Mon Sep 17 00:00:00 2001 From: "M.Ravi" Date: Sun, 24 Sep 2017 09:34:30 +0200 Subject: [PATCH 11/47] Reformatted code --- hosting/views.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/hosting/views.py b/hosting/views.py index c21a6cd8..99ab6f05 100644 --- a/hosting/views.py +++ b/hosting/views.py @@ -47,7 +47,6 @@ from .mixins import ProcessVMSelectionMixin from .models import HostingOrder, HostingBill, HostingPlan, UserHostingKey from datacenterlight.models import VMTemplate - logger = logging.getLogger(__name__) CONNECTION_ERROR = "Your VMs cannot be displayed at the moment due to a \ @@ -806,9 +805,10 @@ class OrdersHostingDetailView(LoginRequiredMixin, 'status': True, 'redirect': reverse('hosting:virtual_machines'), 'msg_title': str(_('Thank you for the order.')), - 'msg_body': str(_('Your VM will be up and running in a few moments.' - ' We will send you a confirmation email as soon as' - ' it is ready.')) + 'msg_body': str( + _('Your VM will be up and running in a few moments.' + ' We will send you a confirmation email as soon as' + ' it is ready.')) } return HttpResponse(json.dumps(response), @@ -937,7 +937,7 @@ class CreateVirtualMachinesView(LoginRequiredMixin, View): return HttpResponseRedirect( reverse('datacenterlight:index') + "#order_form") price = get_vm_price(cpu=cores, memory=memory, - disk_size=storage) + disk_size=storage) specs = { 'cpu': cores, 'memory': memory, From afc368e9dd6cf470a3aaa547a5f6a63e2768e816 Mon Sep 17 00:00:00 2001 From: PCoder Date: Sun, 24 Sep 2017 15:49:40 +0530 Subject: [PATCH 12/47] Added ResendActivationEmailView --- hosting/views.py | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/hosting/views.py b/hosting/views.py index d7c4c168..02e68bbd 100644 --- a/hosting/views.py +++ b/hosting/views.py @@ -33,12 +33,15 @@ from membership.models import CustomUser, StripeCustomer from opennebula_api.models import OpenNebulaManager from opennebula_api.serializers import VirtualMachineSerializer, \ VirtualMachineTemplateSerializer, VMTemplateSerializer -from utils.forms import BillingAddressForm, PasswordResetRequestForm, \ - UserBillingAddressForm +from utils.forms import ( + BillingAddressForm, PasswordResetRequestForm, UserBillingAddressForm, + ResendActivationEmailForm +) from utils.mailer import BaseEmail from utils.stripe_utils import StripeUtils from utils.views import ( - PasswordResetViewMixin, PasswordResetConfirmViewMixin, LoginViewMixin + PasswordResetViewMixin, PasswordResetConfirmViewMixin, LoginViewMixin, + ResendActivationLinkViewMixin ) from .forms import HostingUserSignupForm, HostingUserLoginForm, \ UserHostingKeyForm, generate_ssh_key_name @@ -282,6 +285,14 @@ class SignupValidatedView(SignupValidateView): return context +class ResendActivationEmailView(ResendActivationLinkViewMixin): + template_name = 'hosting/resend_activation_link.html' + form_class = ResendActivationEmailForm + success_url = reverse_lazy('hosting:login') + email_template_path = 'datacenterlight/emails/' + email_template_name = 'user_activation' + + class PasswordResetView(PasswordResetViewMixin): site = 'dcl' template_name = 'hosting/reset_password.html' From 324761613752d77a2824df67feec22047b445722 Mon Sep 17 00:00:00 2001 From: PCoder Date: Sun, 24 Sep 2017 15:53:08 +0530 Subject: [PATCH 13/47] Added resend activation link url --- hosting/urls.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/hosting/urls.py b/hosting/urls.py index 2868c717..f40e803a 100644 --- a/hosting/urls.py +++ b/hosting/urls.py @@ -8,8 +8,7 @@ from .views import ( MarkAsReadNotificationView, PasswordResetView, PasswordResetConfirmView, HostingPricingView, CreateVirtualMachinesView, HostingBillListView, HostingBillDetailView, SSHKeyDeleteView, SSHKeyCreateView, SSHKeyListView, - SSHKeyChoiceView, DashboardView, SettingsView) - + SSHKeyChoiceView, DashboardView, SettingsView, ResendActivationEmailView) urlpatterns = [ url(r'index/?$', IndexView.as_view(), name='index'), @@ -52,6 +51,8 @@ urlpatterns = [ url(r'signup/?$', SignupView.as_view(), name='signup'), url(r'signup-validate/?$', SignupValidateView.as_view(), name='signup-validate'), + url(r'resend-activation-link/?$', ResendActivationEmailView.as_view(), + name='resend_activation_link'), url(r'reset-password/?$', PasswordResetView.as_view(), name='reset_password'), url(r'reset-password-confirm/(?P[0-9A-Za-z]+)-(?P.+)/$', From af426c5b7a19f943f95a174f51924c5d52360c78 Mon Sep 17 00:00:00 2001 From: PCoder Date: Sun, 24 Sep 2017 15:54:38 +0530 Subject: [PATCH 14/47] Added ResendActivationEmailForm and translation function to untranslated texts --- utils/forms.py | 32 +++++++++++++++++++++++++------- 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/utils/forms.py b/utils/forms.py index c3f3b6db..a12034dd 100644 --- a/utils/forms.py +++ b/utils/forms.py @@ -18,7 +18,8 @@ class SignupFormMixin(forms.ModelForm): model = CustomUser fields = ['name', 'email', 'password'] widgets = { - 'name': forms.TextInput(attrs={'placeholder': _('Enter your name or company name')}), + 'name': forms.TextInput( + attrs={'placeholder': _('Enter your name or company name')}), } def clean_confirm_password(self): @@ -42,7 +43,7 @@ class LoginFormMixin(forms.Form): is_auth = authenticate(email=email, password=password) if not is_auth: raise forms.ValidationError( - "Your username and/or password were incorrect.") + _("Your username and/or password were incorrect.")) return self.cleaned_data def clean_email(self): @@ -51,7 +52,24 @@ class LoginFormMixin(forms.Form): CustomUser.objects.get(email=email) return email except CustomUser.DoesNotExist: - raise forms.ValidationError("User does not exist") + raise forms.ValidationError(_("User does not exist")) + + +class ResendActivationEmailForm(forms.Form): + email = forms.CharField(widget=forms.EmailInput()) + + class Meta: + fields = ['email'] + + def clean_email(self): + email = self.cleaned_data.get('email') + try: + c = CustomUser.objects.get(email=email) + if c.validated == 1: + raise forms.ValidationError(_("The account is already active.")) + return email + except CustomUser.DoesNotExist: + raise forms.ValidationError(_("User does not exist")) class PasswordResetRequestForm(forms.Form): @@ -66,7 +84,7 @@ class PasswordResetRequestForm(forms.Form): CustomUser.objects.get(email=email) return email except CustomUser.DoesNotExist: - raise forms.ValidationError("User does not exist") + raise forms.ValidationError(_("User does not exist")) class SetPasswordForm(forms.Form): @@ -75,11 +93,11 @@ class SetPasswordForm(forms.Form): password """ error_messages = { - 'password_mismatch': ("The two password fields didn't match."), + 'password_mismatch': _("The two password fields didn't match."), } - new_password1 = forms.CharField(label=("New password"), + new_password1 = forms.CharField(label=_("New password"), widget=forms.PasswordInput) - new_password2 = forms.CharField(label=("New password confirmation"), + new_password2 = forms.CharField(label=_("New password confirmation"), widget=forms.PasswordInput) def clean_new_password2(self): From 3e32e5127be5eebc9107edd7c791ad3f87f9a1c9 Mon Sep 17 00:00:00 2001 From: PCoder Date: Sun, 24 Sep 2017 15:55:52 +0530 Subject: [PATCH 15/47] Added ResendActivationLinkViewMixin --- utils/views.py | 45 +++++++++++++++++++++++++++++++++++++++------ 1 file changed, 39 insertions(+), 6 deletions(-) diff --git a/utils/views.py b/utils/views.py index 3150fa6d..4ec39bce 100644 --- a/utils/views.py +++ b/utils/views.py @@ -2,6 +2,7 @@ from django.conf import settings from django.contrib import messages from django.contrib.auth import authenticate, login from django.contrib.auth.tokens import default_token_generator +from django.core.urlresolvers import reverse_lazy from django.http import HttpResponseRedirect from django.utils.encoding import force_bytes from django.utils.http import urlsafe_base64_encode, urlsafe_base64_decode @@ -63,9 +64,45 @@ class LoginViewMixin(FormView): return super(LoginViewMixin, self).get(request, *args, **kwargs) +class ResendActivationLinkViewMixin(FormView): + success_message = _( + "An email with the activation link has been sent to your email") + + def generate_email_context(self, user): + context = { + 'base_url': "{0}://{1}".format(self.request.scheme, + self.request.get_host()), + 'activation_link': reverse_lazy( + 'hosting:validate', + kwargs={'validate_slug': user.validation_slug} + ), + 'dcl_text': settings.DCL_TEXT, + } + return context + + def form_valid(self, form): + email = form.cleaned_data.get('email') + user = CustomUser.objects.get(email=email) + messages.add_message(self.request, messages.SUCCESS, + self.success_message) + context = self.generate_email_context(user) + email_data = { + 'subject': '{dcl_text} {account_activation}'.format( + dcl_text=settings.DCL_TEXT, + account_activation=_('Account Activation') + ), + 'to': email, + 'context': context, + 'template_name': self.email_template_name, + 'template_path': self.email_template_path, + 'from_address': settings.DCL_SUPPORT_FROM_ADDRESS + } + email = BaseEmail(**email_data) + email.send() + return HttpResponseRedirect(self.get_success_url()) + + class PasswordResetViewMixin(FormView): - # template_name = 'hosting/reset_password.html' - # form_class = PasswordResetRequestForm success_message = _( "The link to reset your email has been sent to your email") site = '' @@ -78,7 +115,6 @@ class PasswordResetViewMixin(FormView): 'site_name': 'ungleich' if self.site != 'dcl' else settings.DCL_TEXT, 'base_url': "{0}://{1}".format(self.request.scheme, self.request.get_host()) - } return context @@ -104,11 +140,8 @@ class PasswordResetViewMixin(FormView): class PasswordResetConfirmViewMixin(FormView): - # template_name = 'hosting/confirm_reset_password.html' form_class = SetPasswordForm - # success_url = reverse_lazy('hosting:login') - def post(self, request, uidb64=None, token=None, *arg, **kwargs): try: uid = urlsafe_base64_decode(uidb64) From 24522908e0332b6135fadc7c789df662a591d85f Mon Sep 17 00:00:00 2001 From: PCoder Date: Sun, 24 Sep 2017 16:02:06 +0530 Subject: [PATCH 16/47] Added resend activation link to login page --- hosting/templates/hosting/login.html | 2 ++ 1 file changed, 2 insertions(+) diff --git a/hosting/templates/hosting/login.html b/hosting/templates/hosting/login.html index 9f18fda9..82056d2f 100644 --- a/hosting/templates/hosting/login.html +++ b/hosting/templates/hosting/login.html @@ -44,6 +44,8 @@ {% trans "Sign up"%} or {% trans "Forgot your password ? "%} + or
+ {% trans "Resend activation link"%} From 84db1606a346707ec50464a5c7d9dd16a95ffec1 Mon Sep 17 00:00:00 2001 From: PCoder Date: Sun, 24 Sep 2017 18:04:11 +0530 Subject: [PATCH 17/47] Added resend_activation_link.html template file --- .../hosting/resend_activation_link.html | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 hosting/templates/hosting/resend_activation_link.html diff --git a/hosting/templates/hosting/resend_activation_link.html b/hosting/templates/hosting/resend_activation_link.html new file mode 100644 index 00000000..fffb6e59 --- /dev/null +++ b/hosting/templates/hosting/resend_activation_link.html @@ -0,0 +1,36 @@ +{% extends "hosting/base_short.html" %} +{% load staticfiles bootstrap3%} +{% load i18n %} + +{% block navbar %} + {% include 'hosting/includes/_navbar_transparent.html' %} +{% endblock navbar %} + + +{% block content %} +
+
+
+
+

{% trans "Your VM hosted in Switzerland"%}

+
+
+ +
+
+
+{% endblock %} From cd5607b44e9f062707450601026e99fcdf9f0246 Mon Sep 17 00:00:00 2001 From: PCoder Date: Sun, 24 Sep 2017 19:04:18 +0530 Subject: [PATCH 18/47] Updated hosting django.po --- hosting/locale/de/LC_MESSAGES/django.po | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/hosting/locale/de/LC_MESSAGES/django.po b/hosting/locale/de/LC_MESSAGES/django.po index b273dbcf..0db6580d 100644 --- a/hosting/locale/de/LC_MESSAGES/django.po +++ b/hosting/locale/de/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2017-09-23 19:00+0530\n" +"POT-Creation-Date: 2017-09-24 12:34+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -306,6 +306,9 @@ msgstr "Registrieren" msgid "Forgot your password ? " msgstr "Passwort vergessen?" +msgid "Resend activation link" +msgstr "" + msgid "Notifications" msgstr "Benachrichtigungen" @@ -601,8 +604,11 @@ msgstr "" #, python-format msgid "" -"Your Virtual Machine %(virtual_machine.name)s is successfully terminated!" -msgstr "Deine Virtuelle Machine (VM) %(virtual_machine.name)s wurde erfolgreich beendet!" +"Your Virtual Machine %(machine_name)s is successfully " +"terminated!" +msgstr "" +"Deine Virtuelle Machine (VM) %(machine_name)s wurde erfolgreich " +"beendet!" msgid "Virtual Machines" msgstr "Virtuelle Maschinen" From a45679d89a3c97da8e046f4b7464645a550de6b1 Mon Sep 17 00:00:00 2001 From: PCoder Date: Mon, 25 Sep 2017 00:00:45 +0530 Subject: [PATCH 19/47] Added VMDetail model --- hosting/models.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/hosting/models.py b/hosting/models.py index 478ed745..73c082bb 100644 --- a/hosting/models.py +++ b/hosting/models.py @@ -159,3 +159,16 @@ class HostingBill(AssignPermissionsMixin, models.Model): instance = cls.objects.create(customer=customer, billing_address=billing_address) return instance + + +class VMDetail(models.Model): + user = models.ForeignKey(CustomUser) + vm_id = models.IntegerField(default=0) + disk_size = models.FloatField(default=0.0) + cores = models.FloatField(default=0.0) + memory = models.FloatField(default=0.0) + configuration = models.CharField(default='', max_length=25) + ipv4 = models.TextField(default='') + ipv6 = models.TextField(default='') + created_at = models.DateTimeField(auto_now_add=True) + terminated_at = models.DateTimeField(null=True) From f4899ffc184a849f4a56b4796667ad19ae0b5c9e Mon Sep 17 00:00:00 2001 From: PCoder Date: Mon, 25 Sep 2017 00:01:48 +0530 Subject: [PATCH 20/47] Added missing get_language import --- hosting/views.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hosting/views.py b/hosting/views.py index d7c4c168..7ce66e57 100644 --- a/hosting/views.py +++ b/hosting/views.py @@ -16,7 +16,7 @@ from django.http import Http404, HttpResponseRedirect, HttpResponse from django.shortcuts import redirect, render from django.utils.http import urlsafe_base64_decode from django.utils.safestring import mark_safe -from django.utils.translation import ugettext_lazy as _ +from django.utils.translation import get_language, ugettext_lazy as _ from django.utils.translation import ugettext from django.views.generic import ( View, CreateView, FormView, ListView, DetailView, DeleteView, From 7278a201358dbc4c00c5cbefb860d35c0d63d571 Mon Sep 17 00:00:00 2001 From: PCoder Date: Mon, 25 Sep 2017 00:02:36 +0530 Subject: [PATCH 21/47] Added get_or_create_vm_detail function --- datacenterlight/tasks.py | 5 +++-- utils/hosting_utils.py | 39 ++++++++++++++++++++++++++++++++++++++- 2 files changed, 41 insertions(+), 3 deletions(-) diff --git a/datacenterlight/tasks.py b/datacenterlight/tasks.py index 1335869b..fd83a320 100644 --- a/datacenterlight/tasks.py +++ b/datacenterlight/tasks.py @@ -9,11 +9,11 @@ from django.utils import translation from django.utils.translation import ugettext_lazy as _ from dynamicweb.celery import app -from hosting.models import HostingOrder, HostingBill +from hosting.models import HostingOrder, HostingBill, VMDetail from membership.models import StripeCustomer, CustomUser from opennebula_api.models import OpenNebulaManager from opennebula_api.serializers import VirtualMachineSerializer -from utils.hosting_utils import get_all_public_keys +from utils.hosting_utils import get_all_public_keys, get_or_create_vm_detail from utils.forms import UserBillingAddressForm from utils.mailer import BaseEmail from utils.models import BillingAddress @@ -174,6 +174,7 @@ def create_vm_task(self, vm_template_id, user, specs, template, logger.debug("New VM ID is {vm_id}".format(vm_id=vm_id)) if new_host 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 diff --git a/utils/hosting_utils.py b/utils/hosting_utils.py index 7c1a83ad..7faf2a29 100644 --- a/utils/hosting_utils.py +++ b/utils/hosting_utils.py @@ -1,5 +1,10 @@ -from hosting.models import UserHostingKey +import logging +from oca.pool import WrongIdError +from hosting.models import UserHostingKey, VMDetail +from opennebula_api.serializers import VirtualMachineSerializer + +logger = logging.getLogger(__name__) def get_all_public_keys(customer): """ @@ -9,3 +14,35 @@ def get_all_public_keys(customer): """ return UserHostingKey.objects.filter(user_id=customer.id).values_list( "public_key", flat=True) + + +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 From f2f2fc22df5aae4a0f787ecc20ed4f38bdcb4a1e Mon Sep 17 00:00:00 2001 From: PCoder Date: Mon, 25 Sep 2017 00:30:28 +0530 Subject: [PATCH 22/47] Update VMDetail's terminated_at on delete of a vm --- hosting/views.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/hosting/views.py b/hosting/views.py index 7ce66e57..19c02979 100644 --- a/hosting/views.py +++ b/hosting/views.py @@ -1,6 +1,7 @@ import json import logging import uuid +from datetime import datetime from time import sleep from django import forms @@ -43,7 +44,9 @@ from utils.views import ( from .forms import HostingUserSignupForm, HostingUserLoginForm, \ UserHostingKeyForm, generate_ssh_key_name from .mixins import ProcessVMSelectionMixin -from .models import HostingOrder, HostingBill, HostingPlan, UserHostingKey +from .models import ( + HostingOrder, HostingBill, HostingPlan, UserHostingKey, VMDetail +) from datacenterlight.models import VMTemplate @@ -1043,6 +1046,9 @@ class VirtualMachineView(LoginRequiredMixin, View): except WrongIdError: response['status'] = True response['text'] = ugettext('Terminated') + vm_detail_obj = VMDetail.objects.filter(vm_id=opennebula_vm_id).first() + vm_detail_obj.terminated_at = datetime.utcnow() + vm_detail_obj.save() break except BaseException: break From 114511e9240762c283d5452783d494e0fc3bb21f Mon Sep 17 00:00:00 2001 From: PCoder Date: Mon, 25 Sep 2017 00:34:18 +0530 Subject: [PATCH 23/47] Fixed some flake8 warnings --- datacenterlight/tasks.py | 4 ++-- utils/hosting_utils.py | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/datacenterlight/tasks.py b/datacenterlight/tasks.py index fd83a320..a5496d83 100644 --- a/datacenterlight/tasks.py +++ b/datacenterlight/tasks.py @@ -9,7 +9,7 @@ from django.utils import translation from django.utils.translation import ugettext_lazy as _ from dynamicweb.celery import app -from hosting.models import HostingOrder, HostingBill, VMDetail +from hosting.models import HostingOrder, HostingBill from membership.models import StripeCustomer, CustomUser from opennebula_api.models import OpenNebulaManager from opennebula_api.serializers import VirtualMachineSerializer @@ -142,7 +142,7 @@ def create_vm_task(self, vm_template_id, user, specs, template, email.send() if 'pass' in user: - lang = 'en-us' + lang = 'en-us' if user.get('language') is not None: logger.debug("Language is set to {}".format(user.get('language'))) lang = user.get('language') diff --git a/utils/hosting_utils.py b/utils/hosting_utils.py index 7faf2a29..09f81536 100644 --- a/utils/hosting_utils.py +++ b/utils/hosting_utils.py @@ -6,6 +6,7 @@ from opennebula_api.serializers import VirtualMachineSerializer logger = logging.getLogger(__name__) + def get_all_public_keys(customer): """ Returns all the public keys of the user From 83ccb9cffae5475e3b8626a0e90dbe07b2c5a29f Mon Sep 17 00:00:00 2001 From: PCoder Date: Mon, 25 Sep 2017 00:36:33 +0530 Subject: [PATCH 24/47] Added vmdetail migration file --- hosting/migrations/0043_vmdetail.py | 34 +++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 hosting/migrations/0043_vmdetail.py diff --git a/hosting/migrations/0043_vmdetail.py b/hosting/migrations/0043_vmdetail.py new file mode 100644 index 00000000..66966233 --- /dev/null +++ b/hosting/migrations/0043_vmdetail.py @@ -0,0 +1,34 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.4 on 2017-09-24 18:12 +from __future__ import unicode_literals + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('hosting', '0042_hostingorder_subscription_id'), + ] + + operations = [ + migrations.CreateModel( + name='VMDetail', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('vm_id', models.IntegerField(default=0)), + ('disk_size', models.FloatField(default=0.0)), + ('cores', models.FloatField(default=0.0)), + ('memory', models.FloatField(default=0.0)), + ('configuration', models.CharField(default='', max_length=25)), + ('ipv4', models.TextField(default='')), + ('ipv6', models.TextField(default='')), + ('created_at', models.DateTimeField(auto_now_add=True)), + ('terminated_at', models.DateTimeField(null=True)), + ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), + ], + ), + ] From f2213305f61fff09509d4f82dd0b5db875ec9edd Mon Sep 17 00:00:00 2001 From: PCoder Date: Mon, 25 Sep 2017 00:46:39 +0530 Subject: [PATCH 25/47] Reformatted hosting views.py --- hosting/views.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hosting/views.py b/hosting/views.py index 19c02979..77bf05b7 100644 --- a/hosting/views.py +++ b/hosting/views.py @@ -49,7 +49,6 @@ from .models import ( ) from datacenterlight.models import VMTemplate - logger = logging.getLogger(__name__) CONNECTION_ERROR = "Your VMs cannot be displayed at the moment due to a \ @@ -1046,7 +1045,8 @@ class VirtualMachineView(LoginRequiredMixin, View): except WrongIdError: response['status'] = True response['text'] = ugettext('Terminated') - vm_detail_obj = VMDetail.objects.filter(vm_id=opennebula_vm_id).first() + vm_detail_obj = VMDetail.objects.filter( + vm_id=opennebula_vm_id).first() vm_detail_obj.terminated_at = datetime.utcnow() vm_detail_obj.save() break From 7fcece40c1d986c66380509d55f250aca06fd125 Mon Sep 17 00:00:00 2001 From: PCoder Date: Mon, 25 Sep 2017 01:49:00 +0530 Subject: [PATCH 26/47] Using VMDetail model to show order details --- hosting/views.py | 42 +++++++++++++++++++++++------------------- 1 file changed, 23 insertions(+), 19 deletions(-) diff --git a/hosting/views.py b/hosting/views.py index 77bf05b7..577715ca 100644 --- a/hosting/views.py +++ b/hosting/views.py @@ -680,25 +680,29 @@ class OrdersHostingDetailView(LoginRequiredMixin, if obj is not None: # invoice for previous order try: - manager = OpenNebulaManager( - email=owner.email, password=owner.password - ) - 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.') - ) + vm_detail = VMDetail.objects.get(vm_id=obj.vm_id) + context['vm'] = vm_detail.__dict__ + except VMDetail.DoesNotExist: + try: + manager = OpenNebulaManager( + email=owner.email, password=owner.password + ) + 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.') + ) elif not card_details.get('response_object'): # new order, failed to get card details context['failed_payment'] = True From 46d82268f41c002a6b6d74fad89ae62db8f7efbe Mon Sep 17 00:00:00 2001 From: PCoder Date: Mon, 25 Sep 2017 02:04:40 +0530 Subject: [PATCH 27/47] Show terminated in invoice for VM that has been terminated --- hosting/templates/hosting/order_detail.html | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/hosting/templates/hosting/order_detail.html b/hosting/templates/hosting/order_detail.html index 345632d2..ece84a9e 100644 --- a/hosting/templates/hosting/order_detail.html +++ b/hosting/templates/hosting/order_detail.html @@ -42,7 +42,9 @@

{% trans "Status" %}: - {% if order.status == 'Approved' %} + {% if vm.terminated_at %} + {% trans "Terminated" %} + {% elif order.status == 'Approved' %} {% trans "Approved" %} {% else %} {% trans "Declined" %} @@ -202,4 +204,4 @@ -{% endblock js_extra %} \ No newline at end of file +{% endblock js_extra %} From 70d5efb21a230c53de61f1c51219a75567d63d5f Mon Sep 17 00:00:00 2001 From: PCoder Date: Mon, 25 Sep 2017 02:09:49 +0530 Subject: [PATCH 28/47] Update hosting django.po with a de translation --- hosting/locale/de/LC_MESSAGES/django.po | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hosting/locale/de/LC_MESSAGES/django.po b/hosting/locale/de/LC_MESSAGES/django.po index 0db6580d..ec11986b 100644 --- a/hosting/locale/de/LC_MESSAGES/django.po +++ b/hosting/locale/de/LC_MESSAGES/django.po @@ -307,7 +307,7 @@ msgid "Forgot your password ? " msgstr "Passwort vergessen?" msgid "Resend activation link" -msgstr "" +msgstr "Aktivierungslink noch einmal senden" msgid "Notifications" msgstr "Benachrichtigungen" From 75ff7e4ea86f14bce202d2cf0dc202734a1e2872 Mon Sep 17 00:00:00 2001 From: PCoder Date: Tue, 26 Sep 2017 01:53:19 +0530 Subject: [PATCH 29/47] Added some translations --- utils/locale/de/LC_MESSAGES/django.po | 30 +++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/utils/locale/de/LC_MESSAGES/django.po b/utils/locale/de/LC_MESSAGES/django.po index 794b5fd9..04d1f4dc 100644 --- a/utils/locale/de/LC_MESSAGES/django.po +++ b/utils/locale/de/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2017-09-02 11:50+0000\n" +"POT-Creation-Date: 2017-09-25 20:11+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -738,6 +738,24 @@ msgstr "" msgid "Enter your name or company name" msgstr "Geben Sie Ihren Namen oder der Ihrer Firma ein" +msgid "Your username and/or password were incorrect." +msgstr "Dein Benutzername und/oder Dein Passwort ist falsch." + +msgid "User does not exist" +msgstr "Der Benutzer existiert nicht" + +msgid "The account is already active." +msgstr "" + +msgid "The two password fields didn't match." +msgstr "" + +msgid "New password" +msgstr "" + +msgid "New password confirmation" +msgstr "" + msgid "Cardholder Name" msgstr "Name des Kartenbesitzer" @@ -768,8 +786,16 @@ msgstr "Telefon" msgid "Message" msgstr "Nachricht" +msgid "An email with the activation link has been sent to your email" +msgstr "" +"Der Link zum Zurücksetzen deines Passwortes wurde an deine E-Mail gesendet" + +msgid "Account Activation" +msgstr "Accountaktivierung" + msgid "The link to reset your email has been sent to your email" -msgstr "Der Link zum Zurücksetzen deines Passwortes wurde an deine E-Mail gesendet" +msgstr "" +"Der Link zum Zurücksetzen deines Passwortes wurde an deine E-Mail gesendet" msgid "Password Reset" msgstr "Passwort zurücksetzen" From 6bf89669eff4b8faef57eba42097a97778a5e33c Mon Sep 17 00:00:00 2001 From: PCoder Date: Tue, 26 Sep 2017 02:07:28 +0530 Subject: [PATCH 30/47] some more de translations --- utils/locale/de/LC_MESSAGES/django.po | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/utils/locale/de/LC_MESSAGES/django.po b/utils/locale/de/LC_MESSAGES/django.po index 04d1f4dc..f8374e4e 100644 --- a/utils/locale/de/LC_MESSAGES/django.po +++ b/utils/locale/de/LC_MESSAGES/django.po @@ -745,16 +745,16 @@ msgid "User does not exist" msgstr "Der Benutzer existiert nicht" msgid "The account is already active." -msgstr "" +msgstr "Das Benutzerkonto ist bereits aktiv." msgid "The two password fields didn't match." -msgstr "" +msgstr "Die beiden Passwörter stimmen nicht überein." msgid "New password" -msgstr "" +msgstr "Neues Passwort" msgid "New password confirmation" -msgstr "" +msgstr "Neues Passwort Bestätigung" msgid "Cardholder Name" msgstr "Name des Kartenbesitzer" From 7933584942bee21a167c46e21c0f06f75410249d Mon Sep 17 00:00:00 2001 From: PCoder Date: Tue, 26 Sep 2017 02:13:49 +0530 Subject: [PATCH 31/47] Updated changelog --- Changelog | 1 + 1 file changed, 1 insertion(+) diff --git a/Changelog b/Changelog index 7ba5e634..7f4394dd 100644 --- a/Changelog +++ b/Changelog @@ -6,6 +6,7 @@ Pre-changelog: 1.2.3 2017-09-20 * #3786: [hosting] Redesigned the hosting invoice and order-confirmation page * #3728: [hosting] VM Termination animation added * #3777: [hosting] Create new VM calculator added like dcl landing + * #3781: [hosting] Resend activation mail * #3806: [hosting] Fix can not create VMs after password reset * Feature: [cms, blog] Added /cms prefix for all the django-cms generated urls * Bugfix: [dcl, hosting] added host to celery error mails From 29a45e81bf943beeeaf43260b096f0c38bbc32af Mon Sep 17 00:00:00 2001 From: PCoder Date: Tue, 26 Sep 2017 02:24:17 +0530 Subject: [PATCH 32/47] Include cdist 4.7.0 in requirements.txt --- requirements.txt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/requirements.txt b/requirements.txt index 6446a5c9..89285c83 100644 --- a/requirements.txt +++ b/requirements.txt @@ -96,5 +96,4 @@ pyflakes==1.5.0 billiard==3.5.0.3 amqp==2.2.1 vine==1.1.4 -#git+https://github.com/ungleich/cdist.git#egg=cdist -file:///home/app/cdist#egg=cdist +cdist==4.7.0 From 543465e89bbb154d0845f3287d64967e0320ca77 Mon Sep 17 00:00:00 2001 From: PCoder Date: Tue, 26 Sep 2017 02:34:10 +0530 Subject: [PATCH 33/47] Update Changelog for 1.2.3 --- Changelog | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Changelog b/Changelog index 7f4394dd..f03a04ed 100644 --- a/Changelog +++ b/Changelog @@ -1,4 +1,4 @@ -Pre-changelog: 1.2.3 2017-09-20 +1.2.3: 2017-09-25 * #3484: [dcl, hosting] Refactored account activation, password reset, VM order and cancellation email * #3731: [dcl, hosting] Added cdist ssh key handler * #3628: [dcl] on hosting, VM is created at credit card info submit From f35c3dbc10f190182d57042553a9c00a36187795 Mon Sep 17 00:00:00 2001 From: Arvind Tiwari Date: Tue, 26 Sep 2017 02:38:31 +0530 Subject: [PATCH 34/47] modal check icon thinner, terminate modal text smaller --- .../datacenterlight/css/landing-page.css | 17 +++++++++ .../datacenterlight/beta_success.html | 2 +- hosting/static/hosting/css/landing-page.css | 38 +++++++++++++++++++ .../hosting/js/virtual_machine_detail.js | 21 +++++----- hosting/templates/hosting/order_detail.html | 9 ++--- .../hosting/virtual_machine_detail.html | 7 ++-- hosting/views.py | 1 - 7 files changed, 74 insertions(+), 21 deletions(-) diff --git a/datacenterlight/static/datacenterlight/css/landing-page.css b/datacenterlight/static/datacenterlight/css/landing-page.css index 6537dd0d..d50a864d 100755 --- a/datacenterlight/static/datacenterlight/css/landing-page.css +++ b/datacenterlight/static/datacenterlight/css/landing-page.css @@ -1653,3 +1653,20 @@ a.list-group-item-danger.active:focus { .panel-danger > .panel-heading .badge { background-color: #eb4d5c; } + +.checkmark { + display: inline-block; +} +.checkmark:after { + /*Add another block-level blank space*/ + content: ''; + display: block; + /*Make it a small rectangle so the border will create an L-shape*/ + width: 25px; + height: 60px; + /*Add a white border on the bottom and left, creating that 'L' */ + border: solid #777; + border-width: 0 3px 3px 0; + /*Rotate the L 45 degrees to turn it into a checkmark*/ + transform: rotate(45deg); +} diff --git a/datacenterlight/templates/datacenterlight/beta_success.html b/datacenterlight/templates/datacenterlight/beta_success.html index 2512a05c..60df607c 100644 --- a/datacenterlight/templates/datacenterlight/beta_success.html +++ b/datacenterlight/templates/datacenterlight/beta_success.html @@ -8,7 +8,7 @@

diff --git a/hosting/static/hosting/css/landing-page.css b/hosting/static/hosting/css/landing-page.css index ed8fb310..5275dd97 100644 --- a/hosting/static/hosting/css/landing-page.css +++ b/hosting/static/hosting/css/landing-page.css @@ -870,3 +870,41 @@ a.list-group-item-danger.active:focus { .panel-danger > .panel-heading .badge { background-color: #eb4d5c; } + +.checkmark { + display: inline-block; +} +.checkmark:after { + /*Add another block-level blank space*/ + content: ''; + display: block; + /*Make it a small rectangle so the border will create an L-shape*/ + width: 25px; + height: 60px; + /*Add a white border on the bottom and left, creating that 'L' */ + border: solid #777; + border-width: 0 3px 3px 0; + /*Rotate the L 45 degrees to turn it into a checkmark*/ + transform: rotate(45deg); +} + +.closemark { + display: inline-block; + width: 50px; + height: 50px; + position: relative; +} +.closemark:before, .closemark:after { + position: absolute; + left: 25px; + content: ' '; + height: 50px; + width: 2px; + background-color: #777; +} +.closemark:before { + transform: rotate(45deg); +} +.closemark:after { + transform: rotate(-45deg); +} diff --git a/hosting/static/hosting/js/virtual_machine_detail.js b/hosting/static/hosting/js/virtual_machine_detail.js index db2621c1..ca79df56 100644 --- a/hosting/static/hosting/js/virtual_machine_detail.js +++ b/hosting/static/hosting/js/virtual_machine_detail.js @@ -79,7 +79,6 @@ $(document).ready(function() { $('html,body').scrollTop(scrollmem); }); - $('.modal-text').removeClass('hide'); var create_vm_form = $('#virtual_machine_create_form'); create_vm_form.submit(function () { $('#btn-create-vm').prop('disabled', true); @@ -90,26 +89,28 @@ $(document).ready(function() { success: function (data) { if (data.status === true) { fa_icon = $('.modal-icon > .fa'); - fa_icon.attr('class', 'fa fa-check'); - $('.modal-header > .close').attr('class', 'close'); + fa_icon.attr('class', 'checkmark'); + // $('.modal-header > .close').removeClass('hidden'); $('#createvm-modal-title').text(data.msg_title); $('#createvm-modal-body').text(data.msg_body); - $('#createvm-modal').on('hidden.bs.modal', function () { - window.location = data.redirect; - }) + $('#createvm-modal-done-btn').removeClass('hide'); } }, error: function (xmlhttprequest, textstatus, message) { fa_icon = $('.modal-icon > .fa'); - fa_icon.attr('class', 'fa fa-times'); - $('.modal-header > .close').attr('class', 'close'); - $('.modal-text').addClass('hide'); + fa_icon.attr('class', 'fa fa-close'); + // $('.modal-header > .close').attr('class', 'close'); + // $('.modal-text').addClass('hide'); if (typeof(create_vm_error_message) !== 'undefined') { - $('#createvm-modal-title').text(create_vm_error_message); + $('#createvm-modal-text').text(create_vm_error_message); } $('#btn-create-vm').prop('disabled', false); + $('#createvm-modal-close-btn').removeClass('hide'); } }); return false; }); + $('#createvm-modal').on('hidden.bs.modal', function () { + $(this).find('.modal-footer .btn').addClass('hide'); + }) }); diff --git a/hosting/templates/hosting/order_detail.html b/hosting/templates/hosting/order_detail.html index 345632d2..699a2d37 100644 --- a/hosting/templates/hosting/order_detail.html +++ b/hosting/templates/hosting/order_detail.html @@ -160,22 +160,19 @@ @@ -123,8 +123,9 @@ From 858fdd5e3f192bceba3da7bda58e3126245751ba Mon Sep 17 00:00:00 2001 From: Arvind Tiwari Date: Thu, 28 Sep 2017 02:11:11 +0530 Subject: [PATCH 44/47] Update order_detail.html --- hosting/templates/hosting/order_detail.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hosting/templates/hosting/order_detail.html b/hosting/templates/hosting/order_detail.html index 08b52770..59b0bcd6 100644 --- a/hosting/templates/hosting/order_detail.html +++ b/hosting/templates/hosting/order_detail.html @@ -173,7 +173,7 @@ {% trans "Hold tight, we are processing your request" %} From 4e080c9afc98c6db23e3b2dede914897ba587ec1 Mon Sep 17 00:00:00 2001 From: PCoder Date: Thu, 28 Sep 2017 02:36:49 +0530 Subject: [PATCH 45/47] Invoice: Get VM name from id and configuration --- hosting/views.py | 1 + 1 file changed, 1 insertion(+) diff --git a/hosting/views.py b/hosting/views.py index e694f55b..4d736aa8 100644 --- a/hosting/views.py +++ b/hosting/views.py @@ -694,6 +694,7 @@ class OrdersHostingDetailView(LoginRequiredMixin, try: vm_detail = VMDetail.objects.get(vm_id=obj.vm_id) context['vm'] = vm_detail.__dict__ + context['vm']['name'] = '{}-{}'.format(context['vm']['configuration'], context['vm']['vm_id']) except VMDetail.DoesNotExist: try: manager = OpenNebulaManager( From df67fa3333c77976ae823641413ecd28c33f5018 Mon Sep 17 00:00:00 2001 From: Arvind Tiwari Date: Thu, 28 Sep 2017 02:39:55 +0530 Subject: [PATCH 46/47] period added --- hosting/templates/hosting/order_detail.html | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/hosting/templates/hosting/order_detail.html b/hosting/templates/hosting/order_detail.html index 59b0bcd6..462593f8 100644 --- a/hosting/templates/hosting/order_detail.html +++ b/hosting/templates/hosting/order_detail.html @@ -98,14 +98,12 @@

- {% comment %}

- {% trans "Period" %} - {{}} + {% trans "Period" %}: + {{ vm.created_at|date:'Y/m/d' }} - {% if vm.terminated_at %}{{ vm.terminated_at|date:'Y/m/d' }}{% else %}{% now 'Y/m/d' %}{% endif %}

- {% endcomment %}

- {% trans "Cores" %} + {% trans "Cores" %}: {% if vm.cores %} {{vm.cores|floatformat}} {% else %} @@ -113,11 +111,11 @@ {% endif %}

- {% trans "Memory" %} + {% trans "Memory" %}: {{vm.memory}} GB

- {% trans "Disk space" %} + {% trans "Disk space" %}: {{vm.disk_size}} GB

From 3ba1f191a302d4226ad44a054846ac580e4d9547 Mon Sep 17 00:00:00 2001 From: Arvind Tiwari Date: Thu, 28 Sep 2017 02:47:58 +0530 Subject: [PATCH 47/47] show period if dates exist --- hosting/templates/hosting/order_detail.html | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/hosting/templates/hosting/order_detail.html b/hosting/templates/hosting/order_detail.html index 462593f8..dc8de901 100644 --- a/hosting/templates/hosting/order_detail.html +++ b/hosting/templates/hosting/order_detail.html @@ -98,10 +98,12 @@

-

- {% trans "Period" %}: - {{ vm.created_at|date:'Y/m/d' }} - {% if vm.terminated_at %}{{ vm.terminated_at|date:'Y/m/d' }}{% else %}{% now 'Y/m/d' %}{% endif %} -

+ {% if vm.created_at %} +

+ {% trans "Period" %}: + {{ vm.created_at|date:'Y/m/d' }} - {% if vm.terminated_at %}{{ vm.terminated_at|date:'Y/m/d' }}{% else %}{% now 'Y/m/d' %}{% endif %} +

+ {% endif %}

{% trans "Cores" %}: {% if vm.cores %}