Added Flake8 lib and fixed PEP8 violations

This commit is contained in:
Siarhei Puhach 2017-06-29 17:34:40 +03:00
parent 0cbd3aa666
commit edcfd3e9f4
65 changed files with 340 additions and 387 deletions

View File

@ -4,8 +4,10 @@ python:
- "3.6"
env:
# Set a dummy secret key
# Set a dummy secret key
- DJANGO_SECRET_KEY=0
# install dependencies
install: "pip install -r requirements.txt"
script: python manage.py test
script:
- flake8
- python manage.py test

View File

@ -1,3 +1,3 @@
from django.contrib import admin
# from django.contrib import admin
# Register your models here.

View File

@ -1,3 +1,3 @@
from django.db import models
# from django.db import models
# Create your models here.

View File

@ -1,3 +1,3 @@
from django.test import TestCase
# from django.test import TestCase
# Create your tests here.

View File

@ -7,6 +7,6 @@ urlpatterns = [
url(r'^/?$', IndexView.as_view(), name='index'),
url(r'/login/', LoginView.as_view(), name='login'),
url(r'/contact', ContactView.as_view(), name='contact'),
# url(r'^/beta-program/?$', BetaProgramView.as_view(), name='beta'),
# url(r'^/landing/?$', LandingProgramView.as_view(), name='landing'),
# url(r'^/beta-program/?$', BetaProgramView.as_view(), name='beta'),
# url(r'^/landing/?$', LandingProgramView.as_view(), name='landing'),
]

View File

@ -4,11 +4,11 @@ from django.utils.translation import get_language, get_language_info
from django.utils.translation import ugettext_lazy as _
from django.views.generic.edit import FormView
from django.contrib import messages
from django.core.urlresolvers import reverse_lazy, reverse
from django.shortcuts import render
from utils.forms import ContactUsForm
class IndexView(TemplateView):
template_name = "alplora/index.html"
@ -18,6 +18,7 @@ class IndexView(TemplateView):
context.update(languages)
return context
class ContactView(FormView):
template_name = 'alplora/contact.html'
form_class = ContactUsForm
@ -33,7 +34,8 @@ class ContactView(FormView):
form.save()
form.send_email(email_to='info@alplora.ch')
messages.add_message(self.request, messages.SUCCESS, self.success_message)
return render(self.request, 'alplora/contact_success.html', {})
return render(self.request, 'alplora/contact_success.html', {})
class LoginView(TemplateView):
template_name = "alplora/login.html"

View File

@ -1,6 +1,6 @@
from django import forms
from .models import BetaAccess, BetaAccessVM
from .models import BetaAccess
class BetaAccessForm(forms.ModelForm):

View File

@ -5,20 +5,18 @@ from django.utils.translation import activate, get_language
register = template.Library()
@register.simple_tag(takes_context=True)
def change_lang(context, lang=None, *args, **kwargs):
path = context['request'].path
url_parts = resolve( path )
url_parts = resolve(path)
url = path
cur_language = get_language()
try:
activate(lang)
url = reverse( url_parts.view_name, kwargs=url_parts.kwargs )
url = reverse(url_parts.view_name, kwargs=url_parts.kwargs)
finally:
activate(cur_language)
return "%s" % url
return "%s" % url

View File

@ -1,3 +1,3 @@
from django.test import TestCase
# from django.test import TestCase
# Create your tests here.

View File

@ -3,7 +3,7 @@ from django.http import HttpResponseRedirect
from .forms import BetaAccessForm
from .models import BetaAccess, BetaAccessVMType, BetaAccessVM
from django.contrib import messages
from django.core.urlresolvers import reverse_lazy, reverse
from django.core.urlresolvers import reverse
from django.core.mail import EmailMessage
from utils.mailer import BaseEmail
from django.shortcuts import render
@ -14,12 +14,15 @@ from django.core.exceptions import ValidationError
from opennebula_api.models import OpenNebulaManager
from opennebula_api.serializers import VirtualMachineTemplateSerializer
class LandingProgramView(TemplateView):
template_name = "datacenterlight/landing.html"
class SuccessView(TemplateView):
template_name = "datacenterlight/success.html"
class PricingView(TemplateView):
template_name = "datacenterlight/pricing.html"
@ -32,17 +35,16 @@ class PricingView(TemplateView):
'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'
)
messages.error(request,
'We have a temporary problem to connect to our backend. \
Please try again in a few minutes'
)
context = {
'error' : 'connection'
'error': 'connection'
}
return render(request, self.template_name, context)
def post(self, request):
cores = request.POST.get('cpu')
@ -61,7 +63,7 @@ class PricingView(TemplateView):
request.session['next'] = reverse('hosting:payment')
request.session['specs'] = {
'cpu':cores,
'cpu': cores,
'memory': memory,
'disk_size': storage,
'price': price,
@ -111,6 +113,7 @@ class BetaAccessView(FormView):
messages.add_message(self.request, messages.SUCCESS, self.success_message)
return render(self.request, 'datacenterlight/beta_success.html', {})
class BetaProgramView(CreateView):
template_name = "datacenterlight/beta.html"
model = BetaAccessVM
@ -169,7 +172,7 @@ class IndexView(CreateView):
form_class = BetaAccessForm
success_url = "/datacenterlight#requestform"
success_message = "Thank you, we will contact you as soon as possible"
def get(self, request, *args, **kwargs):
try:
manager = OpenNebulaManager()
@ -178,12 +181,12 @@ class IndexView(CreateView):
'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'
)
messages.error(request,
'We have a temporary problem to connect to our backend. \
Please try again in a few minutes'
)
context = {
'error' : 'connection'
'error': 'connection'
}
return render(request, self.template_name, context)
@ -196,7 +199,7 @@ class IndexView(CreateView):
manager = OpenNebulaManager()
template = manager.get_template(template_id)
template_data = VirtualMachineTemplateSerializer(template).data
name = request.POST.get('name')
email = request.POST.get('email')
name_field = forms.CharField()
@ -207,7 +210,7 @@ class IndexView(CreateView):
messages.add_message(self.request, messages.ERROR, '%(value) is not a proper name.'.format(name))
return HttpResponseRedirect(reverse('datacenterlight:index'))
try:
try:
email = email_field.clean(email)
except ValidationError as err:
messages.add_message(self.request, messages.ERROR, '%(value) is not a proper email.'.format(email))
@ -230,7 +233,7 @@ class IndexView(CreateView):
'reply_to': [context['email']],
}
email = EmailMessage(**email_data)
email.send()
email.send()
return HttpResponseRedirect(reverse('datacenterlight:order_success'))

View File

@ -1,5 +1,5 @@
from django.contrib import admin
from .models import Supporter, DGGallery, DGPicture, Booking, BookingPrice,\
from .models import DGGallery, DGPicture, Booking, BookingPrice,\
MembershipOrder, Membership, MembershipType, BookingOrder, BookingCancellation
from django.core.urlresolvers import reverse

View File

@ -1,9 +1,9 @@
from cms.plugin_base import CMSPluginBase
from cms.plugin_pool import plugin_pool
from cms.wizards import wizard_base
from .models import DGGalleryPlugin, DGSupportersPlugin, Supporter
from django.utils.translation import ugettext as _
#
class CMSGalleryPlugin(CMSPluginBase):
model = DGGalleryPlugin
name = _("Digital Glarus Gallery")
@ -11,12 +11,13 @@ class CMSGalleryPlugin(CMSPluginBase):
def render(self, context, instance, placeholder):
context.update({
'gallery':instance.dgGallery,
'object':instance,
'placeholder':placeholder
'gallery': instance.dgGallery,
'object': instance,
'placeholder': placeholder
})
return context
class CMSSupportersPlugin(CMSPluginBase):
name = _("Digital Glarus Supporters")
model = DGSupportersPlugin
@ -26,11 +27,10 @@ class CMSSupportersPlugin(CMSPluginBase):
context.update({
'supporters': Supporter.objects.all().order_by('name'),
'object': instance,
'placeholder':placeholder
'placeholder': placeholder
})
return context
#
#
#
plugin_pool.register_plugin(CMSGalleryPlugin)
plugin_pool.register_plugin(CMSSupportersPlugin)

View File

@ -1,7 +1,6 @@
from django import forms
from django.db.models import Q
from django.utils.translation import ugettext_lazy as _
from datetime import datetime
from utils.models import BillingAddress
@ -92,7 +91,7 @@ class CancelBookingForm(forms.ModelForm):
class BookingDateForm(forms.Form):
start_date = forms.DateField(required=False,
widget=forms.TextInput(attrs={'id': 'booking-date-1',
'value': 'Select your date'}))
'value': 'Select your date'}))
end_date = forms.DateField(required=False,
widget=forms.TextInput(attrs={'id': 'booking-date-2'}))

View File

@ -3,6 +3,7 @@ from django.conf import settings
import stripe
stripe.api_key = settings.STRIPE_API_PRIVATE_KEY
class Command(BaseCommand):
help = "Record payment plans for Digital Glarus on stripe"
@ -10,5 +11,3 @@ class Command(BaseCommand):
print("Available plans:")
for plan in stripe.Plan.all():
print(plan)

View File

@ -11,11 +11,11 @@ PAYMENT_PLANS = [
'id': "spontaneus"
}),
('committed', {
'amount':36000,
'interval':'year',
'name':'The Committed',
'currency':'chf',
'id':'committed'
'amount': 36000,
'interval': 'year',
'name': 'The Committed',
'currency': 'chf',
'id': 'committed'
})
]
@ -26,8 +26,6 @@ class Command(BaseCommand):
def handle(self, *args, **options):
for payment_plan, data in PAYMENT_PLANS:
try:
res = stripe.Plan.create(**data)
stripe.Plan.create(**data)
except stripe.InvalidRequestError as e:
print(e)

View File

@ -105,7 +105,7 @@ class Membership(models.Model):
has_order_current_month = Q(membershiporder__customer__user=user,
membershiporder__created_at__month=datetime.today().month)
# has_order_past_month = Q(membershiporder__customer__user=user,
# membershiporder__created_at__month=past_month)
# membershiporder__created_at__month=past_month)
active_membership = Q(active=True)
# return cls.objects.filter(has_order_past_month | has_order_current_month).\
return cls.objects.filter(has_order_current_month).\
@ -316,17 +316,20 @@ class DGGallery(models.Model):
class Meta:
verbose_name_plural = 'dgGallery'
#
class DGPicture(models.Model):
gallery = models.ForeignKey(DGGallery)
image = FilerImageField(related_name='dg_gallery')
image = FilerImageField(related_name='dg_gallery')
description = models.CharField(max_length=60)
def __str__(self):
return "%s" % (self.image.name)
class DGGalleryPlugin(CMSPlugin):
dgGallery = models.ForeignKey(DGGallery)
class DGSupportersPlugin(CMSPlugin):
pass

View File

@ -1,4 +1,3 @@
import json
from model_mommy import mommy
from unittest import mock
@ -150,7 +149,7 @@ class MembershipPaymentViewTest(BaseTestCase):
# self.assertTrue(HostingOrder.objects.filter(customer=stripe_customer).exists())
# hosting_order = HostingOrder.objects.filter(customer=stripe_customer)[0]
# vm_plan = {
# 'cores': hosting_order.vm_plan.cores,
# 'cores': hosting_order.vm_plan.cores,
# 'memory': hosting_order.vm_plan.memory,
# 'disk_size': hosting_order.vm_plan.disk_size,
# 'price': hosting_order.vm_plan.price,

View File

@ -720,7 +720,9 @@ class ContactView(FormView):
messages.add_message(self.request, messages.SUCCESS, self.success_message)
return super(ContactView, self).form_valid(form)
############## OLD VIEWS
# OLD VIEWS
def blog(request):
tags = ["digitalglarus"]
@ -751,6 +753,3 @@ def supporters(request):
'supporters': Supporter.objects.order_by('name')
}
return render(request, 'supporters.html', context)

View File

@ -9,12 +9,15 @@ from django.utils.translation import ugettext_lazy as _
# dotenv
import dotenv
gettext = lambda s: s
def gettext(s):
return s
def env(env_name):
return os.environ.get(env_name)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
PROJECT_DIR = os.path.abspath(
@ -83,7 +86,7 @@ INSTALLED_APPS = (
'django_select2',
'meta',
'meta_mixin',
# 'admin_enhancer',
# 'admin_enhancer',
'djangocms_blog',
'bootstrap3',
'compressor',
@ -433,5 +436,5 @@ MANAGERS = ADMINS
ALLOWED_HOSTS = [
".ungleich.ch",
"digital.glarus.ungleich.ch" ,
"digital.glarus.ungleich.ch",
]

View File

@ -1 +1 @@
from .base import *
# from .base import *

View File

@ -11,7 +11,9 @@ from django.utils.translation import ugettext_lazy as _
# dotenv
import dotenv
gettext = lambda s: s
def gettext(s):
return s
def env(env_name):
@ -186,7 +188,11 @@ CMS_TEMPLATES = (
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': 'app'
'NAME': 'app',
'HOST': 'localhost',
'USER': 'ubuntu',
'PASSWORD': 'Qwerty123',
}
}
@ -462,17 +468,20 @@ STRIPE_DESCRIPTION_ON_PAYMENT = "Payment for ungleich GmbH services"
# EMAIL MESSAGES
REGISTRATION_MESSAGE = {'subject': "Validation mail",
'message': 'Thank You for registering for account on Digital Glarus.\nPlease verify Your account under following link http://{host}/en-us/digitalglarus/login/validate/{slug}',
'message': 'Thank You for registering for account on Digital Glarus.\n'
'Please verify Your account under following link '
'http://{host}/en-us/digitalglarus/login/validate/{slug}',
}
STRIPE_API_PRIVATE_KEY = env('STRIPE_API_PRIVATE_KEY')
STRIPE_API_PUBLIC_KEY = env('STRIPE_API_PUBLIC_KEY')
DEBUG = True
if DEBUG:
from .local import *
else:
from .prod import *
# not used
# if DEBUG:
# from .local import *
# # else:
# # from .prod import *
ANONYMOUS_USER_NAME = 'anonymous@ungleich.ch'

View File

@ -1,5 +1,7 @@
from .base import *
REGISTRATION_MESSAGE['message'] = REGISTRATION_MESSAGE['message'].format(host='dynamicweb-development.ungleich.ch',slug='{slug}')
from .base import * # flake8: noqa
REGISTRATION_MESSAGE['message'] = REGISTRATION_MESSAGE['message'].format(host='dynamicweb-development.ungleich.ch',
slug='{slug}')
ALLOWED_HOSTS = [
"*"
]
@ -13,9 +15,9 @@ CACHES = {
}
}
MIDDLEWARE_CLASSES+=("debug_toolbar.middleware.DebugToolbarMiddleware",)
MIDDLEWARE_CLASSES += ("debug_toolbar.middleware.DebugToolbarMiddleware",)
INSTALLED_APPS+=(
INSTALLED_APPS += (
'django_extensions',
'debug_toolbar'
)

View File

@ -1,15 +1,16 @@
from .base import *
from .base import * # flake8: noqa
# List of people that get admin messages
ADMINS = ( (x, x + "@ungleich.ch") for x in ["web-team"] )
ADMINS = ((x, x + "@ungleich.ch") for x in ["web-team"])
DEBUG=False
DEBUG = False
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
#MANAGERS = ADMINS
# MANAGERS = ADMINS
REGISTRATION_MESSAGE['message'] = REGISTRATION_MESSAGE['message'].format(host='digitalglarus.ungleich.ch',slug='{slug}')
REGISTRATION_MESSAGE['message'] = REGISTRATION_MESSAGE['message'].format(host='digitalglarus.ungleich.ch',
slug='{slug}') # flake8: noqa
ALLOWED_HOSTS = [
".ungleich.ch",

View File

@ -12,30 +12,31 @@ from django.views.generic import RedirectView
from django.core.urlresolvers import reverse_lazy
import debug_toolbar
urlpatterns = [ url(r'^index.html$', LandingView.as_view()),
url(r'^hosting/', include('hosting.urls', namespace="hosting")),
url(r'^open_api/', include('opennebula_api.urls',
namespace='opennebula_api')),
url(r'^railshosting/', RailsHostingView.as_view(), name="rails.hosting"),
url(r'^nodehosting/', NodeJSHostingView.as_view(), name="node.hosting"),
url(r'^djangohosting/', DjangoHostingView.as_view(), name="django.hosting"),
url(r'^nosystemd/', include('nosystemd.urls', namespace="nosystemd")),
url(r'^taggit_autosuggest/', include('taggit_autosuggest.urls')),
url(r'^jsi18n/(?P<packages>\S+?)/$',
'django.views.i18n.javascript_catalog'),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
urlpatterns = [url(r'^index.html$', LandingView.as_view()),
url(r'^hosting/', include('hosting.urls', namespace="hosting")),
url(r'^open_api/', include('opennebula_api.urls',
namespace='opennebula_api')),
url(r'^railshosting/', RailsHostingView.as_view(), name="rails.hosting"),
url(r'^nodehosting/', NodeJSHostingView.as_view(), name="node.hosting"),
url(r'^djangohosting/', DjangoHostingView.as_view(), name="django.hosting"),
url(r'^nosystemd/', include('nosystemd.urls', namespace="nosystemd")),
url(r'^taggit_autosuggest/', include('taggit_autosuggest.urls')),
url(r'^jsi18n/(?P<packages>\S+?)/$',
'django.views.i18n.javascript_catalog'),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
# note the django CMS URLs included via i18n_patterns
urlpatterns += i18n_patterns('',
url(r'^/?$', LandingView.as_view()),
url(r'^admin/', include(admin.site.urls)),
url(r'^datacenterlight', include('datacenterlight.urls', namespace="datacenterlight")),
url(r'^hosting/', RedirectView.as_view(url=reverse_lazy('hosting:login')), name='redirect_hosting_login'),
url(r'^hosting/', RedirectView.as_view(
url=reverse_lazy('hosting:login')), name='redirect_hosting_login'),
url(r'^alplora', include('alplora.urls', namespace="alplora")),
url(r'^membership/', include(membership_urls)),
url(r'^digitalglarus/', include('digitalglarus.urls',
namespace="digitalglarus")),
#url(r'^blog/', include('ungleich.urls', namespace='ungleich')),
# url(r'^blog/', include('ungleich.urls', namespace='ungleich')),
url(r'^',
include('ungleich_page.urls', namespace='ungleich_page'),
name='ungleich_page'),
@ -50,4 +51,4 @@ if settings.DEBUG:
'document_root': settings.MEDIA_ROOT,
}),
)
urlpatterns += patterns('',url(r'^__debug__/', include(debug_toolbar.urls)))
urlpatterns += patterns('', url(r'^__debug__/', include(debug_toolbar.urls)))

View File

@ -7,13 +7,13 @@ For more information on this file, see
https://docs.djangoproject.com/en/1.8/howto/deployment/wsgi/
"""
import os,sys
#sys.path.append(os.path.dirname(__file__))
import os
import sys
from django.core.wsgi import get_wsgi_application
# sys.path.append(os.path.dirname(__file__))
sys.path.append('/home/app/pyvenv/lib/python3.4/site-packages/')
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "dynamicweb.settings.prod")
from django.core.wsgi import get_wsgi_application
application = get_wsgi_application()

View File

@ -1,8 +1,4 @@
from django.contrib import admin
from django.utils.html import format_html
from django.core.urlresolvers import reverse
from utils.mailer import BaseEmail
from .models import HostingOrder, HostingBill, HostingPlan

View File

@ -1,14 +1,11 @@
import random
import string
from django import forms
from membership.models import CustomUser
from django.contrib.auth import authenticate
from django.utils.translation import ugettext_lazy as _
from utils.stripe_utils import StripeUtils
from .models import UserHostingKey
from .models import HostingOrder, UserHostingKey
class HostingUserLoginForm(forms.Form):
@ -62,9 +59,9 @@ class HostingUserSignupForm(forms.ModelForm):
class UserHostingKeyForm(forms.ModelForm):
private_key = forms.CharField(widget=forms.HiddenInput(), required=False)
public_key = forms.CharField(widget=forms.Textarea(), required=False,
help_text=_('Paste here your public key'))
help_text=_('Paste here your public key'))
user = forms.models.ModelChoiceField(queryset=CustomUser.objects.all(),
required=False, widget=forms.HiddenInput())
required=False, widget=forms.HiddenInput())
name = forms.CharField(required=True)
def __init__(self, *args, **kwargs):

View File

@ -1,4 +1,4 @@
from django.core.management.base import BaseCommand, CommandError
from django.core.management.base import BaseCommand
from hosting.models import VirtualMachineType
@ -55,15 +55,15 @@ class Command(BaseCommand):
},
]
hetzner = {
'base_price': 10,
'core_price': 5,
'memory_price': 2,
'disk_size_price': 0.6,
'description': 'VM auf einzelner HW, Raid1, kein HA',
'location': 'DE'
}
# not used
# hetzner = {
# 'base_price': 10,
# 'core_price': 5,
# 'memory_price': 2,
# 'disk_size_price': 0.6,
# 'description': 'VM auf einzelner HW, Raid1, kein HA',
# 'location': 'DE'
# }
# return {
# # 'hetzner_nug': {

View File

@ -1,22 +1,16 @@
import os
import socket
import logging
import oca
from django.db import models
from django.utils.translation import ugettext_lazy as _
from django.utils.functional import cached_property
from django.conf import settings
from Crypto.PublicKey import RSA
from stored_messages.settings import stored_messages_settings
from membership.models import StripeCustomer, CustomUser
from utils.models import BillingAddress
from utils.mixins import AssignPermissionsMixin
from .managers import VMPlansManager
logger = logging.getLogger(__name__)
@ -29,7 +23,7 @@ class HostingPlan(models.Model):
def serialize(self):
return {
'id': self.id,
'cpu':self.cpu_cores,
'cpu': self.cpu_cores,
'memory': self.memory,
'disk_size': self.disk_size,
'price': self.price(),
@ -46,6 +40,7 @@ class HostingPlan(models.Model):
price += self.memory * 2
return price
class HostingOrder(AssignPermissionsMixin, models.Model):
ORDER_APPROVED_STATUS = 'Approved'
@ -128,6 +123,7 @@ class UserHostingKey(models.Model):
# self.save(update_fields=['public_key'])
return private_key, public_key
class HostingBill(AssignPermissionsMixin, models.Model):
customer = models.ForeignKey(StripeCustomer)
billing_address = models.ForeignKey(BillingAddress)
@ -147,4 +143,3 @@ class HostingBill(AssignPermissionsMixin, models.Model):
def create(cls, customer=None, billing_address=None):
instance = cls.objects.create(customer=customer, billing_address=billing_address)
return instance

View File

@ -1,6 +1,6 @@
{% extends "hosting/base_short.html" %}
{% load staticfiles bootstrap3 i18n %}
{% block content %}
{% block content %}
<!-- Credit card form -->
<div>
<div class="payment-container">
@ -29,7 +29,7 @@
</div>
</div>
</form>
</div>
<div class="col-xs-12 col-md-4 billing">
<h3><b>{%trans "Billing Address"%}</b></h3>
@ -56,7 +56,7 @@
<h5 class="membership-lead">Last 4: *****{{credit_card_data.last4}}</h5>
<h5 class="membership-lead">Type: {{credit_card_data.cc_brand}}</h5>
<input type="hidden" name="credit_card_needed" value="false"/>
</form>
</form>
<div class="col-xs-6">
<button id="payment_button_with_creditcard" class="btn btn-success btn-sm btn-block" type="submit">
{% trans "Submit Payment" %}
@ -86,7 +86,7 @@
placeholder="{%trans "Valid Card Number"%}" required autofocus data-stripe="number" />
<span class="input-group-addon"><i class="fa fa-credit-card"></i></span>
</div>
</div>
</div>
</div>
</div>
<div class="row">
@ -128,7 +128,7 @@
</div>
{% endif %}
</form>
{% endif %}
@ -143,7 +143,7 @@
<!-- stripe key data -->
{% if stripe_key %}
{% get_current_language as LANGUAGE_CODE %}
<script type="text/javascript">
<script type="text/javascript">
(function () {
@ -154,7 +154,7 @@
{%endif%}
{% if credit_card_data.last4 and credit_card_data.cc_brand %}
<script type="text/javascript">
<script type="text/javascript">
(function () {window.hasCreditcard = true;})();
</script>

View File

@ -4,7 +4,7 @@ from django.test import TestCase
from django.core.urlresolvers import reverse
from django.core.urlresolvers import resolve
from django.contrib.auth.tokens import default_token_generator
from django.utils.http import urlsafe_base64_encode, urlsafe_base64_decode
from django.utils.http import urlsafe_base64_encode
from django.utils.encoding import force_bytes

View File

@ -1,7 +1,7 @@
from django.test import TestCase
# from django.test import TestCase
# Create your tests here.
test_user_can_add_ssh_key()
test_user_can_delete_ssh_ke()
# test_user_can_add_ssh_key()
#
# test_user_can_delete_ssh_ke()

View File

@ -1,5 +1,3 @@
from collections import namedtuple
from django.shortcuts import render
from django.http import Http404
from django.core.urlresolvers import reverse_lazy, reverse
@ -7,7 +5,6 @@ from django.contrib.auth.mixins import LoginRequiredMixin
from django.views.generic import View, CreateView, FormView, ListView, DetailView,\
DeleteView, TemplateView, UpdateView
from django.http import HttpResponseRedirect
from django.contrib.auth import authenticate, login
from django.contrib import messages
from django.conf import settings
from django.shortcuts import redirect
@ -35,7 +32,6 @@ from opennebula_api.serializers import VirtualMachineSerializer,\
from django.utils.translation import ugettext_lazy as _
from oca.exceptions import OpenNebulaException
from oca.pool import WrongNameError, WrongIdError
CONNECTION_ERROR = "Your VMs cannot be displayed at the moment due to a backend \
@ -205,31 +201,35 @@ class SignupView(CreateView):
return HttpResponseRedirect(reverse_lazy('hosting:signup-validate'))
class SignupValidateView(TemplateView):
template_name = "hosting/signup_validate.html"
def get_context_data(self, **kwargs):
context = super(SignupValidateView, self).get_context_data(**kwargs)
login_url = reverse('hosting:login')
message= _("Thank you for signing up. We have sent an email to you. Please follow the instructions in it to activate your account. Once activated, you can login using ") + '<a href="' + login_url +'">login</a>'
section_title='Sign up'
message = _("Thank you for signing up. We have sent an email to you. "
"Please follow the instructions in it to activate your account. "
"Once activated, you can login using ") + '<a href="' + login_url + '">login</a>'
section_title = 'Sign up'
context['message'] = mark_safe(message)
context['section_title'] = section_title
return context
class SignupValidatedView(SignupValidateView):
template_name = "hosting/signup_validate.html"
def get_context_data(self, **kwargs):
context = super(SignupValidateView, self).get_context_data(**kwargs)
validated = CustomUser.validate_url(self.kwargs['validate_slug'])
login_url = reverse('hosting:login')
if validated:
message= _("Your account has been activated. You can now ") + '<a href="' + login_url +'">login</a>'
section_title=_('Account activation')
message = _("Your account has been activated. You can now ") + '<a href="' + login_url + '">login</a>'
section_title = _('Account activation')
else:
message= _("Sorry. Your request is invalid.") + '<a href="' + login_url +'">login</a>'
section_title=_('Account activation')
message = _("Sorry. Your request is invalid.") + '<a href="' + login_url + '">login</a>'
section_title = _('Account activation')
context['message'] = mark_safe(message)
context['section_title'] = section_title
return context
@ -338,6 +338,7 @@ class SSHKeyDeleteView(LoginRequiredMixin, DeleteView):
return super(SSHKeyDeleteView, self).delete(request, *args, **kwargs)
class SSHKeyListView(LoginRequiredMixin, ListView):
template_name = "hosting/user_keys.html"
login_url = reverse_lazy('hosting:login')
@ -346,7 +347,6 @@ class SSHKeyListView(LoginRequiredMixin, ListView):
paginate_by = 10
ordering = '-id'
def get_queryset(self):
user = self.request.user
self.queryset = UserHostingKey.objects.filter(user=user)
@ -366,7 +366,6 @@ class SSHKeyCreateView(LoginRequiredMixin, FormView):
context_object_name = "virtual_machine"
success_url = reverse_lazy('hosting:ssh_keys')
def get_form_kwargs(self):
kwargs = super(SSHKeyCreateView, self).get_form_kwargs()
kwargs.update({'request': self.request})
@ -463,7 +462,7 @@ class PaymentVMView(LoginRequiredMixin, FormView):
return context
def get(self, request, *args, **kwargs):
if not UserHostingKey.objects.filter( user=self.request.user).exists():
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.'
@ -525,7 +524,7 @@ class PaymentVMView(LoginRequiredMixin, FormView):
manager = OpenNebulaManager(email=owner.email,
password=owner.password)
# Get user ssh key
if not UserHostingKey.objects.filter( user=self.request.user).exists():
if not UserHostingKey.objects.filter(user=self.request.user).exists():
context.update({
'sshError': 'error',
'form': form
@ -534,7 +533,7 @@ class PaymentVMView(LoginRequiredMixin, FormView):
# For now just get first one
user_key = UserHostingKey.objects.filter(
user=self.request.user).first()
# Create a vm using logged user
vm_id = manager.create_vm(
template_id=vm_template_id,
@ -552,8 +551,9 @@ class PaymentVMView(LoginRequiredMixin, FormView):
)
# Create a Hosting Bill
bill = HostingBill.create(
customer=customer, billing_address=billing_address)
# variable bill is not used
# bill = HostingBill.create(
# customer=customer, billing_address=billing_address)
# Create Billing Address for User if he does not have one
if not customer.user.billing_addresses.count():
@ -686,7 +686,7 @@ class CreateVirtualMachinesView(LoginRequiredMixin, View):
def get(self, request, *args, **kwargs):
if not UserHostingKey.objects.filter( user=self.request.user).exists():
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.'
@ -710,7 +710,7 @@ class CreateVirtualMachinesView(LoginRequiredMixin, View):
)
context = {
'error': 'connection'
}
}
return render(request, self.template_name, context)

View File

@ -38,26 +38,26 @@ class CustomHTMLCalendar(CustomCalendar):
self.requested_month = requested_month
super(CustomHTMLCalendar, self).__init__()
def formatday(self, day, weekday, month=None,year=None):
def formatday(self, day, weekday, month=None, year=None):
"""
Return a day as a table cell.
"""
booked = CalendarModel.objects.filter(user_id=self.user.id)
is_booked= booked.filter(datebooked=datetime.date(day=day,month=month,year=year))
is_booked = booked.filter(datebooked=datetime.date(day=day, month=month, year=year))
if month < int(self.requested_month):
return '<td class="prev-month %s">%d</td>' % ("selected" if is_booked else "",day)
return '<td class="prev-month %s">%d</td>' % ("selected" if is_booked else "", day)
elif month > int(self.requested_month):
return '<td class="next-month %s">%d</td>' % ("selected" if is_booked else "",day)
return '<td class="next-month %s">%d</td>' % ("selected" if is_booked else "", day)
else:
return '<td class="%s">%d</td>' % ("selected" if is_booked else "",day)
return '<td class="%s">%d</td>' % ("selected" if is_booked else "", day)
def formatweek(self, theweek,year):
def formatweek(self, theweek, year):
"""
Return a complete week as a table row.
"""
s = ''.join(self.formatday(d, wd, month,year) for (d, wd, month) in theweek)
s = ''.join(self.formatday(d, wd, month, year) for (d, wd, month) in theweek)
return '<tr>%s</tr>' % s
def formatmonthname(self, theyear, themonth, withyear=True):
@ -93,7 +93,7 @@ class CustomHTMLCalendar(CustomCalendar):
a(self.formatweekheader())
a('\n')
for week in self.monthdays2calendar(theyear, themonth):
a(self.formatweek(week,theyear))
a(self.formatweek(week, theyear))
a('\n')
a('</table>')
a('\n')
@ -102,8 +102,8 @@ class CustomHTMLCalendar(CustomCalendar):
class BookCalendar(CustomHTMLCalendar):
def __init__(self, user,requested_month):
self.user=user
def __init__(self, user, requested_month):
self.user = user
super(BookCalendar, self).__init__(requested_month)
def formatmonth(self, year, month):
@ -111,7 +111,7 @@ class BookCalendar(CustomHTMLCalendar):
return super(BookCalendar, self).formatmonth(year, month)
def day_cell(self, cssclass, body):
return '<td>%s</td>' % body
return '<td>%s</td>' % body
def formatmonthname(self, theyear, themonth, withyear):
"""

View File

@ -1,7 +1,7 @@
__author__ = 'tomislav'
from django import forms
from django.utils.translation import ugettext_lazy as _
from django.contrib.auth import authenticate,login
from django.contrib.auth import authenticate
from .models import CreditCards
@ -25,7 +25,7 @@ class LoginForm(forms.Form):
raise forms.ValidationError("Sorry, that login was invalid. Please try again.")
return self.cleaned_data
def login(self,request):
def login(self, request):
username = self.cleaned_data.get('email')
password = self.cleaned_data.get('password')
user = authenticate(email=username, password=password)
@ -36,6 +36,7 @@ class RegisterForm(SignupFormMixin):
password = forms.CharField(widget=forms.PasswordInput())
confirm_password = forms.CharField(widget=forms.PasswordInput())
class PaymentForm(forms.ModelForm):
class Meta:
model = CreditCards
@ -58,7 +59,7 @@ class PaymentForm(forms.ModelForm):
# if CreditCards.objects.filter(card_number=data.get("card_number")):
# raise forms.ValidationError({'card_number': _('Credit card is used before.')})
return self.cleaned_data
return data
def save(self, user_id):
self.instance.user_id = user_id

View File

@ -1,10 +1,9 @@
from datetime import datetime
from django.db import models
from django.utils.translation import ugettext_lazy as _
from django.contrib.auth.models import User, AbstractBaseUser, BaseUserManager, AbstractUser, PermissionsMixin
from django.contrib.auth.models import AbstractBaseUser, BaseUserManager, PermissionsMixin
from django.contrib.auth.hashers import make_password
from django.core.validators import RegexValidator
from django.contrib.auth.models import User
from django.contrib.sites.models import Site
from utils.stripe_utils import StripeUtils
@ -13,11 +12,12 @@ from django.core.urlresolvers import reverse
from utils.mailer import BaseEmail
REGISTRATION_MESSAGE = {'subject': "Validation mail",
'message': 'Please validate Your account under this link http://localhost:8000/en-us/digitalglarus/login/validate/{}',
'message': 'Please validate Your account under this link '
'http://localhost:8000/en-us/digitalglarus/login/validate/{}',
'from': 'test@test.com'}
def get_anonymous_user_instance(User):
def get_anonymous_user_instance():
return CustomUser(name='Anonymous', email='anonymous@ungleich.ch',
validation_slug=make_password(None))
@ -87,8 +87,9 @@ class CustomUser(AbstractBaseUser, PermissionsMixin):
'subject': _('Activate your Data Center Light account'),
'from_address': '(Data Center Light) Data Center Light Support <support@datacenterlight.ch>',
'to': user.email,
'context': {'base_url' : base_url,
'activation_link' : reverse('hosting:validate', kwargs={'validate_slug': user.validation_slug})},
'context': {'base_url': base_url,
'activation_link': reverse('hosting:validate',
kwargs={'validate_slug': user.validation_slug})},
'template_name': 'user_activation',
'template_path': 'datacenterlight/emails/'
}

View File

@ -7,7 +7,7 @@ stripe.api_key = settings.STRIPE_API_PRIVATE_KEY
class StripePayment(object):
@classmethod
def make_payment(cls,user,amount,token,time):
def make_payment(cls, user, amount, token, time):
try:
print(amount)
print(amount)
@ -19,7 +19,7 @@ class StripePayment(object):
source=token,
description=settings.STRIPE_DESCRIPTION_ON_PAYMENT
)
if charge['status'] =='succeeded':
if charge['status'] == 'succeeded':
obj = CreditCards.objects.filter(user_id=user.id).first()
obj.payment_type = time
obj.save()
@ -42,7 +42,7 @@ class StripePayment(object):
return "Currently its not possible to make payments."
except stripe.error.StripeError as e:
return "Currently its not possible to make payments."
#maybe send email
# maybe send email
except Exception as e:
return "Currently its not possible to make payments."
#maybe send email
# maybe send email

View File

@ -26,6 +26,4 @@ class LoginTestCase(TestCase):
# check fail login
res4 = self.client.post(url, data={'email': 'test@gmail.com', 'password': 'falsepassword'})
self.assertContains(res4,'Sorry, that login was invalid.',1,200)
self.assertContains(res4, 'Sorry, that login was invalid.', 1, 200)

View File

@ -8,7 +8,7 @@ urlpatterns = (
url(r"^$", views.LoginRegistrationView.as_view(), name='login_glarus'),
url(r"^validate/(?P<validate_slug>.*)/$", views.validate_email),
url(r"^membership/$", login_required(views.MembershipView.as_view()), name='membership'),
url(r'logout/?$',views.logout_glarus,name='logout_glarus'),
url(r'logout/?$', views.logout_glarus, name='logout_glarus'),
url(r"^buy/(?P<time>\w+)/$", login_required(views.CreditCardView.as_view()), name='payment'),
url(r'^buy/(?P<time>\w+)/reset',login_required(views.reset),name='reset')
url(r'^buy/(?P<time>\w+)/reset', login_required(views.reset), name='reset')
)

View File

@ -8,22 +8,23 @@ from django.contrib.auth import logout
from django.http import HttpResponseRedirect
from django.contrib.auth import login
from .models import CustomUser,StripeCustomer
from .models import CustomUser, StripeCustomer
from .forms import LoginForm, RegisterForm, PaymentForm
from utils.stripe_utils import StripeUtils
def validate_email(request, validate_slug):
validated = CustomUser.validate_url(validate_slug)
if validated:
return render(request, 'templates/validated_email.html',{'msg':True})
return render(request, 'templates/validated_email.html', {'msg': True})
else:
return render(request, 'templates/error.html',{'msg':'Validation failed.'})
return render(request, 'templates/error.html', {'msg': 'Validation failed.'})
def reset(request, time):
request.session['next'] = 0
return redirect('payment', time=time)
def reset(request,time):
request.session['next']=0
return redirect('payment',time=time)
class CreditCardView(View):
def _get_context(self, request, time):
@ -42,20 +43,20 @@ class CreditCardView(View):
context['form'] = PaymentForm()
return context
@cache_control(no_cache=True,must_revalidate=True)
@cache_control(no_cache=True, must_revalidate=True)
def get(self, request, time=None):
context = self._get_context(request, time)
next = request.session.get('next')
if next == 1 or next ==0:
if next == 1 or next == 0:
template = 'templates/creditcard.html'
request.session['next'] +=1
request.session['next'] += 1
elif next == 2:
customer = StripeCustomer.get_or_create(email=request.user.email,token=request.session['token'])
customer = StripeCustomer.get_or_create(email=request.user.email, token=request.session['token'])
stripe_utils = StripeUtils()
charge = stripe_utils.make_charge(request.session['amount'],customer=customer.stripe_id)
charge = stripe_utils.make_charge(request.session['amount'], customer=customer.stripe_id)
template = 'templates/validated.html'
resp = charge.get('response_object')
context['msg'] = resp.get('status',None)
resp = charge.get('response_object')
context['msg'] = resp.get('status', None)
request.session['next'] = None
return render(request, template, context)
@ -64,11 +65,11 @@ class CreditCardView(View):
stripe_token = request.POST['stripeToken']
if form.is_valid():
ret = form.save(request.user)
form.save(request.user)
amount = 35 if time == 'month' else 360
request.session['token'] = stripe_token
request.session['amount'] = amount
request.session['next'] +=1
request.session['next'] += 1
return render(request, 'templates/confirm.html',
context={'name': request.user.name, 'email': request.user.email})
else:
@ -121,13 +122,14 @@ class LoginRegistrationView(View):
class MembershipView(View):
def get(self, request):
#if the user has payed already
# if the user has payed already
member_payed = request.user.creditcards_set.filter(Q(payment_type='month') | Q(payment_type='year'))
if member_payed:
return redirect('/')
request.session['next'] = 0
language = get_language()
return render(request, 'templates/membership.html',context={'language_code':language})
return render(request, 'templates/membership.html', context={'language_code': language})
def logout_glarus(request):
logout(request)

View File

@ -1,3 +1,3 @@
from django.test import TestCase
# from django.test import TestCase
# Create your tests here.

View File

@ -1,3 +1,3 @@
from django.contrib import admin
# from django.contrib import admin
# Register your models here.

View File

@ -1,9 +1,10 @@
class KeyExistsError(Exception):
pass
class UserExistsError(Exception):
pass
class UserCredentialError(Exception):
pass

View File

@ -6,7 +6,6 @@ from oca.pool import WrongNameError, WrongIdError
from oca.exceptions import OpenNebulaException
from django.conf import settings
from django.utils.functional import cached_property
from utils.models import CustomUser
from .exceptions import KeyExistsError, UserExistsError, UserCredentialError
@ -38,9 +37,10 @@ class OpenNebulaManager():
)
except:
pass
def _get_client(self, user):
"""Get a opennebula client object for a CustomUser object
"""Get a opennebula client object for a CustomUser object
Args:
user (CustomUser): dynamicweb CustomUser object
@ -49,7 +49,7 @@ class OpenNebulaManager():
Raise:
ConnectionError: If the connection to the opennebula server can't be
established
established
"""
return oca.Client("{0}:{1}".format(
user.email,
@ -74,8 +74,8 @@ class OpenNebulaManager():
))
def _get_user(self, user):
"""Get the corresponding opennebula user for a CustomUser object
"""Get the corresponding opennebula user for a CustomUser object
Args:
user (CustomUser): dynamicweb CustomUser object
@ -85,7 +85,7 @@ class OpenNebulaManager():
Raise:
WrongNameError: If no openebula user with this credentials exists
ConnectionError: If the connection to the opennebula server can't be
established
established
"""
user_pool = self._get_user_pool()
return user_pool.get_by_name(user.email)
@ -93,16 +93,16 @@ class OpenNebulaManager():
def create_user(self, user: CustomUser):
"""Create a new opennebula user or a corresponding CustomUser object
Args:
user (CustomUser): dynamicweb CustomUser object
Returns:
int: Return the opennebula user id
Raises:
ConnectionError: If the connection to the opennebula server can't be
established
established
UserExistsError: If a user with this credeintals already exits on the
server
UserCredentialError: If a user with this email exists but the
@ -111,7 +111,7 @@ class OpenNebulaManager():
"""
try:
self._get_user(user)
try:
try:
self._get_client(self, user)
logger.debug('User already exists')
raise UserExistsError()
@ -122,19 +122,18 @@ class OpenNebulaManager():
except WrongNameError:
user_id = self.oneadmin_client.call(oca.User.METHODS['allocate'],
user.email, user.password, 'core')
user.email, user.password, 'core')
logger.debug('Created a user for CustomObject: {user} with user id = {u_id}',
user=user,
u_id=user_id
)
return user_id
user=user,
u_id=user_id
)
return user_id
except ConnectionRefusedError:
logger.error('Could not connect to host: {host} via protocol {protocol}'.format(
host=settings.OPENNEBULA_DOMAIN,
protocol=settings.OPENNEBULA_PROTOCOL)
)
raise ConnectionRefusedError
def _get_or_create_user(self, email, password):
try:
@ -166,7 +165,7 @@ class OpenNebulaManager():
host=settings.OPENNEBULA_DOMAIN,
protocol=settings.OPENNEBULA_PROTOCOL)
)
raise
raise
return user_pool
def _get_vm_pool(self):
@ -209,36 +208,6 @@ class OpenNebulaManager():
except:
raise ConnectionRefusedError
def create_template(self, name, cores, memory, disk_size, core_price, memory_price,
disk_size_price, ssh=''):
"""Create and add a new template to opennebula.
:param name: A string representation describing the template.
Used as label in view.
:param cores: Amount of virtual cpu cores for the VM.
:param memory: Amount of RAM for the VM (GB)
:param disk_size: Amount of disk space for VM (GB)
:param core_price: Price of virtual cpu for the VM per core.
:param memory_price: Price of RAM for the VM per GB
:param disk_size_price: Price of disk space for VM per GB
:param ssh: User public ssh key
"""
template_id = oca.VmTemplate.allocate(
self.oneadmin_client,
template_string_formatter.format(
name=name,
vcpu=cores,
cpu=0.1 * cores,
size=1024 * disk_size,
memory=1024 * memory,
# * 10 because we set cpu to *0.1
cpu_cost=10 * core_price,
memory_cost=memory_price,
disk_cost=disk_size_price,
ssh=ssh
)
)
def create_vm(self, template_id, specs, ssh_key=None):
template = self.get_template(template_id)
@ -286,8 +255,7 @@ class OpenNebulaManager():
""".format(size=1024 * int(specs['disk_size']),
image=image,
image_uname=image_uname)
if ssh_key:
vm_specs += """<CONTEXT>
<SSH_PUBLIC_KEY>{ssh}</SSH_PUBLIC_KEY>
@ -431,30 +399,30 @@ class OpenNebulaManager():
)
def add_public_key(self, user, public_key='', merge=False):
"""
"""
Args:
user (CustomUser): Dynamicweb user
Args:
user (CustomUser): Dynamicweb user
public_key (string): Public key to add to the user
merge (bool): Optional if True the new public key replaces the old
Raises:
KeyExistsError: If replace is False and the user already has a
public key
public key
WrongNameError: If no openebula user with this credentials exists
ConnectionError: If the connection to the opennebula server can't be
established
established
Returns:
True if public_key was added
"""
# TODO: Check if we can remove this first try because we basically just
# raise the possible Errors
# raise the possible Errors
try:
open_user = self._get_user(user)
try:
old_key = open_user.template.ssh_public_key
old_key = open_user.template.ssh_public_key
if not merge:
raise KeyExistsError()
public_key += '\n{key}'.format(key=old_key)
@ -462,7 +430,8 @@ class OpenNebulaManager():
except AttributeError:
pass
self.oneadmin_client.call('user.update', open_user.id,
'<CONTEXT><SSH_PUBLIC_KEY>{key}</SSH_PUBLIC_KEY></CONTEXT>'.format(key=public_key))
'<CONTEXT><SSH_PUBLIC_KEY>{key}</SSH_PUBLIC_KEY></CONTEXT>'
.format(key=public_key))
return True
except WrongNameError:
raise
@ -471,18 +440,18 @@ class OpenNebulaManager():
raise
def remove_public_key(self, user, public_key=''):
"""
"""
Args:
user (CustomUser): Dynamicweb user
Args:
user (CustomUser): Dynamicweb user
public_key (string): Public key to be removed to the user
Raises:
KeyDoesNotExistsError: If replace is False and the user already has a
public key
public key
WrongNameError: If no openebula user with this credentials exists
ConnectionError: If the connection to the opennebula server can't be
established
established
Returns:
True if public_key was removed
@ -492,21 +461,22 @@ class OpenNebulaManager():
try:
open_user = self._get_user(user)
try:
old_key = open_user.template.ssh_public_key
old_key = open_user.template.ssh_public_key
if public_key not in old_key:
return False
# raise KeyDoesNotExistsError()
if '\n{}'.format(public_key) in old_key:
public_key = old_key.replace('\n{}'.format(public_key), '')
else:
else:
public_key = old_key.replace(public_key, '')
except AttributeError:
return False
#raise KeyDoesNotExistsError()
# raise KeyDoesNotExistsError()
self.oneadmin_client.call('user.update', open_user.id,
'<CONTEXT><SSH_PUBLIC_KEY>{key}</SSH_PUBLIC_KEY></CONTEXT>'.format(key=public_key))
'<CONTEXT><SSH_PUBLIC_KEY>{key}</SSH_PUBLIC_KEY></CONTEXT>'
.format(key=public_key))
return True
except WrongNameError:
raise

View File

@ -1,20 +1,19 @@
import oca
import ipaddress
from rest_framework import serializers
from oca import OpenNebulaException
from oca.template import VmTemplate
from .models import OpenNebulaManager
class VirtualMachineTemplateSerializer(serializers.Serializer):
"""Serializer to map the virtual machine template instance into JSON format."""
id = serializers.IntegerField(read_only=True)
name = serializers.SerializerMethodField()
cores = serializers.SerializerMethodField()
disk_size = serializers.SerializerMethodField()
memory = serializers.SerializerMethodField()
id = serializers.IntegerField(read_only=True)
name = serializers.SerializerMethodField()
cores = serializers.SerializerMethodField()
disk_size = serializers.SerializerMethodField()
memory = serializers.SerializerMethodField()
def get_cores(self, obj):
if hasattr(obj.template, 'vcpu'):
@ -28,7 +27,7 @@ class VirtualMachineTemplateSerializer(serializers.Serializer):
try:
for disk in template.disks:
disk_size += int(disk.size)
return disk_size / 1024
return disk_size / 1024
except:
return 0
@ -39,30 +38,28 @@ class VirtualMachineTemplateSerializer(serializers.Serializer):
return obj.name.strip('public-')
class VirtualMachineSerializer(serializers.Serializer):
"""Serializer to map the virtual machine instance into JSON format."""
name = serializers.SerializerMethodField()
cores = serializers.IntegerField(source='template.vcpu')
disk = serializers.IntegerField(write_only=True)
set_memory = serializers.IntegerField(write_only=True, label='Memory')
memory = serializers.SerializerMethodField()
cores = serializers.IntegerField(source='template.vcpu')
disk = serializers.IntegerField(write_only=True)
set_memory = serializers.IntegerField(write_only=True, label='Memory')
memory = serializers.SerializerMethodField()
disk_size = serializers.SerializerMethodField()
ipv4 = serializers.SerializerMethodField()
ipv6 = serializers.SerializerMethodField()
vm_id = serializers.IntegerField(read_only=True, source='id')
state = serializers.CharField(read_only=True, source='str_state')
price = serializers.SerializerMethodField()
ssh_key = serializers.CharField(write_only=True)
disk_size = serializers.SerializerMethodField()
ipv4 = serializers.SerializerMethodField()
ipv6 = serializers.SerializerMethodField()
vm_id = serializers.IntegerField(read_only=True, source='id')
state = serializers.CharField(read_only=True, source='str_state')
price = serializers.SerializerMethodField()
ssh_key = serializers.CharField(write_only=True)
configuration = serializers.SerializerMethodField()
template_id = serializers.ChoiceField(
choices=[(key.id, key.name) for key in
OpenNebulaManager().try_get_templates()
],
OpenNebulaManager().try_get_templates()
],
source='template.template_id',
write_only=True,
default=[]
@ -77,12 +74,11 @@ class VirtualMachineSerializer(serializers.Serializer):
template_id = validated_data['template']['template_id']
specs = {
'cpu' : cores,
'disk_size' : disk,
'memory' : memory,
'cpu': cores,
'disk_size': disk,
'memory': memory,
}
try:
manager = OpenNebulaManager(email=owner.email,
password=owner.password,
@ -92,7 +88,7 @@ class VirtualMachineSerializer(serializers.Serializer):
specs=specs)
except OpenNebulaException as err:
raise serializers.ValidationError("OpenNebulaException occured. {0}".format(err))
return manager.get_vm(opennebula_id)
def get_memory(self, obj):
@ -112,6 +108,7 @@ class VirtualMachineSerializer(serializers.Serializer):
for disk in template.disks:
price += int(disk.size)/1024 * 0.6
return price
def get_configuration(self, obj):
template_id = obj.template.template_id
template = OpenNebulaManager().get_template(template_id)
@ -123,7 +120,7 @@ class VirtualMachineSerializer(serializers.Serializer):
return str(v4_from_mac(nic.mac))
else:
return '-'
def get_ipv6(self, obj):
nic = obj.template.nics[0]
return nic.ip6_global
@ -131,12 +128,15 @@ class VirtualMachineSerializer(serializers.Serializer):
def get_name(self, obj):
return obj.name.strip('public-')
def hexstr2int(string):
return int(string.replace(':', ''), 16)
FIRST_MAC = hexstr2int('02:00:b3:39:79:4d')
FIRST_V4 = ipaddress.ip_address('185.203.112.2')
COUNT = 1000
FIRST_V4 = ipaddress.ip_address('185.203.112.2')
COUNT = 1000
def v4_from_mac(mac):
"""Calculates the IPv4 address from a MAC address.
@ -146,5 +146,6 @@ def v4_from_mac(mac):
"""
return FIRST_V4 + (hexstr2int(mac) - FIRST_MAC)
def is_in_v4_range(mac):
return FIRST_MAC <= hexstr2int(mac) < FIRST_MAC + 1000

View File

@ -1,4 +1,3 @@
import socket
import random
import string
@ -8,32 +7,30 @@ from .models import OpenNebulaManager
from .serializers import VirtualMachineSerializer
from utils.models import CustomUser
class OpenNebulaManagerTestCases(TestCase):
"""This class defines the test suite for the opennebula manager model."""
def setUp(self):
"""Define the test client and other test variables."""
self.email = '{}@ungleich.ch'.format(''.join(random.choices(string.ascii_uppercase, k=10)))
self.password = ''.join(random.choices(string.ascii_uppercase + string.digits, k=20))
self.password = ''.join(random.choices(string.ascii_uppercase + string.digits, k=20))
self.user = CustomUser.objects.create(name='test', email=self.email,
password=self.password)
password=self.password)
self.vm_specs = {}
self.vm_specs['cpu'] = 1
self.vm_specs['memory'] = 2
self.vm_specs['disk_size'] = 10
self.manager = OpenNebulaManager()
self.manager = OpenNebulaManager()
def test_connect_to_server(self):
"""Test the opennebula manager can connect to a server."""
try:
ver = self.manager.oneadmin_client.version()
except:
except:
ver = None
self.assertTrue(ver is not None)
@ -54,7 +51,7 @@ class OpenNebulaManagerTestCases(TestCase):
# Remove the user afterwards
user = user_pool.get_by_name(self.email)
user.delete()
self.assertNotEqual(old_count, new_count)
def test_user_can_login(self):
@ -64,7 +61,7 @@ class OpenNebulaManagerTestCases(TestCase):
client = self.manager._get_client(self.user)
version = client.version()
# Cleanup
# Cleanup
user.delete()
self.assertNotEqual(version, None)
@ -77,11 +74,11 @@ class OpenNebulaManagerTestCases(TestCase):
# Fetch new user information from opennebula
user.info()
user_public_key = user.template.ssh_public_key
# Cleanup
# Cleanup
user.delete()
self.assertEqual(user_public_key, public_key)
def test_append_public_key_to_user(self):
""" Test the manager can append a new public key to an user """
self.manager.create_user(self.user)
@ -94,11 +91,11 @@ class OpenNebulaManagerTestCases(TestCase):
self.manager.add_public_key(self.user, public_key, merge=True)
user.info()
new_public_key = user.template.ssh_public_key
# Cleanup
# Cleanup
user.delete()
self.assertEqual(new_public_key, '{}\n{}'.format(old_public_key,
public_key))
public_key))
def test_remove_public_key_to_user(self):
""" Test the manager can remove a public key from an user """
@ -112,12 +109,11 @@ class OpenNebulaManagerTestCases(TestCase):
self.manager.remove_public_key(self.user, public_key)
user.info()
new_public_key = user.template.ssh_public_key
# Cleanup
# Cleanup
user.delete()
self.assertEqual(new_public_key,
old_public_key.replace('{}\n'.format(public_key), '', 1))
old_public_key.replace('{}\n'.format(public_key), '', 1))
def test_requires_ssh_key_for_new_vm(self):
"""Test the opennebula manager requires the user to have a ssh key when
@ -128,14 +124,11 @@ class VirtualMachineSerializerTestCase(TestCase):
def setUp(self):
"""Define the test client and other test variables."""
self.manager = OpenNebulaManager(email=None, password=None)
def test_serializer_strips_of_public(self):
""" Test the serialized virtual machine object contains no 'public-'."""
""" Test the serialized virtual machine object contains no 'public-'."""
for vm in self.manager.get_vms():
serialized = VirtualMachineSerializer(vm)
self.assertEqual(serialized.data.get('name'), vm.name.strip('public-'))
break

View File

@ -1,19 +1,11 @@
from rest_framework import generics
from rest_framework import permissions
from django.contrib.auth.mixins import LoginRequiredMixin
from django.contrib.auth import authenticate, login
from utils.views import LoginViewMixin
from membership.models import CustomUser, StripeCustomer
from guardian.mixins import PermissionRequiredMixin
from .serializers import VirtualMachineTemplateSerializer, \
VirtualMachineSerializer
from .serializers import VirtualMachineSerializer
from .models import OpenNebulaManager
from rest_framework.exceptions import APIException
class ServiceUnavailable(APIException):
status_code = 503
default_detail = 'Service temporarily unavailable, try again later.'
@ -29,7 +21,7 @@ class VmCreateView(generics.ListCreateAPIView):
owner = self.request.user
manager = OpenNebulaManager(email=owner.email,
password=owner.password)
# We may have ConnectionRefusedError if we don't have a
# We may have ConnectionRefusedError if we don't have a
# connection to OpenNebula. For now, we raise ServiceUnavailable
try:
vms = manager.get_vms()
@ -41,6 +33,7 @@ class VmCreateView(generics.ListCreateAPIView):
"""Save the post data when creating a new template."""
serializer.save(owner=self.request.user)
class VmDetailsView(generics.RetrieveUpdateDestroyAPIView):
"""This class handles the http GET, PUT and DELETE requests."""
permission_classes = (permissions.IsAuthenticated, )
@ -51,7 +44,7 @@ class VmDetailsView(generics.RetrieveUpdateDestroyAPIView):
owner = self.request.user
manager = OpenNebulaManager(email=owner.email,
password=owner.password)
# We may have ConnectionRefusedError if we don't have a
# We may have ConnectionRefusedError if we don't have a
# connection to OpenNebula. For now, we raise ServiceUnavailable
try:
vms = manager.get_vms()
@ -63,22 +56,21 @@ class VmDetailsView(generics.RetrieveUpdateDestroyAPIView):
owner = self.request.user
manager = OpenNebulaManager(email=owner.email,
password=owner.password)
# We may have ConnectionRefusedError if we don't have a
# We may have ConnectionRefusedError if we don't have a
# connection to OpenNebula. For now, we raise ServiceUnavailable
try:
vm = manager.get_vm(self.kwargs.get('pk'))
except ConnectionRefusedError:
raise ServiceUnavailable
return vm
return vm
def perform_destroy(self, instance):
owner = self.request.user
manager = OpenNebulaManager(email=owner.email,
password=owner.password)
# We may have ConnectionRefusedError if we don't have a
# We may have ConnectionRefusedError if we don't have a
# connection to OpenNebula. For now, we raise ServiceUnavailable
try:
manager.delete_vm(instance.id)
except ConnectionRefusedError:
raise ServiceUnavailable

View File

@ -84,5 +84,4 @@ django-admin-honeypot==1.0.0
coverage==4.3.4
git+https://github.com/ungleich/python-oca.git#egg=python-oca
djangorestframework
flake8==3.3.0

3
setup.cfg Executable file
View File

@ -0,0 +1,3 @@
[flake8]
max-line-length = 120
exclude = .tox,.git,*/migrations/*,*/static/*,docs,venv,node_modules/*

View File

@ -9,4 +9,5 @@ from .models import UngleichPage
class UngleichPageAdmin(PageExtensionAdmin):
pass
admin.site.register(UngleichPage, UngleichPageAdmin)

View File

@ -2,7 +2,6 @@ from cms.extensions.toolbar import ExtensionToolbar
from django.utils.translation import ugettext_lazy as _
from cms.toolbar_pool import toolbar_pool
from cms.toolbar_base import CMSToolbar
from .models import UngleichPage
@ -22,4 +21,4 @@ class UngleichPageToolbar(ExtensionToolbar):
if url:
# adds a toolbar item
current_page_menu.add_modal_item(_('Page Header'), url=url,
disabled=not self.toolbar.edit_mode)
disabled=not self.toolbar.edit_mode)

View File

@ -1,5 +1,3 @@
from django.db import models
from cms.extensions import PageExtension
from cms.extensions.extension_pool import extension_pool
from filer.fields.image import FilerImageField
@ -9,11 +7,12 @@ from filer.fields.image import FilerImageField
class UngleichPage(PageExtension):
#image_header = models.ImageField(upload_to='image_header')
# image_header = models.ImageField(upload_to='image_header')
image = FilerImageField(null=True, blank=True,
related_name="ungleinch_page_image")
related_name="ungleinch_page_image")
class Meta:
app_label = 'ungleich'
extension_pool.register(UngleichPage)

View File

@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
from django.utils.translation import ugettext_lazy as _
# from django.utils.translation import ugettext_lazy as _
# TEMPLATES = {
# 'blog_u.html': _('Blog'),
# 'page.html': _('Page'),

View File

@ -1,3 +1,3 @@
from django.test import TestCase
# from django.test import TestCase
# Create your tests here.

View File

@ -6,6 +6,7 @@ from django.utils.translation import get_language
from djangocms_blog.models import Post
from djangocms_blog.views import PostListView
from djangocms_blog.settings import get_setting
from django.utils.translation import ugettext_lazy as _
def blog(request):

View File

@ -1,3 +1,3 @@
from django.contrib import admin
# from django.contrib import admin
# Register your models here.

View File

@ -1,3 +1,3 @@
from django.db import models
# from django.db import models
# Create your models here.

View File

@ -1,3 +1,3 @@
from django.test import TestCase
# from django.test import TestCase
# Create your tests here.

View File

@ -2,10 +2,9 @@ from django.contrib import messages
from django.views.generic.edit import FormView
from django.utils.translation import ugettext_lazy as _
from django.core.urlresolvers import reverse_lazy,reverse
from django.core.urlresolvers import reverse_lazy
from django.views.generic import View
from django.shortcuts import render,redirect,render_to_response
from django.http import HttpResponseRedirect
from django.shortcuts import render
from utils.forms import ContactUsForm

View File

@ -1,5 +1,5 @@
from django.contrib import admin
from .models import BillingAddress, UserBillingAddress
from .models import UserBillingAddress
# Register your models here.

View File

@ -1,6 +1,5 @@
from django.utils.translation import ugettext as _
from django.db import models
from django import forms
# http://xml.coverpages.org/country3166.html
COUNTRIES = (
@ -255,4 +254,4 @@ class CountryField(models.CharField):
super(CountryField, self).__init__(*args, **kwargs)
def get_internal_type(self):
return "CharField"
return "CharField"

View File

@ -115,7 +115,8 @@ class BillingAddressForm(forms.ModelForm):
class UserBillingAddressForm(forms.ModelForm):
user = forms.ModelChoiceField(queryset=CustomUser.objects.all(),
widget=forms.HiddenInput())
widget=forms.HiddenInput())
class Meta:
model = UserBillingAddress
fields = ['street_address', 'city', 'postal_code', 'country', 'user']
@ -126,6 +127,7 @@ class UserBillingAddressForm(forms.ModelForm):
'Country': _('Country'),
}
class ContactUsForm(forms.ModelForm):
error_css_class = 'autofocus'

View File

@ -77,4 +77,3 @@ class DigitalGlarusRegistrationMailer(BaseMailer):
self.registration = self.message
self._message = self._message.format(slug=self._slug)
super().__init__()

View File

@ -1,6 +1,4 @@
from django.db import models
from django.core import serializers
from django.forms.models import model_to_dict
from membership.models import CustomUser
@ -18,6 +16,7 @@ class BaseBillingAddress(models.Model):
class Meta:
abstract = True
class BillingAddress(BaseBillingAddress):
def __str__(self):

View File

@ -127,22 +127,10 @@ class StripeUtils(object):
id=id)
@handleStripeError
def make_payment(self, user, amount, token):
def make_payment(self, customer, amount, token):
charge = self.stripe.Charge.create(
amount=amount, # in cents
currency=self.CURRENCY,
customer=customer
)
return charge
@handleStripeError
def create_plan(self, amount, name, id):
self.stripe.Plan.create(
amount=amount,
interval=self.INTERVAL,
name=name,
currency=self.CURRENCY,
id=id)