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

@ -8,4 +8,6 @@ env:
- DJANGO_SECRET_KEY=0 - DJANGO_SECRET_KEY=0
# install dependencies # install dependencies
install: "pip install -r requirements.txt" 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. # Register your models here.

View file

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

View file

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

View file

@ -7,6 +7,6 @@ urlpatterns = [
url(r'^/?$', IndexView.as_view(), name='index'), url(r'^/?$', IndexView.as_view(), name='index'),
url(r'/login/', LoginView.as_view(), name='login'), url(r'/login/', LoginView.as_view(), name='login'),
url(r'/contact', ContactView.as_view(), name='contact'), url(r'/contact', ContactView.as_view(), name='contact'),
# url(r'^/beta-program/?$', BetaProgramView.as_view(), name='beta'), # url(r'^/beta-program/?$', BetaProgramView.as_view(), name='beta'),
# url(r'^/landing/?$', LandingProgramView.as_view(), name='landing'), # 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.utils.translation import ugettext_lazy as _
from django.views.generic.edit import FormView from django.views.generic.edit import FormView
from django.contrib import messages from django.contrib import messages
from django.core.urlresolvers import reverse_lazy, reverse
from django.shortcuts import render from django.shortcuts import render
from utils.forms import ContactUsForm from utils.forms import ContactUsForm
class IndexView(TemplateView): class IndexView(TemplateView):
template_name = "alplora/index.html" template_name = "alplora/index.html"
@ -18,6 +18,7 @@ class IndexView(TemplateView):
context.update(languages) context.update(languages)
return context return context
class ContactView(FormView): class ContactView(FormView):
template_name = 'alplora/contact.html' template_name = 'alplora/contact.html'
form_class = ContactUsForm form_class = ContactUsForm
@ -35,6 +36,7 @@ class ContactView(FormView):
messages.add_message(self.request, messages.SUCCESS, self.success_message) 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): class LoginView(TemplateView):
template_name = "alplora/login.html" template_name = "alplora/login.html"

View file

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

View file

@ -5,20 +5,18 @@ from django.utils.translation import activate, get_language
register = template.Library() register = template.Library()
@register.simple_tag(takes_context=True) @register.simple_tag(takes_context=True)
def change_lang(context, lang=None, *args, **kwargs): def change_lang(context, lang=None, *args, **kwargs):
path = context['request'].path path = context['request'].path
url_parts = resolve( path ) url_parts = resolve(path)
url = path url = path
cur_language = get_language() cur_language = get_language()
try: try:
activate(lang) activate(lang)
url = reverse( url_parts.view_name, kwargs=url_parts.kwargs ) url = reverse(url_parts.view_name, kwargs=url_parts.kwargs)
finally: finally:
activate(cur_language) 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. # Create your tests here.

View file

@ -3,7 +3,7 @@ from django.http import HttpResponseRedirect
from .forms import BetaAccessForm from .forms import BetaAccessForm
from .models import BetaAccess, BetaAccessVMType, BetaAccessVM from .models import BetaAccess, BetaAccessVMType, BetaAccessVM
from django.contrib import messages 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 django.core.mail import EmailMessage
from utils.mailer import BaseEmail from utils.mailer import BaseEmail
from django.shortcuts import render from django.shortcuts import render
@ -14,12 +14,15 @@ from django.core.exceptions import ValidationError
from opennebula_api.models import OpenNebulaManager from opennebula_api.models import OpenNebulaManager
from opennebula_api.serializers import VirtualMachineTemplateSerializer from opennebula_api.serializers import VirtualMachineTemplateSerializer
class LandingProgramView(TemplateView): class LandingProgramView(TemplateView):
template_name = "datacenterlight/landing.html" template_name = "datacenterlight/landing.html"
class SuccessView(TemplateView): class SuccessView(TemplateView):
template_name = "datacenterlight/success.html" template_name = "datacenterlight/success.html"
class PricingView(TemplateView): class PricingView(TemplateView):
template_name = "datacenterlight/pricing.html" template_name = "datacenterlight/pricing.html"
@ -32,17 +35,16 @@ class PricingView(TemplateView):
'templates': VirtualMachineTemplateSerializer(templates, many=True).data, 'templates': VirtualMachineTemplateSerializer(templates, many=True).data,
} }
except: except:
messages.error( request, messages.error(request,
'We have a temporary problem to connect to our backend. \ 'We have a temporary problem to connect to our backend. \
Please try again in a few minutes' Please try again in a few minutes'
) )
context = { context = {
'error' : 'connection' 'error': 'connection'
} }
return render(request, self.template_name, context) return render(request, self.template_name, context)
def post(self, request): def post(self, request):
cores = request.POST.get('cpu') cores = request.POST.get('cpu')
@ -61,7 +63,7 @@ class PricingView(TemplateView):
request.session['next'] = reverse('hosting:payment') request.session['next'] = reverse('hosting:payment')
request.session['specs'] = { request.session['specs'] = {
'cpu':cores, 'cpu': cores,
'memory': memory, 'memory': memory,
'disk_size': storage, 'disk_size': storage,
'price': price, 'price': price,
@ -111,6 +113,7 @@ class BetaAccessView(FormView):
messages.add_message(self.request, messages.SUCCESS, self.success_message) messages.add_message(self.request, messages.SUCCESS, self.success_message)
return render(self.request, 'datacenterlight/beta_success.html', {}) return render(self.request, 'datacenterlight/beta_success.html', {})
class BetaProgramView(CreateView): class BetaProgramView(CreateView):
template_name = "datacenterlight/beta.html" template_name = "datacenterlight/beta.html"
model = BetaAccessVM model = BetaAccessVM
@ -178,12 +181,12 @@ class IndexView(CreateView):
'templates': VirtualMachineTemplateSerializer(templates, many=True).data, 'templates': VirtualMachineTemplateSerializer(templates, many=True).data,
} }
except: except:
messages.error( request, messages.error(request,
'We have a temporary problem to connect to our backend. \ 'We have a temporary problem to connect to our backend. \
Please try again in a few minutes' Please try again in a few minutes'
) )
context = { context = {
'error' : 'connection' 'error': 'connection'
} }
return render(request, self.template_name, context) return render(request, self.template_name, context)

View file

@ -1,5 +1,5 @@
from django.contrib import admin 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 MembershipOrder, Membership, MembershipType, BookingOrder, BookingCancellation
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse

View file

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

View file

@ -1,7 +1,6 @@
from django import forms from django import forms
from django.db.models import Q from django.db.models import Q
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from datetime import datetime
from utils.models import BillingAddress from utils.models import BillingAddress

View file

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

View file

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

View file

@ -316,7 +316,8 @@ class DGGallery(models.Model):
class Meta: class Meta:
verbose_name_plural = 'dgGallery' verbose_name_plural = 'dgGallery'
#
class DGPicture(models.Model): class DGPicture(models.Model):
gallery = models.ForeignKey(DGGallery) gallery = models.ForeignKey(DGGallery)
image = FilerImageField(related_name='dg_gallery') image = FilerImageField(related_name='dg_gallery')
@ -325,8 +326,10 @@ class DGPicture(models.Model):
def __str__(self): def __str__(self):
return "%s" % (self.image.name) return "%s" % (self.image.name)
class DGGalleryPlugin(CMSPlugin): class DGGalleryPlugin(CMSPlugin):
dgGallery = models.ForeignKey(DGGallery) dgGallery = models.ForeignKey(DGGallery)
class DGSupportersPlugin(CMSPlugin): class DGSupportersPlugin(CMSPlugin):
pass pass

View file

@ -1,4 +1,3 @@
import json
from model_mommy import mommy from model_mommy import mommy
from unittest import mock from unittest import mock

View file

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

View file

@ -9,12 +9,15 @@ from django.utils.translation import ugettext_lazy as _
# dotenv # dotenv
import dotenv import dotenv
gettext = lambda s: s
def gettext(s):
return s
def env(env_name): def env(env_name):
return os.environ.get(env_name) return os.environ.get(env_name)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
PROJECT_DIR = os.path.abspath( PROJECT_DIR = os.path.abspath(
@ -83,7 +86,7 @@ INSTALLED_APPS = (
'django_select2', 'django_select2',
'meta', 'meta',
'meta_mixin', 'meta_mixin',
# 'admin_enhancer', # 'admin_enhancer',
'djangocms_blog', 'djangocms_blog',
'bootstrap3', 'bootstrap3',
'compressor', 'compressor',
@ -433,5 +436,5 @@ MANAGERS = ADMINS
ALLOWED_HOSTS = [ ALLOWED_HOSTS = [
".ungleich.ch", ".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 # dotenv
import dotenv import dotenv
gettext = lambda s: s
def gettext(s):
return s
def env(env_name): def env(env_name):
@ -186,7 +188,11 @@ CMS_TEMPLATES = (
DATABASES = { DATABASES = {
'default': { 'default': {
'ENGINE': 'django.db.backends.postgresql_psycopg2', '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 # EMAIL MESSAGES
REGISTRATION_MESSAGE = {'subject': "Validation mail", 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_PRIVATE_KEY = env('STRIPE_API_PRIVATE_KEY')
STRIPE_API_PUBLIC_KEY = env('STRIPE_API_PUBLIC_KEY') STRIPE_API_PUBLIC_KEY = env('STRIPE_API_PUBLIC_KEY')
DEBUG = True DEBUG = True
if DEBUG: # not used
from .local import * # if DEBUG:
else: # from .local import *
from .prod import * # # else:
# # from .prod import *
ANONYMOUS_USER_NAME = 'anonymous@ungleich.ch' ANONYMOUS_USER_NAME = 'anonymous@ungleich.ch'

View file

@ -1,5 +1,7 @@
from .base import * from .base import * # flake8: noqa
REGISTRATION_MESSAGE['message'] = REGISTRATION_MESSAGE['message'].format(host='dynamicweb-development.ungleich.ch',slug='{slug}')
REGISTRATION_MESSAGE['message'] = REGISTRATION_MESSAGE['message'].format(host='dynamicweb-development.ungleich.ch',
slug='{slug}')
ALLOWED_HOSTS = [ 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', 'django_extensions',
'debug_toolbar' 'debug_toolbar'
) )

View file

@ -1,15 +1,16 @@
from .base import * from .base import * # flake8: noqa
# List of people that get admin messages # 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' 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 = [ ALLOWED_HOSTS = [
".ungleich.ch", ".ungleich.ch",

View file

@ -12,7 +12,7 @@ from django.views.generic import RedirectView
from django.core.urlresolvers import reverse_lazy from django.core.urlresolvers import reverse_lazy
import debug_toolbar import debug_toolbar
urlpatterns = [ url(r'^index.html$', LandingView.as_view()), urlpatterns = [url(r'^index.html$', LandingView.as_view()),
url(r'^hosting/', include('hosting.urls', namespace="hosting")), url(r'^hosting/', include('hosting.urls', namespace="hosting")),
url(r'^open_api/', include('opennebula_api.urls', url(r'^open_api/', include('opennebula_api.urls',
namespace='opennebula_api')), namespace='opennebula_api')),
@ -30,12 +30,13 @@ urlpatterns += i18n_patterns('',
url(r'^/?$', LandingView.as_view()), url(r'^/?$', LandingView.as_view()),
url(r'^admin/', include(admin.site.urls)), url(r'^admin/', include(admin.site.urls)),
url(r'^datacenterlight', include('datacenterlight.urls', namespace="datacenterlight")), 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'^alplora', include('alplora.urls', namespace="alplora")),
url(r'^membership/', include(membership_urls)), url(r'^membership/', include(membership_urls)),
url(r'^digitalglarus/', include('digitalglarus.urls', url(r'^digitalglarus/', include('digitalglarus.urls',
namespace="digitalglarus")), namespace="digitalglarus")),
#url(r'^blog/', include('ungleich.urls', namespace='ungleich')), # url(r'^blog/', include('ungleich.urls', namespace='ungleich')),
url(r'^', url(r'^',
include('ungleich_page.urls', namespace='ungleich_page'), include('ungleich_page.urls', namespace='ungleich_page'),
name='ungleich_page'), name='ungleich_page'),
@ -50,4 +51,4 @@ if settings.DEBUG:
'document_root': settings.MEDIA_ROOT, '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/ https://docs.djangoproject.com/en/1.8/howto/deployment/wsgi/
""" """
import os,sys import os
#sys.path.append(os.path.dirname(__file__)) 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/') sys.path.append('/home/app/pyvenv/lib/python3.4/site-packages/')
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "dynamicweb.settings.prod") os.environ.setdefault("DJANGO_SETTINGS_MODULE", "dynamicweb.settings.prod")
from django.core.wsgi import get_wsgi_application
application = get_wsgi_application() application = get_wsgi_application()

View file

@ -1,8 +1,4 @@
from django.contrib import admin 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 from .models import HostingOrder, HostingBill, HostingPlan

View file

@ -1,14 +1,11 @@
import random
import string
from django import forms from django import forms
from membership.models import CustomUser from membership.models import CustomUser
from django.contrib.auth import authenticate from django.contrib.auth import authenticate
from django.utils.translation import ugettext_lazy as _ 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): class HostingUserLoginForm(forms.Form):

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 from hosting.models import VirtualMachineType
@ -55,15 +55,15 @@ class Command(BaseCommand):
}, },
] ]
# not used
hetzner = { # hetzner = {
'base_price': 10, # 'base_price': 10,
'core_price': 5, # 'core_price': 5,
'memory_price': 2, # 'memory_price': 2,
'disk_size_price': 0.6, # 'disk_size_price': 0.6,
'description': 'VM auf einzelner HW, Raid1, kein HA', # 'description': 'VM auf einzelner HW, Raid1, kein HA',
'location': 'DE' # 'location': 'DE'
} # }
# return { # return {
# # 'hetzner_nug': { # # 'hetzner_nug': {

View file

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

View file

@ -4,7 +4,7 @@ from django.test import TestCase
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from django.core.urlresolvers import resolve from django.core.urlresolvers import resolve
from django.contrib.auth.tokens import default_token_generator 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 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. # Create your tests here.
test_user_can_add_ssh_key() # test_user_can_add_ssh_key()
#
test_user_can_delete_ssh_ke() # test_user_can_delete_ssh_ke()

View file

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

View file

@ -38,26 +38,26 @@ class CustomHTMLCalendar(CustomCalendar):
self.requested_month = requested_month self.requested_month = requested_month
super(CustomHTMLCalendar, self).__init__() 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. Return a day as a table cell.
""" """
booked = CalendarModel.objects.filter(user_id=self.user.id) 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): 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): 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: 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. 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 return '<tr>%s</tr>' % s
def formatmonthname(self, theyear, themonth, withyear=True): def formatmonthname(self, theyear, themonth, withyear=True):
@ -93,7 +93,7 @@ class CustomHTMLCalendar(CustomCalendar):
a(self.formatweekheader()) a(self.formatweekheader())
a('\n') a('\n')
for week in self.monthdays2calendar(theyear, themonth): for week in self.monthdays2calendar(theyear, themonth):
a(self.formatweek(week,theyear)) a(self.formatweek(week, theyear))
a('\n') a('\n')
a('</table>') a('</table>')
a('\n') a('\n')
@ -102,8 +102,8 @@ class CustomHTMLCalendar(CustomCalendar):
class BookCalendar(CustomHTMLCalendar): class BookCalendar(CustomHTMLCalendar):
def __init__(self, user,requested_month): def __init__(self, user, requested_month):
self.user=user self.user = user
super(BookCalendar, self).__init__(requested_month) super(BookCalendar, self).__init__(requested_month)
def formatmonth(self, year, month): def formatmonth(self, year, month):

View file

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

View file

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

View file

@ -7,7 +7,7 @@ stripe.api_key = settings.STRIPE_API_PRIVATE_KEY
class StripePayment(object): class StripePayment(object):
@classmethod @classmethod
def make_payment(cls,user,amount,token,time): def make_payment(cls, user, amount, token, time):
try: try:
print(amount) print(amount)
print(amount) print(amount)
@ -19,7 +19,7 @@ class StripePayment(object):
source=token, source=token,
description=settings.STRIPE_DESCRIPTION_ON_PAYMENT description=settings.STRIPE_DESCRIPTION_ON_PAYMENT
) )
if charge['status'] =='succeeded': if charge['status'] == 'succeeded':
obj = CreditCards.objects.filter(user_id=user.id).first() obj = CreditCards.objects.filter(user_id=user.id).first()
obj.payment_type = time obj.payment_type = time
obj.save() obj.save()
@ -42,7 +42,7 @@ class StripePayment(object):
return "Currently its not possible to make payments." return "Currently its not possible to make payments."
except stripe.error.StripeError as e: except stripe.error.StripeError as e:
return "Currently its not possible to make payments." return "Currently its not possible to make payments."
#maybe send email # maybe send email
except Exception as e: except Exception as e:
return "Currently its not possible to make payments." 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 # check fail login
res4 = self.client.post(url, data={'email': 'test@gmail.com', 'password': 'falsepassword'}) 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"^$", views.LoginRegistrationView.as_view(), name='login_glarus'),
url(r"^validate/(?P<validate_slug>.*)/$", views.validate_email), url(r"^validate/(?P<validate_slug>.*)/$", views.validate_email),
url(r"^membership/$", login_required(views.MembershipView.as_view()), name='membership'), 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+)/$", 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.http import HttpResponseRedirect
from django.contrib.auth import login from django.contrib.auth import login
from .models import CustomUser,StripeCustomer from .models import CustomUser, StripeCustomer
from .forms import LoginForm, RegisterForm, PaymentForm from .forms import LoginForm, RegisterForm, PaymentForm
from utils.stripe_utils import StripeUtils from utils.stripe_utils import StripeUtils
def validate_email(request, validate_slug): def validate_email(request, validate_slug):
validated = CustomUser.validate_url(validate_slug) validated = CustomUser.validate_url(validate_slug)
if validated: if validated:
return render(request, 'templates/validated_email.html',{'msg':True}) return render(request, 'templates/validated_email.html', {'msg': True})
else: 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): class CreditCardView(View):
def _get_context(self, request, time): def _get_context(self, request, time):
@ -42,20 +43,20 @@ class CreditCardView(View):
context['form'] = PaymentForm() context['form'] = PaymentForm()
return context return context
@cache_control(no_cache=True,must_revalidate=True) @cache_control(no_cache=True, must_revalidate=True)
def get(self, request, time=None): def get(self, request, time=None):
context = self._get_context(request, time) context = self._get_context(request, time)
next = request.session.get('next') next = request.session.get('next')
if next == 1 or next ==0: if next == 1 or next == 0:
template = 'templates/creditcard.html' template = 'templates/creditcard.html'
request.session['next'] +=1 request.session['next'] += 1
elif next == 2: 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() 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' template = 'templates/validated.html'
resp = charge.get('response_object') resp = charge.get('response_object')
context['msg'] = resp.get('status',None) context['msg'] = resp.get('status', None)
request.session['next'] = None request.session['next'] = None
return render(request, template, context) return render(request, template, context)
@ -64,11 +65,11 @@ class CreditCardView(View):
stripe_token = request.POST['stripeToken'] stripe_token = request.POST['stripeToken']
if form.is_valid(): if form.is_valid():
ret = form.save(request.user) form.save(request.user)
amount = 35 if time == 'month' else 360 amount = 35 if time == 'month' else 360
request.session['token'] = stripe_token request.session['token'] = stripe_token
request.session['amount'] = amount request.session['amount'] = amount
request.session['next'] +=1 request.session['next'] += 1
return render(request, 'templates/confirm.html', return render(request, 'templates/confirm.html',
context={'name': request.user.name, 'email': request.user.email}) context={'name': request.user.name, 'email': request.user.email})
else: else:
@ -121,13 +122,14 @@ class LoginRegistrationView(View):
class MembershipView(View): class MembershipView(View):
def get(self, request): 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')) member_payed = request.user.creditcards_set.filter(Q(payment_type='month') | Q(payment_type='year'))
if member_payed: if member_payed:
return redirect('/') return redirect('/')
request.session['next'] = 0 request.session['next'] = 0
language = get_language() 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): def logout_glarus(request):
logout(request) logout(request)

View file

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

View file

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

View file

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

View file

@ -6,7 +6,6 @@ from oca.pool import WrongNameError, WrongIdError
from oca.exceptions import OpenNebulaException from oca.exceptions import OpenNebulaException
from django.conf import settings from django.conf import settings
from django.utils.functional import cached_property
from utils.models import CustomUser from utils.models import CustomUser
from .exceptions import KeyExistsError, UserExistsError, UserCredentialError from .exceptions import KeyExistsError, UserExistsError, UserCredentialError
@ -38,6 +37,7 @@ class OpenNebulaManager():
) )
except: except:
pass pass
def _get_client(self, user): def _get_client(self, user):
"""Get a opennebula client object for a CustomUser object """Get a opennebula client object for a CustomUser object
@ -135,7 +135,6 @@ class OpenNebulaManager():
) )
raise ConnectionRefusedError raise ConnectionRefusedError
def _get_or_create_user(self, email, password): def _get_or_create_user(self, email, password):
try: try:
user_pool = self._get_user_pool() user_pool = self._get_user_pool()
@ -209,36 +208,6 @@ class OpenNebulaManager():
except: except:
raise ConnectionRefusedError 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): def create_vm(self, template_id, specs, ssh_key=None):
template = self.get_template(template_id) template = self.get_template(template_id)
@ -287,7 +256,6 @@ class OpenNebulaManager():
image=image, image=image,
image_uname=image_uname) image_uname=image_uname)
if ssh_key: if ssh_key:
vm_specs += """<CONTEXT> vm_specs += """<CONTEXT>
<SSH_PUBLIC_KEY>{ssh}</SSH_PUBLIC_KEY> <SSH_PUBLIC_KEY>{ssh}</SSH_PUBLIC_KEY>
@ -462,7 +430,8 @@ class OpenNebulaManager():
except AttributeError: except AttributeError:
pass pass
self.oneadmin_client.call('user.update', open_user.id, 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 return True
except WrongNameError: except WrongNameError:
raise raise
@ -503,10 +472,11 @@ class OpenNebulaManager():
except AttributeError: except AttributeError:
return False return False
#raise KeyDoesNotExistsError() # raise KeyDoesNotExistsError()
self.oneadmin_client.call('user.update', open_user.id, 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 return True
except WrongNameError: except WrongNameError:
raise raise

View file

@ -1,13 +1,12 @@
import oca
import ipaddress import ipaddress
from rest_framework import serializers from rest_framework import serializers
from oca import OpenNebulaException from oca import OpenNebulaException
from oca.template import VmTemplate
from .models import OpenNebulaManager from .models import OpenNebulaManager
class VirtualMachineTemplateSerializer(serializers.Serializer): class VirtualMachineTemplateSerializer(serializers.Serializer):
"""Serializer to map the virtual machine template instance into JSON format.""" """Serializer to map the virtual machine template instance into JSON format."""
id = serializers.IntegerField(read_only=True) id = serializers.IntegerField(read_only=True)
@ -39,7 +38,6 @@ class VirtualMachineTemplateSerializer(serializers.Serializer):
return obj.name.strip('public-') return obj.name.strip('public-')
class VirtualMachineSerializer(serializers.Serializer): class VirtualMachineSerializer(serializers.Serializer):
"""Serializer to map the virtual machine instance into JSON format.""" """Serializer to map the virtual machine instance into JSON format."""
@ -49,7 +47,6 @@ class VirtualMachineSerializer(serializers.Serializer):
set_memory = serializers.IntegerField(write_only=True, label='Memory') set_memory = serializers.IntegerField(write_only=True, label='Memory')
memory = serializers.SerializerMethodField() memory = serializers.SerializerMethodField()
disk_size = serializers.SerializerMethodField() disk_size = serializers.SerializerMethodField()
ipv4 = serializers.SerializerMethodField() ipv4 = serializers.SerializerMethodField()
ipv6 = serializers.SerializerMethodField() ipv6 = serializers.SerializerMethodField()
@ -77,12 +74,11 @@ class VirtualMachineSerializer(serializers.Serializer):
template_id = validated_data['template']['template_id'] template_id = validated_data['template']['template_id']
specs = { specs = {
'cpu' : cores, 'cpu': cores,
'disk_size' : disk, 'disk_size': disk,
'memory' : memory, 'memory': memory,
} }
try: try:
manager = OpenNebulaManager(email=owner.email, manager = OpenNebulaManager(email=owner.email,
password=owner.password, password=owner.password,
@ -112,6 +108,7 @@ class VirtualMachineSerializer(serializers.Serializer):
for disk in template.disks: for disk in template.disks:
price += int(disk.size)/1024 * 0.6 price += int(disk.size)/1024 * 0.6
return price return price
def get_configuration(self, obj): def get_configuration(self, obj):
template_id = obj.template.template_id template_id = obj.template.template_id
template = OpenNebulaManager().get_template(template_id) template = OpenNebulaManager().get_template(template_id)
@ -131,13 +128,16 @@ class VirtualMachineSerializer(serializers.Serializer):
def get_name(self, obj): def get_name(self, obj):
return obj.name.strip('public-') return obj.name.strip('public-')
def hexstr2int(string): def hexstr2int(string):
return int(string.replace(':', ''), 16) return int(string.replace(':', ''), 16)
FIRST_MAC = hexstr2int('02:00:b3:39:79:4d') FIRST_MAC = hexstr2int('02:00:b3:39:79:4d')
FIRST_V4 = ipaddress.ip_address('185.203.112.2') FIRST_V4 = ipaddress.ip_address('185.203.112.2')
COUNT = 1000 COUNT = 1000
def v4_from_mac(mac): def v4_from_mac(mac):
"""Calculates the IPv4 address from a MAC address. """Calculates the IPv4 address from a MAC address.
@ -146,5 +146,6 @@ def v4_from_mac(mac):
""" """
return FIRST_V4 + (hexstr2int(mac) - FIRST_MAC) return FIRST_V4 + (hexstr2int(mac) - FIRST_MAC)
def is_in_v4_range(mac): def is_in_v4_range(mac):
return FIRST_MAC <= hexstr2int(mac) < FIRST_MAC + 1000 return FIRST_MAC <= hexstr2int(mac) < FIRST_MAC + 1000

View file

@ -1,4 +1,3 @@
import socket
import random import random
import string import string
@ -8,13 +7,12 @@ from .models import OpenNebulaManager
from .serializers import VirtualMachineSerializer from .serializers import VirtualMachineSerializer
from utils.models import CustomUser from utils.models import CustomUser
class OpenNebulaManagerTestCases(TestCase): class OpenNebulaManagerTestCases(TestCase):
"""This class defines the test suite for the opennebula manager model.""" """This class defines the test suite for the opennebula manager model."""
def setUp(self): def setUp(self):
"""Define the test client and other test variables.""" """Define the test client and other test variables."""
self.email = '{}@ungleich.ch'.format(''.join(random.choices(string.ascii_uppercase, k=10))) 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))
@ -28,7 +26,6 @@ class OpenNebulaManagerTestCases(TestCase):
self.manager = OpenNebulaManager() self.manager = OpenNebulaManager()
def test_connect_to_server(self): def test_connect_to_server(self):
"""Test the opennebula manager can connect to a server.""" """Test the opennebula manager can connect to a server."""
try: try:
@ -118,7 +115,6 @@ class OpenNebulaManagerTestCases(TestCase):
self.assertEqual(new_public_key, 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): def test_requires_ssh_key_for_new_vm(self):
"""Test the opennebula manager requires the user to have a ssh key when """Test the opennebula manager requires the user to have a ssh key when
creating a new vm""" creating a new vm"""
@ -129,7 +125,6 @@ class VirtualMachineSerializerTestCase(TestCase):
"""Define the test client and other test variables.""" """Define the test client and other test variables."""
self.manager = OpenNebulaManager(email=None, password=None) self.manager = OpenNebulaManager(email=None, password=None)
def test_serializer_strips_of_public(self): 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-'."""
@ -137,5 +132,3 @@ class VirtualMachineSerializerTestCase(TestCase):
serialized = VirtualMachineSerializer(vm) serialized = VirtualMachineSerializer(vm)
self.assertEqual(serialized.data.get('name'), vm.name.strip('public-')) self.assertEqual(serialized.data.get('name'), vm.name.strip('public-'))
break break

View file

@ -1,19 +1,11 @@
from rest_framework import generics from rest_framework import generics
from rest_framework import permissions from rest_framework import permissions
from django.contrib.auth.mixins import LoginRequiredMixin from .serializers import VirtualMachineSerializer
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 .models import OpenNebulaManager from .models import OpenNebulaManager
from rest_framework.exceptions import APIException from rest_framework.exceptions import APIException
class ServiceUnavailable(APIException): class ServiceUnavailable(APIException):
status_code = 503 status_code = 503
default_detail = 'Service temporarily unavailable, try again later.' default_detail = 'Service temporarily unavailable, try again later.'
@ -41,6 +33,7 @@ class VmCreateView(generics.ListCreateAPIView):
"""Save the post data when creating a new template.""" """Save the post data when creating a new template."""
serializer.save(owner=self.request.user) serializer.save(owner=self.request.user)
class VmDetailsView(generics.RetrieveUpdateDestroyAPIView): class VmDetailsView(generics.RetrieveUpdateDestroyAPIView):
"""This class handles the http GET, PUT and DELETE requests.""" """This class handles the http GET, PUT and DELETE requests."""
permission_classes = (permissions.IsAuthenticated, ) permission_classes = (permissions.IsAuthenticated, )
@ -81,4 +74,3 @@ class VmDetailsView(generics.RetrieveUpdateDestroyAPIView):
manager.delete_vm(instance.id) manager.delete_vm(instance.id)
except ConnectionRefusedError: except ConnectionRefusedError:
raise ServiceUnavailable raise ServiceUnavailable

View file

@ -84,5 +84,4 @@ django-admin-honeypot==1.0.0
coverage==4.3.4 coverage==4.3.4
git+https://github.com/ungleich/python-oca.git#egg=python-oca git+https://github.com/ungleich/python-oca.git#egg=python-oca
djangorestframework 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): class UngleichPageAdmin(PageExtensionAdmin):
pass pass
admin.site.register(UngleichPage, UngleichPageAdmin) 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 django.utils.translation import ugettext_lazy as _
from cms.toolbar_pool import toolbar_pool from cms.toolbar_pool import toolbar_pool
from cms.toolbar_base import CMSToolbar
from .models import UngleichPage from .models import UngleichPage

View file

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

View file

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

View file

@ -1,3 +1,3 @@
from django.test import TestCase # from django.test import TestCase
# Create your tests here. # 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.models import Post
from djangocms_blog.views import PostListView from djangocms_blog.views import PostListView
from djangocms_blog.settings import get_setting from djangocms_blog.settings import get_setting
from django.utils.translation import ugettext_lazy as _
def blog(request): def blog(request):

View file

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

View file

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

View file

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

View file

@ -2,10 +2,9 @@ from django.contrib import messages
from django.views.generic.edit import FormView from django.views.generic.edit import FormView
from django.utils.translation import ugettext_lazy as _ 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.views.generic import View
from django.shortcuts import render,redirect,render_to_response from django.shortcuts import render
from django.http import HttpResponseRedirect
from utils.forms import ContactUsForm from utils.forms import ContactUsForm

View file

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

View file

@ -1,6 +1,5 @@
from django.utils.translation import ugettext as _ from django.utils.translation import ugettext as _
from django.db import models from django.db import models
from django import forms
# http://xml.coverpages.org/country3166.html # http://xml.coverpages.org/country3166.html
COUNTRIES = ( COUNTRIES = (

View file

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

View file

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

View file

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

View file

@ -127,22 +127,10 @@ class StripeUtils(object):
id=id) id=id)
@handleStripeError @handleStripeError
def make_payment(self, user, amount, token): def make_payment(self, customer, amount, token):
charge = self.stripe.Charge.create( charge = self.stripe.Charge.create(
amount=amount, # in cents amount=amount, # in cents
currency=self.CURRENCY, currency=self.CURRENCY,
customer=customer customer=customer
) )
return charge 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)