merge master

This commit is contained in:
Arvind Tiwari 2017-09-28 18:37:33 +05:30
commit ba366eed77
27 changed files with 916 additions and 678 deletions

View file

@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2017-09-27 04:21+0530\n"
"POT-Creation-Date: 2017-09-28 18:36+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"
@ -198,6 +198,7 @@ msgstr "Deine Neue VM %(vm_name)s"
msgid "You have ordered a new virtual machine!"
msgstr "Du hast eine neue virtuelle Maschine bestellt!"
#, python-format
msgid "Your order of [ <strong>%(vm_name)s</strong> ] has been charged."
msgstr "Deine Bestellung von [ <strong>%(vm_name)s</strong> ] wurde erhoben."
@ -237,13 +238,13 @@ msgstr "Dankeschön!"
msgid "Virtual Machine Cancellation"
msgstr "VM Kündigung"
#, python-format
msgid ""
"You are receiving this email because your virutal machine [ <strong>"
"%(vm_name)s</strong> ] has been cancelled."
msgstr ""
"Du erhälst diese E-Mail, da deine virtuelle Maschine [ <strong>"
"%(vm_name)s</strong> ] gekündigt "
"wurde."
"Du erhälst diese E-Mail, da deine virtuelle Maschine [ <strong>%(vm_name)s</"
"strong> ] gekündigt wurde."
msgid "You can always order a new VM by clicking the button below."
msgstr ""
@ -313,6 +314,9 @@ msgstr "Rechnung Datum"
msgid "Status"
msgstr ""
msgid "Terminated"
msgstr "Beendet"
msgid "Approved"
msgstr "Akzeptiert"
@ -334,6 +338,9 @@ msgstr "Bestellungsübersicht"
msgid "Product"
msgstr "Produkt"
msgid "Period"
msgstr ""
msgid "Cores"
msgstr "Prozessorkerne"
@ -595,8 +602,13 @@ msgstr "Virtuelle Maschinen"
msgid "To create a new virtual machine, click \"Create VM\""
msgstr "Um eine neue VM zu erzeugen, klicke \"Neue VM erzeugen\""
#, python-format
msgid ""
"To access your VM, add your SSH key <a href=\"%(create_ssh_url)s\">here</a>"
msgstr ""
msgid "login"
msgstr "Einloggen"
msgstr "anmelden"
msgid ""
"Thank you for signing up. We have sent an email to you. Please follow the "
@ -673,12 +685,17 @@ msgid ""
"contact Data Center Light Support."
msgstr "Kontaktiere den Data Center Light Support."
msgid "Terminated"
msgstr "Beendet"
msgid "Error terminating VM"
msgstr "Fehler beenden VM"
#, fuzzy, python-format
#| msgid "Virtual Machine Cancellation"
msgid "Virtual Machine %(vm_name)s Cancelled"
msgstr "VM Kündigung"
#~ msgid "My VM page"
#~ msgstr "Meine VM page"
#~ msgid ""
#~ "\n"
#~ "You're receiving this email because you requested a password reset for "

View file

@ -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)),
],
),
]

View file

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

View file

@ -857,6 +857,8 @@ a.list-group-item-danger:focus,
background: rgba(235, 204, 209, 0.2);
}
.has-error .form-control,
.has-error .form-control:focus,
.has-error .form-control:active,
.has-error .input-group-addon {
color: #eb4d5c;
border-color: #eb4d5c;
@ -871,6 +873,13 @@ a.list-group-item-danger.active:focus {
background-color: #eb4d5c;
}
/* bootstrap input box-shadom disable */
.has-error .form-control:focus,
.has-error .form-control:active,
.has-success .form-control:focus,
.has-success .form-control:active {
box-shadow: inset 0 0 1px rgba(0,0,0,0.25);
}
.checkmark {
display: inline-block;
}

View file

@ -22,7 +22,100 @@
}
.summary-box .content {
padding-top: 15px;
}
/* landing page payment new style */
.last-p {
margin-bottom: 0;
}
.dcl-payment-section {
max-width: 391px;
margin: 0 auto 30px;
padding: 0 10px 30px;
border-bottom: 1px solid #edebeb;
height: 100%;
}
.dcl-payment-section hr{
margin-top: 15px;
margin-bottom: 15px;
}
.dcl-payment-section .top-hr {
margin-left: -10px;
}
.dcl-payment-section h3 {
font-weight: 600;
}
.dcl-payment-section p {
padding: 0 5px;
font-weight: 400;
}
.dcl-payment-section .card-warning-content {
padding: 8px 10px;
font-weight: 300;
}
.dcl-payment-order strong{
font-size: 17px;
}
.dcl-payment-order p {
font-weight: 300;
}
.dcl-payment-section .form-group {
margin-bottom: 10px;
}
.dcl-payment-section .form-control {
box-shadow: none;
padding: 6px 12px;
height: 32px;
}
.dcl-payment-user {
height: 100%;
display: flex;
flex-direction: column;
justify-content: center;
}
.dcl-payment-user h4 {
font-weight: 600;
padding-left: 5px;
font-size: 17px;
}
@media (min-width: 768px) {
.dcl-payment-grid {
display: flex;
align-items: stretch;
flex-wrap: wrap;
}
.dcl-payment-box {
width: 50%;
position: relative;
padding: 0 30px;
}
.dcl-payment-box:nth-child(2) {
order: 1;
}
.dcl-payment-box:nth-child(4) {
order: 2;
}
.dcl-payment-section {
padding: 15px 10px;
margin-bottom: 0;
border-bottom-width: 5px;
}
.dcl-payment-box:nth-child(2n) .dcl-payment-section {
border-bottom: none;
}
.dcl-payment-box:nth-child(1):after,
.dcl-payment-box:nth-child(2):after {
content: ' ';
display: block;
background: #eee;
width: 1px;
position: absolute;
right: 0;
z-index: 2;
top: 20px;
bottom: 20px;
}
}

View file

@ -47,20 +47,5 @@
window.location.href = '{{next_url}}';
</script>
{% endif %}
<script type="text/javascript">
window.onload = function () {
{% for user_key in keys %}
var locale_date = moment.utc(document.getElementById("ssh-created_at-{{user_key.id}}").textContent,'YYYY-MM-DD HH:mm').toDate();
locale_date = moment(locale_date).format("YYYY-MM-DD h:mm:ss a");
document.getElementById('ssh-created_at-{{user_key.id}}').innerHTML = locale_date;
{% endfor %}
};
</script>
{%endblock%}

View file

@ -42,7 +42,9 @@
<p>
<strong>{% trans "Status" %}: </strong>
<strong>
{% if order.status == 'Approved' %}
{% if vm.terminated_at %}
<span class="vm-color-failed">{% trans "Terminated" %}</span>
{% elif order.status == 'Approved' %}
<span class="vm-color-online">{% trans "Approved" %}</span>
{% else %}
<span class="vm-status-failed">{% trans "Declined" %}</span>
@ -96,14 +98,14 @@
</p>
<div class="row">
<div class="col-sm-6">
{% comment %}
{% if vm.created_at %}
<p>
<span>{% trans "Period" %}: </span>
<span>{{ vm.created_at|date:'Y/m/d' }} - {% if vm.terminated_at %}{{ vm.terminated_at|date:'Y/m/d' }}{% else %}{% now 'Y/m/d' %}{% endif %}</span>
</p>
{% endif %}
<p>
<span>{% trans "Period" %}</span>
<span class="pull-right">{{}}</span>
</p>
{% endcomment %}
<p>
<span>{% trans "Cores" %}</span>
<span>{% trans "Cores" %}: </span>
{% if vm.cores %}
<span class="pull-right">{{vm.cores|floatformat}}</span>
{% else %}
@ -111,11 +113,11 @@
{% endif %}
</p>
<p>
<span>{% trans "Memory" %}</span>
<span>{% trans "Memory" %}: </span>
<span class="pull-right">{{vm.memory}} GB</span>
</p>
<p>
<span>{% trans "Disk space" %}</span>
<span>{% trans "Disk space" %}: </span>
<span class="pull-right">{{vm.disk_size}} GB</span>
</p>
<p>
@ -171,7 +173,7 @@
{% trans "Hold tight, we are processing your request" %}
</div>
<div class="modal-footer">
<a id="createvm-modal-done-btn" class="btn btn-danger btn-ok btn-wide hide" href="{% url 'hosting:virtual_machines' %}">{% trans "OK" %}</a>
<a id="createvm-modal-done-btn" class="btn btn-success btn-ok btn-wide hide" href="{% url 'hosting:virtual_machines' %}">{% trans "OK" %}</a>
<button id="createvm-modal-close-btn" type="button" class="btn btn-danger btn-ok btn-wide hide" data-dismiss="modal" aria-label="create-vm-close">{% trans "Close" %}</button>
</div>
</div>
@ -199,4 +201,4 @@
<script src="https://cdnjs.cloudflare.com/ajax/libs/html2canvas/0.4.1/html2canvas.min.js"></script>
<script src="{% static 'hosting/js/html2pdf.js' %}"></script>
<script src="{% static 'hosting/js/order.js' %}"></script>
{% endblock js_extra %}
{% endblock js_extra %}

View file

@ -101,21 +101,5 @@
window.location.href = '{{next_url}}';
</script>
{% endif %}
<script type="text/javascript">
window.onload = function () {
{% for user_key in keys %}
var locale_date = moment.utc(document.getElementById("ssh-created_at-{{user_key.id}}").textContent,'YYYY-MM-DD HH:mm').toDate();
locale_date = moment(locale_date).format("YYYY-MM-DD h:mm:ss a");
document.getElementById('ssh-created_at-{{user_key.id}}').innerHTML = locale_date;
{% endfor %}
};
</script>
{%endblock%}

View file

@ -13,7 +13,12 @@
{% endif %}
{% if not error %}
<div class="dashboard-subtitle">
<p>{% trans 'To create a new virtual machine, click "Create VM"' %}</p>
<p>{% trans 'To create a new virtual machine, click "Create VM"' %}
{% if show_create_ssh_key_msg %}
{% url 'hosting:create_ssh_key' as create_ssh_url %}
<br/>{% blocktrans %}To access your VM, add your SSH key <a href="{{create_ssh_url}}">here</a>{% endblocktrans %}
{% endif %}
</p>
<div class="text-right">
<a class="btn btn-vm" href="{% url 'hosting:create_virtual_machine' %}"><span class="css-plus"></span> <span>{% trans "CREATE VM" %}</span></a>
</div>

View file

@ -1,6 +1,7 @@
import json
import logging
import uuid
from datetime import datetime
from time import sleep
from django import forms
@ -37,6 +38,7 @@ from utils.forms import (
BillingAddressForm, PasswordResetRequestForm, UserBillingAddressForm,
ResendActivationEmailForm
)
from utils.hosting_utils import get_vm_price
from utils.mailer import BaseEmail
from utils.stripe_utils import StripeUtils
from utils.views import (
@ -46,10 +48,11 @@ 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
logger = logging.getLogger(__name__)
CONNECTION_ERROR = "Your VMs cannot be displayed at the moment due to a \
@ -627,13 +630,6 @@ class PaymentVMView(LoginRequiredMixin, FormView):
return context
def get(self, request, *args, **kwargs):
if not UserHostingKey.objects.filter(user=self.request.user).exists():
messages.success(
request,
'In order to create a VM, you create/upload your SSH KEY first.'
)
return HttpResponseRedirect(reverse('hosting:ssh_keys'))
if 'next' in request.session:
del request.session['next']
@ -706,25 +702,30 @@ 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__
context['vm']['name'] = '{}-{}'.format(context['vm']['configuration'], context['vm']['vm_id'])
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
@ -784,12 +785,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,
@ -834,9 +834,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),
@ -894,6 +895,10 @@ class VirtualMachinesPlanListView(LoginRequiredMixin, ListView):
context = {'error': 'connection'}
else:
context = super(ListView, self).get_context_data(**kwargs)
if UserHostingKey.objects.filter(user=self.request.user).exists():
context['show_create_ssh_key_msg'] = False
else:
context['show_create_ssh_key_msg'] = True
return context
@ -914,15 +919,6 @@ class CreateVirtualMachinesView(LoginRequiredMixin, View):
raise ValidationError(_('Invalid storage size'))
def get(self, request, *args, **kwargs):
if not UserHostingKey.objects.filter(user=self.request.user).exists():
messages.success(
request,
_(
'In order to create a VM, you need to '
'create/upload your SSH KEY first.'
)
)
return HttpResponseRedirect(reverse('hosting:ssh_keys'))
context = {'templates': VMTemplate.objects.all()}
return render(request, self.template_name, context)
@ -933,7 +929,6 @@ class CreateVirtualMachinesView(LoginRequiredMixin, View):
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()
@ -965,7 +960,8 @@ class CreateVirtualMachinesView(LoginRequiredMixin, View):
extra_tags='storage')
return HttpResponseRedirect(
reverse('datacenterlight:index') + "#order_form")
price = get_vm_price(cpu=cores, memory=memory,
disk_size=storage)
specs = {
'cpu': cores,
'memory': memory,
@ -1072,6 +1068,10 @@ 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