Merge branch 'master' into task/3530/upgrade_to_django_1.11

This commit is contained in:
PCoder 2017-12-24 20:19:05 +01:00
commit 4069199252
18 changed files with 164 additions and 109 deletions

View file

@ -2,6 +2,12 @@ Next:
* #3911: [dcl] Integrate resend activation link into dcl landing payment page
* #3972: [hosting] Add ungleich company info to invoice footer
* #3974: [hosting] Improve invoice number: Show 404 for invoice resources that do not belong to the user
* [ungleich] Add video cover to the header on ungleich.ch landing page and add corresponding cms plugin
* #3774: [hosting] Update Stripe subscription on vm delete
* [ungleich] Update text on landing page
* #3601: [dcl, hosting] Change minimum required RAM from 2GB to 1GB
* #3973: [dcl] Update datacenterlight and glasfaser contact address to Linthal and company name to "ungleich glarus ag"
* #3993: [dg] Fix new user membership payment by setting cardholder_name field for UserBillingAddressForm
1.2.13: 2017-12-09
* [cms] Introduce UngleichHeaderBackgroundImageAndTextSliderPlugin that allows to have scrolling images and texts
* [cms] Remove <p> tag for ungleich cms customer item template

View file

@ -56,11 +56,11 @@ msgstr "Standort: Schweiz"
msgid "Please enter a value in range 1 - 48."
msgstr "Bitte gib einen Wert von 1 bis 48 ein."
msgid "Please enter a value in range 2 - 200."
msgstr "Bitte gib einen Wert von 2 bis 200 ein."
msgid "Please enter a value in range 1 - 200."
msgstr "Bitte gib einen Wert von 1 bis 200 ein."
msgid "Please enter a value in range 10 - 2000."
msgstr "Bitte gib einen Wert von 10 bis 200 ein."
msgstr "Bitte gib einen Wert von 10 bis 2000 ein."
msgid "GB Storage (SSD)"
msgstr "GB Storage (SSD)"

View file

@ -16,7 +16,7 @@
'ram': {
'id': 'ramValue',
'value': 2,
'min': 2,
'min': 1,
'max': 200,
'interval': 1
},

View file

@ -36,8 +36,8 @@
<div class="form-group">
<div class="description input">
<i class="fa fa-minus-circle left" data-minus="ram" aria-hidden="true"></i>
<input id="ramValue" class="input-price select-number" type="number" min="2" max="200" name="ram"
data-error="{% trans 'Please enter a value in range 2 - 200.' %}" required>
<input id="ramValue" class="input-price select-number" type="number" min="1" max="200" name="ram"
data-error="{% trans 'Please enter a value in range 1 - 200.' %}" required>
<span> GB RAM</span>
<i class="fa fa-plus-circle right" data-plus="ram" aria-hidden="true"></i>
</div>

View file

@ -160,11 +160,11 @@
</div>
<div class="contact-details">
<div class="subtitle">
<h3>ungleich GmbH</h3>
<h3>ungleich glarus ag</h3>
</div>
<div class="description">
<p>info@datacenterlight.ch</p>
<p>In der Au 7, Schwanden 8762</p>
<p>Bahnhofstrasse 1, 8783 Linthal</p>
<p>{% trans "Switzerland " %}</p>
</div>
</div>

View file

@ -209,7 +209,7 @@ class IndexView(CreateView):
raise ValidationError(_('Invalid number of cores'))
def validate_memory(self, value):
if (value > 200) or (value < 2):
if (value > 200) or (value < 1):
raise ValidationError(_('Invalid RAM size'))
def validate_storage(self, value):

View file

@ -376,6 +376,10 @@ class MembershipPaymentView(LoginRequiredMixin, IsNotMemberMixin, FormView):
return render(request, self.template_name, context)
charge = charge_response.get('response_object')
if 'source' in charge:
cardholder_name = charge['source']['name']
else:
cardholder_name = customer.user.name
# Create Billing Address
billing_address = form.save()
@ -383,7 +387,8 @@ class MembershipPaymentView(LoginRequiredMixin, IsNotMemberMixin, FormView):
# Create Billing Address for User if he does not have one
if not customer.user.billing_addresses.count():
data.update({
'user': customer.user.id
'user': customer.user.id,
'cardholder_name': cardholder_name
})
billing_address_user_form = UserBillingAddressForm(data)
billing_address_user_form.is_valid()

View file

@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2017-10-26 03:21+0530\n"
"POT-Creation-Date: 2017-12-21 00:23+0000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@ -128,11 +128,11 @@ msgstr "MwSt. inklusive"
msgid "Please enter a value in range 1 - 48."
msgstr "Bitte gib einen Wert von 1 bis 48 ein."
msgid "Please enter a value in range 2 - 200."
msgstr "Bitte gib einen Wert von 2 bis 200 ein."
msgid "Please enter a value in range 1 - 200."
msgstr "Bitte gib einen Wert von 1 bis 200 ein."
msgid "Please enter a value in range 10 - 2000."
msgstr "Bitte gib einen Wert von 10 bis 200 ein."
msgstr "Bitte gib einen Wert von 10 bis 2000 ein."
msgid "GB Storage (SSD)"
msgstr "GB Storage (SSD)"

View file

@ -12,7 +12,7 @@
'ram': {
'id': 'ramValue',
'value': 2,
'min': 2,
'min': 1,
'max': 200,
'interval': 1
},

View file

@ -29,8 +29,8 @@
<div class="form-group">
<div class="description input">
<i class="fa fa-minus left" data-minus="ram" aria-hidden="true"></i>
<input id="ramValue" class="input-price select-number" type="number" min="2" max="200" name="ram"
data-error="{% trans 'Please enter a value in range 2 - 200.' %}" required>
<input id="ramValue" class="input-price select-number" type="number" min="1" max="200" name="ram"
data-error="{% trans 'Please enter a value in range 1 - 200.' %}" required>
<span> GB RAM</span>
<i class="fa fa-plus right" data-plus="ram" aria-hidden="true"></i>
</div>

View file

@ -41,6 +41,7 @@ from utils.forms import (
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
from utils.views import (
PasswordResetViewMixin, PasswordResetConfirmViewMixin, LoginViewMixin,
ResendActivationLinkViewMixin
@ -945,7 +946,7 @@ class CreateVirtualMachinesView(LoginRequiredMixin, View):
raise ValidationError(_('Invalid number of cores'))
def validate_memory(self, value):
if (value > 200) or (value < 2):
if (value > 200) or (value < 1):
raise ValidationError(_('Invalid RAM size'))
def validate_storage(self, value):
@ -1036,7 +1037,7 @@ class VirtualMachineView(LoginRequiredMixin, View):
)
return None
except Exception as error:
print(error)
logger.error(str(error))
raise Http404()
def get_success_url(self):
@ -1079,49 +1080,88 @@ class VirtualMachineView(LoginRequiredMixin, View):
def post(self, request, *args, **kwargs):
response = {'status': False}
admin_email_body = {}
owner = self.request.user
vm = self.get_object()
opennebula_vm_id = self.kwargs.get('pk')
manager = OpenNebulaManager(
email=owner.email,
password=owner.password
)
try:
vm_data = VirtualMachineSerializer(manager.get_vm(vm.id)).data
vm_name = vm_data.get('name')
except WrongIdError:
except WrongIdError as wrong_id_err:
logger.error(str(wrong_id_err))
return redirect(reverse('hosting:virtual_machines'))
# Cancel Stripe subscription
stripe_utils = StripeUtils()
try:
hosting_order = HostingOrder.objects.get(
vm_id=vm.id
)
result = stripe_utils.unsubscribe_customer(
subscription_id=hosting_order.subscription_id
)
stripe_subscription_obj = result.get('response_object')
# Check if the subscription was canceled
if (stripe_subscription_obj is None or
stripe_subscription_obj.status != 'canceled'):
error_msg = result.get('error')
logger.error(
'Error canceling subscription for {user} and vm id '
'{vm_id}'.format(user=owner.email, vm_id=vm.id)
)
logger.error(error_msg)
admin_email_body['stripe_error_msg'] = error_msg
except HostingOrder.DoesNotExist:
error_msg = (
"HostingOrder corresponding to vm_id={vm_id} does"
"not exist. Hence, can not find subscription to "
"cancel ".format(vm_id=vm.id)
)
logger.error(error_msg)
admin_email_body['stripe_error_msg'] = error_msg
terminated = manager.delete_vm(vm.id)
if not terminated:
response['text'] = ugettext(
'Error terminating VM') + opennebula_vm_id
logger.debug(
"manager.delete_vm returned False. Hence, error making "
"xml-rpc call to delete vm failed."
)
response['text'] = ugettext('Error terminating VM') + vm.id
else:
for t in range(15):
try:
manager.get_vm(opennebula_vm_id)
manager.get_vm(vm.id)
except WrongIdError:
response['status'] = True
response['text'] = ugettext('Terminated')
vm_detail_obj = VMDetail.objects.filter(
vm_id=opennebula_vm_id).first()
vm_id=vm.id
).first()
vm_detail_obj.terminated_at = datetime.utcnow()
vm_detail_obj.save()
break
except BaseException:
except BaseException as base_exception:
logger.error(
"manager.get_vm({vm_id}) returned exception: "
"{details}.".format(
details=str(base_exception), vm_id=vm.id
)
)
break
else:
sleep(2)
context = {
'vm_name': vm_name,
'base_url': "{0}://{1}".format(self.request.scheme,
self.request.get_host()),
'base_url': "{0}://{1}".format(
self.request.scheme, self.request.get_host()
),
'page_header': _('Virtual Machine %(vm_name)s Cancelled') % {
'vm_name': vm_name}
'vm_name': vm_name
}
}
email_data = {
'subject': context['page_header'],
@ -1133,6 +1173,18 @@ class VirtualMachineView(LoginRequiredMixin, View):
}
email = BaseEmail(**email_data)
email.send()
admin_email_body.update(response)
email_to_admin_data = {
'subject': "Deleted VM and Subscription for VM {vm_id} and "
"user: {user}".format(
vm_id=vm.id, user=owner.email
),
'from_email': settings.DCL_SUPPORT_FROM_ADDRESS,
'to': ['info@ungleich.ch'],
'body': "\n".join(
["%s=%s" % (k, v) for (k, v) in admin_email_body.items()]),
}
send_plain_email_task.delay(email_to_admin_data)
return HttpResponse(
json.dumps(response),
content_type="application/json"

View file

@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2017-12-22 01:00+0530\n"
"POT-Creation-Date: 2017-12-23 05:18+0530\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@ -71,14 +71,14 @@ msgstr "Die Chronik von ungleich"
msgid "The first incarnation of ungleich"
msgstr "Die erste Inkarnation von ungleich"
msgid "in Germany"
msgstr "in Deutschland"
msgid "in Germany."
msgstr "in Deutschland."
msgid "ungleich founded"
msgstr "ungleich gegründet"
msgid "in Switzerland"
msgstr "in der Schweiz"
msgid "in Switzerland."
msgstr "in der Schweiz."
msgid "ungleich present at various conferences"
msgstr "ungleich präsent an mehreren Konferenzen"
@ -107,7 +107,7 @@ msgstr "ungleich bietet einen PC-Grundkurs für Flüchtlinge an."
msgid ""
"ungleich starts computer learning club for locals, \"Digitale Building "
"ungleich.\""
"ungleich\"."
msgstr ""
"ungleich gründet den Verein Digitale Bildung ungleich für Ortsansässige."
@ -116,7 +116,7 @@ msgid ""
"startup in canton Zürich."
msgstr ""
"ungleich verkauft das Projekt <a href=\"https://www.alplora.ch/de/"
"\">AlpLora</a> an ein IoT-Startup aus dem Kanton Zürich"
"\">AlpLora</a> an ein IoT-Startup aus dem Kanton Zürich."
msgid ""
"ungleich showcases the most affordable Swiss VM hosting, Data Center Light."
@ -157,8 +157,37 @@ msgstr "Copyright © ungleich GmbH"
msgid "ungleich Home"
msgstr "ungleich Home"
msgid "We Design, Configure &amp; Maintain<br>Your Linux Infrastructure "
msgstr "Wir designen, erstellen und warten<br>Ihre Linux-Infrastruktur"
msgid "Hosting"
msgstr "Hosting"
msgid ""
"Ruby on Rails. Java hosting, Django hosting, we make it everything run "
"smooth and safe."
msgstr ""
"Ruby on Rails. Java hosting, Django hosting, wir garantieren einen "
"reibungslosen Ablauf."
msgid "Configuration as a Service"
msgstr "Konfiguration als Service"
msgid ""
"Ruby on Rails, Django, Java, Webserver, Mailserver, any infrastructure that "
"needs to configured, we provide comprehensive solutions. Amazon, rackspace "
"or bare metal servers, we configure for you."
msgstr ""
"Ruby on Rails, Django, Java, Webserver, Mailserver, jegliche Infrastruktur "
"welche eine Konfiguration braucht, wir offerieren umfassende Lösungen, "
"Amazon, Rackspace oder Bare Metal Servers, wir konfigurieren alles."
msgid "Linux System Engineering"
msgstr "Linux System Engineering"
msgid ""
"Let your developers develop! We take care of your system administration. "
"Gentoo, Archlinux, Debian, Ubuntu, and many more."
msgstr ""
"Lassen sie ihre Entwickler entwickeln! Wir kümmern uns um ihre "
"Systemadministration. Gentoo, Archlinux, Debian, Ubuntu und viele mehr."
msgid "Our Products"
msgstr "Unsere Produkte"
@ -216,38 +245,6 @@ msgstr ""
"Unser erstklassiges Konfigurationsmanagement ist erfrischend einfach und "
"zuverlässig."
msgid "Hosting"
msgstr "Hosting"
msgid ""
"Ruby on Rails. Java hosting, Django hosting, we make it everything run "
"smooth and safe."
msgstr ""
"Ruby on Rails. Java hosting, Django hosting, wir garantieren einen "
"reibungslosen Ablauf"
msgid "Configuration as a Service"
msgstr "Konfiguration als Service"
msgid ""
"Ruby on Rails, Django, Java, Webserver, Mailserver, any infrastructure that "
"needs to configured, we provide comprehensive solutions. Amazon, rackspace "
"or bare metal servers, we configure for you."
msgstr ""
"Ruby on Rails, Django, Java, Webserver, Mailserver, jegliche Infrastruktur "
"welche eine Konfiguration braucht, wir offerieren umfassende Lösungen, "
"Amazon, Rackspace oder Bare Metal Servers, wir konfigurieren alles."
msgid "Linux System Engineering"
msgstr "Linux System Engineering"
msgid ""
"Let your developers develop! We take care of your system administration. "
"Gentoo, Archlinux, Debian, Ubuntu, and many more."
msgstr ""
"Lassen sie ihre Entwickler entwickeln! Wir kümmern uns um ihre "
"Systemadministration. Gentoo, Archlinux, Debian, Ubuntu und viele mehr."
msgid "Why ungleich?*"
msgstr "Warum ungleich?"
@ -363,6 +360,9 @@ msgid "If you have any question, just send us an email."
msgstr ""
"Wenn Sie irgendwelche Fragen haben, schicken Sie uns einfach eine E-Mail."
#~ msgid "We Design, Configure &amp; Maintain<br>Your Linux Infrastructure "
#~ msgstr "Wir designen, erstellen und warten<br>Ihre Linux-Infrastruktur"
#~ msgid "Hosting Products "
#~ msgstr "Hosting Produkte"

View file

@ -30,7 +30,7 @@ class Migration(migrations.Migration):
blank=True, help_text='Text for the button, if a link is provided.', max_length=50, null=True)),
('heading', models.CharField(
blank=True, help_text='An optional title for this slide.', max_length=100, null=True)),
('video', filer.fields.file.FilerFileField(blank=True, help_text='Leavig this blank will make the image as the background.',
('video', filer.fields.file.FilerFileField(blank=True, help_text='Leaving this blank will make the image as the background.',
null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='ungleich_header_item_video', to='filer.File')),
],
options={

View file

@ -372,7 +372,7 @@ section h3.section-subheading {
@media(min-width:768px) {
section {
padding: 125px 0;
padding: 80px 0;
}
section h2.section-heading {
font-size: 40px;
@ -985,4 +985,4 @@ section h3.section-comment {
.carousel-author {
height: 72px;
}
}
}

View file

@ -220,11 +220,11 @@
</div>
<div class="contact-details">
<div class="subtitle">
<h3>ungleich GmbH</h3>
<h3>ungleich glarus ag</h3>
</div>
<div class="description">
<p>glasfaser@ungleich.ch</p>
<p>In der Au 7, Schwanden 8762</p>
<p>Bahnhofstrasse 1, 8783 Linthal</p>
<p>Switzerland</p>
</div>
</div>

View file

@ -17,7 +17,7 @@
</div>
<div class="timeline-body">
<p>{% trans "The first incarnation of ungleich" %}</p>
<p>{% trans "in Germany" %}</p>
<p>{% trans "in Germany." %}</p>
</div>
</div>
</li>
@ -31,7 +31,7 @@
</div>
<div class="timeline-body">
<p>{% trans "ungleich founded" %} </p>
<p>{% trans "in Switzerland" %}</p>
<p>{% trans "in Switzerland." %}</p>
</div>
</div>
</li>
@ -44,7 +44,7 @@
<h4>2014</h4>
</div>
<div class="timeline-body">
<p>{% trans "ungleich present at various conferences" %}: <br><a href="http://www.linuxtag.org/2014/en/program/talk-details/?eventid=1238">Linuxtag</a>, <a href="https://www.usenix.org/conference/ucms14/summit-program/presentation/schottelius">UCMS</a>, Linux Erfa, <a href="https://www.ethz.ch/en.html">ETH Zurich</a><br>
<p>{% trans "ungleich present at various conferences" %}: <br><a href="http://www.linuxtag.org/2014/en/program/talk-details/?eventid=1238">Linuxtag</a>, <a href="https://www.usenix.org/conference/ucms14/summit-program/presentation/schottelius">UCMS</a>, Linux Erfa, <a href="https://www.ethz.ch/en.html">ETH Zurich</a>.<br>
</p>
</div>
</div>
@ -62,7 +62,7 @@
<p>{% trans "and introduces affordable 24X7 support." %}</p>
<p>
{% trans "ungleich launches" %}
<a href="https://digitalglarus.ch">{% trans "Digital Glarus project" %}</a>
<a href="https://digitalglarus.ch">{% trans "Digital Glarus project" %}</a>.
</p>
</div>
</div>
@ -93,19 +93,6 @@
</div>
</div>
</li>
<li class="timeline-inverted">
<div class="timeline-image">
<img class="img-circle img-responsive" src="{% static 'ungleich_page/img/about/2017a.jpg' %}">
</div>
<div class="timeline-panel wow slideInRight">
<div class="timeline-heading">
<h4>2017</h4>
</div>
<div class="timeline-body">
<p>{% trans 'ungleich starts computer learning club for locals, "Digitale Building ungleich."' %}</p>
</div>
</div>
</li>
<li class="timeline-inverted">
<div class="timeline-image">
<img class="img-circle img-responsive" src="{% static 'ungleich_page/img/about/2017b.jpg' %}">
@ -115,6 +102,7 @@
<h4>2017</h4>
</div>
<div class="timeline-body">
<p>{% trans 'ungleich starts computer learning club for locals, "Digitale Building ungleich".' %}</p>
<p>{% blocktrans %}ungleich sells <a href="https://www.alplora.ch/de/">Alplora</a> to an IoT startup in canton Zürich.{% endblocktrans %}</p>
<p>{% trans "ungleich showcases the most affordable Swiss VM hosting, Data Center Light." %}</p>
</div>

View file

@ -18,11 +18,8 @@
</video>
</div>
<div class="container">
<div class="intro-cap">
{% trans "We Design, Configure &amp; Maintain<br>Your Linux Infrastructure " %}
</div>
<p class="intro_lead">Ruby on Rails, Django, Java, Webserver, Mailserver, any infrastructure that needs to configured, we provide comprehensive solutions. Amazon, rackspace or bare metal servers, we configure for you.</p>
<a class="btn btn-trans" href="">Learn More</a>
<div class="intro-cap">{% trans "Hosting" %}</div>
<p class="intro_lead">{% trans "Ruby on Rails. Java hosting, Django hosting, we make it everything run smooth and safe." %}</p>
</div>
</div>
<div class="item">
@ -33,11 +30,9 @@
</video>
</div>
<div class="container">
<div class="intro-cap">
{% trans "We Design, Configure &amp; Maintain<br>Your Linux Infrastructure " %}
</div>
<p class="intro_lead">Ruby on Rails, Django, Nothing else.</p>
<a class="btn btn-trans" href="">Learn More</a>
<div class="intro-cap">{% trans "Configuration as a Service" %}</div>
<p class="intro_lead">{% trans "Ruby on Rails, Django, Java, Webserver, Mailserver, any infrastructure that needs to configured, we provide comprehensive solutions. Amazon, rackspace or bare metal servers, we configure for you." %}</p>
<!-- <a class="btn btn-trans" href="">Learn More</a> -->
</div>
</div>
<div class="item">
@ -47,10 +42,8 @@
</video>
</div>
<div class="container">
<div class="intro-cap">
{% trans "We Design, Configure &amp; Maintain<br>Your Linux Infrastructure " %}
</div>
<a class="btn btn-trans" href="">Learn More</a>
<div class="intro-cap">{% trans "Linux System Engineering" %}</div>
<p class="intro_lead">{% trans "Let your developers develop! We take care of your system administration. Gentoo, Archlinux, Debian, Ubuntu, and many more." %}</p>
</div>
</div>
</div>

View file

@ -232,6 +232,17 @@ class StripeUtils(object):
)
return subscription_result
@handleStripeError
def unsubscribe_customer(self, subscription_id):
"""
Cancels a given subscription
:param subscription_id: The Stripe subscription id string
:return:
"""
sub = stripe.Subscription.retrieve(subscription_id)
return sub.delete()
@handleStripeError
def make_payment(self, customer, amount, token):
charge = self.stripe.Charge.create(