From d13efd4527686a2bfde67c00f9a758eba2a4250c Mon Sep 17 00:00:00 2001 From: Modulos Date: Fri, 19 May 2017 16:39:56 +0200 Subject: [PATCH 01/19] Get public ip for vms By using kamilas script we can get the ip from a vms mac address. --- opennebula_api/serializers.py | 32 +++++++++++++++++++++++++++++--- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/opennebula_api/serializers.py b/opennebula_api/serializers.py index c8878120..fd339e3c 100644 --- a/opennebula_api/serializers.py +++ b/opennebula_api/serializers.py @@ -1,4 +1,5 @@ import oca +import ipaddress from rest_framework import serializers @@ -81,9 +82,7 @@ class VirtualMachineSerializer(serializers.Serializer): disk_size = serializers.SerializerMethodField() - ip = serializers.CharField(read_only=True, - source='user_template.ungleich_public_ip', - default='-') + ip = serializers.SerializerMethodField() vm_id = serializers.IntegerField(read_only=True, source='id') state = serializers.CharField(read_only=True, source='str_state') price = serializers.SerializerMethodField() @@ -147,3 +146,30 @@ class VirtualMachineSerializer(serializers.Serializer): template_id = obj.template.template_id template = OpenNebulaManager().get_template(template_id) return template.name + + def get_ip(self, obj): + nic = obj.template.nics[0] + if is_in_v4_range(nic.mac): + return str(v4_from_mac(nic.mac)) + else: + return '-' + + + +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 + +def v4_from_mac(mac): + """Calculates the IPv4 address from a MAC address. + + mac: string (the colon-separated representation) + returns: ipaddress.ip_address object with the v4 address + """ + return FIRST_V4 + (hexstr2int(mac) - FIRST_MAC) + +def is_in_v4_range(mac): + return FIRST_MAC <= hexstr2int(mac) < FIRST_MAC + 1000 From 3f198bb4decff20bbd7d2a48fedeb358bdd920ed Mon Sep 17 00:00:00 2001 From: Levi Date: Sun, 21 May 2017 22:01:26 -0500 Subject: [PATCH 02/19] Fixed djangohosting, railshosting and nodehosting page. Fixed payment erro --- hosting/mixins.py | 6 +++++ .../templates/hosting/includes/_pricing.html | 14 +++++------ hosting/views.py | 23 ++++++++++++------- opennebula_api/models.py | 1 + opennebula_api/serializers.py | 8 ++++++- 5 files changed, 36 insertions(+), 16 deletions(-) diff --git a/hosting/mixins.py b/hosting/mixins.py index c8539eee..666cbcbe 100644 --- a/hosting/mixins.py +++ b/hosting/mixins.py @@ -4,15 +4,21 @@ from django.core.urlresolvers import reverse from opennebula_api.serializers import VirtualMachineTemplateSerializer from opennebula_api.models import OpenNebulaManager +from .models import HostingPlan + class ProcessVMSelectionMixin(object): def post(self, request, *args, **kwargs): template_id = int(request.POST.get('vm_template_id')) + configuration_id = int(request.POST.get('configuration')) template = OpenNebulaManager().get_template(template_id) data = VirtualMachineTemplateSerializer(template).data + configuration = HostingPlan.objects.get(id=configuration_id) + request.session['template'] = data + request.session['specs'] = configuration.serialize() if not request.user.is_authenticated(): request.session['next'] = reverse('hosting:payment') diff --git a/hosting/templates/hosting/includes/_pricing.html b/hosting/templates/hosting/includes/_pricing.html index c1b2fa11..c5cb2bf1 100644 --- a/hosting/templates/hosting/includes/_pricing.html +++ b/hosting/templates/hosting/includes/_pricing.html @@ -18,13 +18,13 @@
- {% for vm in vm_types %} + {% for vm in configuration_options %}
{% csrf_token %} - + @@ -53,14 +53,14 @@
- +
  • {{vm.price|floatformat}} CHF

    diff --git a/hosting/views.py b/hosting/views.py index 10116079..8ab77a2a 100644 --- a/hosting/views.py +++ b/hosting/views.py @@ -47,6 +47,7 @@ class DjangoHostingView(ProcessVMSelectionMixin, View): HOSTING = 'django' templates = OpenNebulaManager().get_templates() data = VirtualMachineTemplateSerializer(templates, many=True).data + configuration_options = HostingPlan.get_serialized_configs() # configuration_detail = dict(VirtualMachinePlan.VM_CONFIGURATION).get(HOSTING) context = { @@ -57,8 +58,8 @@ class DjangoHostingView(ProcessVMSelectionMixin, View): 'google_analytics': "UA-62285904-6", 'vm_types': data, 'email': "info@django-hosting.ch", - # 'vm_types': VirtualMachineType.get_serialized_vm_types(), - # 'configuration_options': dict(VirtualMachinePlan.VM_CONFIGURATION) + 'configuration_options': configuration_options, + 'templates': templates, } return context @@ -77,7 +78,7 @@ class RailsHostingView(ProcessVMSelectionMixin, View): HOSTING = 'rails' templates = OpenNebulaManager().get_templates() - data = VirtualMachineTemplateSerializer(templates, many=True).data + configuration_options = HostingPlan.get_serialized_configs() context = { 'hosting': HOSTING, @@ -85,7 +86,8 @@ class RailsHostingView(ProcessVMSelectionMixin, View): 'domain': "rails-hosting.ch", 'google_analytics': "UA-62285904-5", 'email': "info@rails-hosting.ch", - 'vm_types': data, + 'configuration_options': configuration_options, + 'templates': templates, } return context @@ -102,7 +104,7 @@ class NodeJSHostingView(ProcessVMSelectionMixin, View): HOSTING = 'nodejs' # configuration_detail = dict(VirtualMachinePlan.VM_CONFIGURATION).get(HOSTING) templates = OpenNebulaManager().get_templates() - data = VirtualMachineTemplateSerializer(templates, many=True).data + configuration_options = HostingPlan.get_serialized_configs() context = { 'hosting': HOSTING, @@ -111,7 +113,9 @@ class NodeJSHostingView(ProcessVMSelectionMixin, View): 'domain': "node-hosting.ch", 'google_analytics': "UA-62285904-7", 'email': "info@node-hosting.ch", - 'vm_types': data, + 'templates': templates, + 'configuration_options': configuration_options, + } return context @@ -128,12 +132,15 @@ class HostingPricingView(ProcessVMSelectionMixin, View): def get_context_data(self, **kwargs): # configuration_options = dict(VirtualMachinePlan.VM_CONFIGURATION) templates = OpenNebulaManager().get_templates() - data = VirtualMachineTemplateSerializer(templates, many=True).data + configuration_options = HostingPlan.get_serialized_configs() context = { # 'configuration_options': configuration_options, 'email': "info@django-hosting.ch", - 'vm_types': data, + 'templates': templates, + 'configuration_options': configuration_options, + + } return context diff --git a/opennebula_api/models.py b/opennebula_api/models.py index bf5b036e..1745fb49 100644 --- a/opennebula_api/models.py +++ b/opennebula_api/models.py @@ -82,6 +82,7 @@ class OpenNebulaManager(): try: vm_pool = oca.VirtualMachinePool(self.client) vm_pool.info() + return vm_pool except AttributeError: logger.info('Could not connect via client, using oneadmin instead') try: diff --git a/opennebula_api/serializers.py b/opennebula_api/serializers.py index c8878120..c72af4e3 100644 --- a/opennebula_api/serializers.py +++ b/opennebula_api/serializers.py @@ -12,7 +12,7 @@ class VirtualMachineTemplateSerializer(serializers.Serializer): id = serializers.IntegerField(read_only=True) set_name = serializers.CharField(read_only=True, label='Name') name = serializers.SerializerMethodField() - cores = serializers.IntegerField(source='template.vcpu') + cores = serializers.SerializerMethodField() disk = serializers.IntegerField(write_only=True) disk_size = serializers.SerializerMethodField() set_memory = serializers.IntegerField(write_only=True, label='Memory') @@ -41,6 +41,12 @@ class VirtualMachineTemplateSerializer(serializers.Serializer): return manager.get_template(template_id=opennebula_id) + def get_cores(self, obj): + if hasattr(obj.template, 'vcpu'): + return obj.template.vcpu + + return '' + def get_disk_size(self, obj): template = obj.template disk_size = 0 From 02a2ac31c620010c376611d1c979f46f73eb34db Mon Sep 17 00:00:00 2001 From: Levi Date: Sun, 21 May 2017 22:35:43 -0500 Subject: [PATCH 03/19] added next url to ssh create key view --- hosting/templates/hosting/virtual_machine_key.html | 4 ++++ hosting/views.py | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/hosting/templates/hosting/virtual_machine_key.html b/hosting/templates/hosting/virtual_machine_key.html index 0ea4abe5..e152948d 100644 --- a/hosting/templates/hosting/virtual_machine_key.html +++ b/hosting/templates/hosting/virtual_machine_key.html @@ -113,6 +113,10 @@ {%endif%} +{% if next_url %} + window.location.href = '{{next_url}}' +{% endif %} + {%endblock%} diff --git a/hosting/views.py b/hosting/views.py index 8ab77a2a..ef1a9226 100644 --- a/hosting/views.py +++ b/hosting/views.py @@ -287,7 +287,6 @@ class GenerateVMSSHKeysView(LoginRequiredMixin, FormView): form_class = UserHostingKeyForm model = UserHostingKey template_name = 'hosting/virtual_machine_key.html' - success_url = reverse_lazy('hosting:orders') login_url = reverse_lazy('hosting:login') context_object_name = "virtual_machine" @@ -324,7 +323,8 @@ class GenerateVMSSHKeysView(LoginRequiredMixin, FormView): context.update({ 'private_key': form.cleaned_data.get('private_key'), 'key_name': form.cleaned_data.get('name'), - 'form': UserHostingKeyForm(request=self.request) + 'form': UserHostingKeyForm(request=self.request), + 'next_url': self.request.session.get('next', None) }) # return HttpResponseRedirect(reverse('hosting:key_pair')) From 65c6f1342beae80a637d0624296d64ad308f1d1a Mon Sep 17 00:00:00 2001 From: Levi Date: Sun, 21 May 2017 22:38:12 -0500 Subject: [PATCH 04/19] added next url to ssh create key view --- hosting/templates/hosting/virtual_machine_key.html | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/hosting/templates/hosting/virtual_machine_key.html b/hosting/templates/hosting/virtual_machine_key.html index e152948d..4eaaf10f 100644 --- a/hosting/templates/hosting/virtual_machine_key.html +++ b/hosting/templates/hosting/virtual_machine_key.html @@ -114,7 +114,9 @@ {% if next_url %} - window.location.href = '{{next_url}}' + {% endif %} {%endblock%} From 05bf8db38ac5fb75c29ae7e8225693bd8fe8a9b7 Mon Sep 17 00:00:00 2001 From: Levi Date: Sun, 21 May 2017 22:39:47 -0500 Subject: [PATCH 05/19] added next url to ssh create key view --- hosting/views.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/hosting/views.py b/hosting/views.py index ef1a9226..15306e13 100644 --- a/hosting/views.py +++ b/hosting/views.py @@ -391,6 +391,8 @@ class PaymentVMView(LoginRequiredMixin, FormView): return context def get(self, request, *args, **kwargs): + if 'next' in request.session: + del request.session['next'] try: UserHostingKey.objects.get( From 34d596f2baa92a6834299cca36544a161adfb838 Mon Sep 17 00:00:00 2001 From: Levi Date: Sun, 21 May 2017 22:46:31 -0500 Subject: [PATCH 06/19] added next url to ssh create key view --- hosting/templates/hosting/virtual_machine_key.html | 2 +- hosting/urls.py | 2 +- hosting/views.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/hosting/templates/hosting/virtual_machine_key.html b/hosting/templates/hosting/virtual_machine_key.html index 4eaaf10f..157ceea8 100644 --- a/hosting/templates/hosting/virtual_machine_key.html +++ b/hosting/templates/hosting/virtual_machine_key.html @@ -115,7 +115,7 @@ {% if next_url %} {% endif %} diff --git a/hosting/urls.py b/hosting/urls.py index abfb8d5f..f09d3aa7 100644 --- a/hosting/urls.py +++ b/hosting/urls.py @@ -19,7 +19,7 @@ urlpatterns = [ url(r'bills/?$', HostingBillListView.as_view(), name='bills'), url(r'bills/(?P\d+)/?$', HostingBillDetailView.as_view(), name='bills'), url(r'cancel_order/(?P\d+)/?$', OrdersHostingDeleteView.as_view(), name='delete_order'), - url(r'create-virtual-machine/?$', CreateVirtualMachinesView.as_view(), name='create-virtual-machine'), + url(r'create-virtual-machine/?$', CreateVirtualMachinesView.as_view(), name='create_virtual_machine'), url(r'my-virtual-machines/?$', VirtualMachinesPlanListView.as_view(), name='virtual_machines'), url(r'my-virtual-machines/(?P\d+)/?$', VirtualMachineView.as_view(), name='virtual_machines'), diff --git a/hosting/views.py b/hosting/views.py index 15306e13..b8b04b7d 100644 --- a/hosting/views.py +++ b/hosting/views.py @@ -324,7 +324,7 @@ class GenerateVMSSHKeysView(LoginRequiredMixin, FormView): 'private_key': form.cleaned_data.get('private_key'), 'key_name': form.cleaned_data.get('name'), 'form': UserHostingKeyForm(request=self.request), - 'next_url': self.request.session.get('next', None) + 'next_url': reverse('hosting:create_virtual_machine') }) # return HttpResponseRedirect(reverse('hosting:key_pair')) From cb33e6a750b684bce43e01b98c2fce1aee350976 Mon Sep 17 00:00:00 2001 From: Levi Date: Sun, 21 May 2017 22:48:10 -0500 Subject: [PATCH 07/19] added price to create vm view --- hosting/templates/hosting/create_virtual_machine.html | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/hosting/templates/hosting/create_virtual_machine.html b/hosting/templates/hosting/create_virtual_machine.html index af618740..b2984a58 100644 --- a/hosting/templates/hosting/create_virtual_machine.html +++ b/hosting/templates/hosting/create_virtual_machine.html @@ -35,7 +35,8 @@ {% endfor %} From d71c3093e8a00e029a1ee25fb9fc683292125eb0 Mon Sep 17 00:00:00 2001 From: Levi Date: Sun, 21 May 2017 22:49:56 -0500 Subject: [PATCH 08/19] added price to create vm view --- hosting/templates/hosting/create_virtual_machine.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hosting/templates/hosting/create_virtual_machine.html b/hosting/templates/hosting/create_virtual_machine.html index b2984a58..ac6ae1d1 100644 --- a/hosting/templates/hosting/create_virtual_machine.html +++ b/hosting/templates/hosting/create_virtual_machine.html @@ -36,7 +36,7 @@ CORE: {{config.cpu|floatformat}}, RAM: {{config.memory|floatformat}} GiB, SSD: {{config.disk_size|floatformat}} GiB, - PRICE: {{config.price|floatformat}} + PRICE: {{config.price|floatformat}} CHF {% endfor %} From e782290eebab5c5797844eefce05eabe3330f17c Mon Sep 17 00:00:00 2001 From: modulos Date: Mon, 22 May 2017 12:53:01 +0200 Subject: [PATCH 09/19] Fix NoReverseMatch for create-virtual-machine --- hosting/templates/hosting/virtual_machines.html | 2 +- hosting/urls.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/hosting/templates/hosting/virtual_machines.html b/hosting/templates/hosting/virtual_machines.html index e7dee999..650f68ac 100644 --- a/hosting/templates/hosting/virtual_machines.html +++ b/hosting/templates/hosting/virtual_machines.html @@ -19,7 +19,7 @@
  • {% if not error %}

    - {% trans "Create VM"%} + {% trans "Create VM"%}


    diff --git a/hosting/urls.py b/hosting/urls.py index f09d3aa7..d5923cf4 100644 --- a/hosting/urls.py +++ b/hosting/urls.py @@ -19,7 +19,7 @@ urlpatterns = [ url(r'bills/?$', HostingBillListView.as_view(), name='bills'), url(r'bills/(?P\d+)/?$', HostingBillDetailView.as_view(), name='bills'), url(r'cancel_order/(?P\d+)/?$', OrdersHostingDeleteView.as_view(), name='delete_order'), - url(r'create-virtual-machine/?$', CreateVirtualMachinesView.as_view(), name='create_virtual_machine'), + url(r'create_virtual_machine/?$', CreateVirtualMachinesView.as_view(), name='create_virtual_machine'), url(r'my-virtual-machines/?$', VirtualMachinesPlanListView.as_view(), name='virtual_machines'), url(r'my-virtual-machines/(?P\d+)/?$', VirtualMachineView.as_view(), name='virtual_machines'), From ccb583b20d731b965a9082b5f6ee6547d545d7df Mon Sep 17 00:00:00 2001 From: modulos Date: Mon, 22 May 2017 13:28:14 +0200 Subject: [PATCH 10/19] Add vm-ipv6-nat64-ipv4 network name check --- opennebula_api/serializers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opennebula_api/serializers.py b/opennebula_api/serializers.py index 3d04d61f..622d89f6 100644 --- a/opennebula_api/serializers.py +++ b/opennebula_api/serializers.py @@ -155,7 +155,7 @@ class VirtualMachineSerializer(serializers.Serializer): def get_ip(self, obj): nic = obj.template.nics[0] - if is_in_v4_range(nic.mac): + if 'vm-ipv6-nat64-ipv4' is in nic.network and is_in_v4_range(nic.mac): return str(v4_from_mac(nic.mac)) else: return '-' From 920e7669dc5e9303936d3f4d073444ff1f4e1aac Mon Sep 17 00:00:00 2001 From: modulos Date: Mon, 22 May 2017 18:03:33 +0200 Subject: [PATCH 11/19] Show modal after beta access signup The beta access form is now in it's own html page. this makes it easier to work with djangos form validation with reloading the whole page. --- datacenterlight/forms.py | 2 +- .../datacenterlight/css/landing-page.css | 2 +- .../static/datacenterlight/js/form.js | 12 +++++ .../datacenterlight/beta_access.html | 27 ++++++++++ .../datacenterlight/beta_success.html | 47 ++++++++++++++++ .../templates/datacenterlight/index.html | 54 ++++--------------- datacenterlight/urls.py | 4 +- datacenterlight/views.py | 38 +++++++++++++ 8 files changed, 140 insertions(+), 46 deletions(-) create mode 100644 datacenterlight/static/datacenterlight/js/form.js create mode 100644 datacenterlight/templates/datacenterlight/beta_access.html create mode 100644 datacenterlight/templates/datacenterlight/beta_success.html diff --git a/datacenterlight/forms.py b/datacenterlight/forms.py index 8371ebfd..90340e8d 100644 --- a/datacenterlight/forms.py +++ b/datacenterlight/forms.py @@ -7,7 +7,7 @@ class BetaAccessForm(forms.ModelForm): email = forms.CharField(widget=forms.EmailInput()) class Meta: - fields = ['email'] + fields = ['name', 'email'] model = BetaAccess diff --git a/datacenterlight/static/datacenterlight/css/landing-page.css b/datacenterlight/static/datacenterlight/css/landing-page.css index 07f03f97..da6f279e 100755 --- a/datacenterlight/static/datacenterlight/css/landing-page.css +++ b/datacenterlight/static/datacenterlight/css/landing-page.css @@ -672,4 +672,4 @@ a#forgotpassword { } .form-300{ width: 300px; -} \ No newline at end of file +} diff --git a/datacenterlight/static/datacenterlight/js/form.js b/datacenterlight/static/datacenterlight/js/form.js new file mode 100644 index 00000000..0e91b172 --- /dev/null +++ b/datacenterlight/static/datacenterlight/js/form.js @@ -0,0 +1,12 @@ +/*! + * jQuery Form Plugin + * version: 4.2.1 + * Requires jQuery v1.7 or later + * Copyright 2017 Kevin Morris + * Copyright 2006 M. Alsup + * Project repository: https://github.com/jquery-form/form + * Dual licensed under the MIT and LGPLv3 licenses. + * https://github.com/jquery-form/form#license + */ +!function(a){"function"==typeof define&&define.amd?define(["jquery"],a):"object"==typeof module&&module.exports?module.exports=function(b,c){return void 0===c&&(c="undefined"!=typeof window?require("jquery"):require("jquery")(b)),a(c),c}:a(jQuery)}(function(a){"use strict";function b(b){var c=b.data;b.isDefaultPrevented()||(b.preventDefault(),a(b.target).closest("form").ajaxSubmit(c))}function c(b){var c=b.target,d=a(c);if(!d.is("[type=submit],[type=image]")){var e=d.closest("[type=submit]");if(0===e.length)return;c=e[0]}var f=c.form;if(f.clk=c,"image"===c.type)if(void 0!==b.offsetX)f.clk_x=b.offsetX,f.clk_y=b.offsetY;else if("function"==typeof a.fn.offset){var g=d.offset();f.clk_x=b.pageX-g.left,f.clk_y=b.pageY-g.top}else f.clk_x=b.pageX-c.offsetLeft,f.clk_y=b.pageY-c.offsetTop;setTimeout(function(){f.clk=f.clk_x=f.clk_y=null},100)}function d(){if(a.fn.ajaxSubmit.debug){var b="[jquery.form] "+Array.prototype.join.call(arguments,"");window.console&&window.console.log?window.console.log(b):window.opera&&window.opera.postError&&window.opera.postError(b)}}var e={};e.fileapi=void 0!==a('').get(0).files,e.formdata=void 0!==window.FormData;var f=!!a.fn.prop;a.fn.attr2=function(){if(!f)return this.attr.apply(this,arguments);var a=this.prop.apply(this,arguments);return a&&a.jquery||"string"==typeof a?a:this.attr.apply(this,arguments)},a.fn.ajaxSubmit=function(b,c,g,h){function i(c){var d,e,f=a.param(c,b.traditional).split("&"),g=f.length,h=[];for(d=0;d',z).val(k.extraData[j].value).appendTo(x)[0]):i.push(a('',z).val(k.extraData[j]).appendTo(x)[0]));k.iframeTarget||p.appendTo(A),q.attachEvent?q.attachEvent("onload",h):q.addEventListener("load",h,!1),setTimeout(b,15);try{x.submit()}catch(a){var m=document.createElement("form").submit;m.apply(x)}}finally{x.setAttribute("action",f),x.setAttribute("enctype",g),c?x.setAttribute("target",c):o.removeAttr("target"),a(i).remove()}}function h(b){if(!r.aborted&&!F){if(E=e(q),E||(d("cannot access response document"),b=2),1===b&&r)return r.abort("timeout"),void y.reject(r,"timeout");if(2===b&&r)return r.abort("server abort"),void y.reject(r,"error","server abort");if(E&&E.location.href!==k.iframeSrc||v){q.detachEvent?q.detachEvent("onload",h):q.removeEventListener("load",h,!1);var c,f="success";try{if(v)throw"timeout";var g="xml"===k.dataType||E.XMLDocument||a.isXMLDoc(E);if(d("isXml="+g),!g&&window.opera&&(null===E.body||!E.body.innerHTML)&&--G)return d("requeing onLoad callback, DOM not available"),void setTimeout(h,250);var i=E.body?E.body:E.documentElement;r.responseText=i?i.innerHTML:null,r.responseXML=E.XMLDocument?E.XMLDocument:E,g&&(k.dataType="xml"),r.getResponseHeader=function(a){return{"content-type":k.dataType}[a.toLowerCase()]},i&&(r.status=Number(i.getAttribute("status"))||r.status,r.statusText=i.getAttribute("statusText")||r.statusText);var j=(k.dataType||"").toLowerCase(),l=/(json|script|text)/.test(j);if(l||k.textarea){var n=E.getElementsByTagName("textarea")[0];if(n)r.responseText=n.value,r.status=Number(n.getAttribute("status"))||r.status,r.statusText=n.getAttribute("statusText")||r.statusText;else if(l){var o=E.getElementsByTagName("pre")[0],s=E.getElementsByTagName("body")[0];o?r.responseText=o.textContent?o.textContent:o.innerText:s&&(r.responseText=s.textContent?s.textContent:s.innerText)}}else"xml"===j&&!r.responseXML&&r.responseText&&(r.responseXML=H(r.responseText));try{D=J(r,j,k)}catch(a){f="parsererror",r.error=c=a||f}}catch(a){d("error caught: ",a),f="error",r.error=c=a||f}r.aborted&&(d("upload aborted"),f=null),r.status&&(f=r.status>=200&&r.status<300||304===r.status?"success":"error"),"success"===f?(k.success&&k.success.call(k.context,D,"success",r),y.resolve(r.responseText,"success",r),m&&a.event.trigger("ajaxSuccess",[r,k])):f&&(void 0===c&&(c=r.statusText),k.error&&k.error.call(k.context,r,f,c),y.reject(r,"error",c),m&&a.event.trigger("ajaxError",[r,k,c])),m&&a.event.trigger("ajaxComplete",[r,k]),m&&!--a.active&&a.event.trigger("ajaxStop"),k.complete&&k.complete.call(k.context,r,f),F=!0,k.timeout&&clearTimeout(w),setTimeout(function(){k.iframeTarget?p.attr("src",k.iframeSrc):p.remove(),r.responseXML=null},100)}}}var i,j,k,m,n,p,q,r,t,u,v,w,x=o[0],y=a.Deferred();if(y.abort=function(a){r.abort(a)},c)for(j=0;j',z),p.css({position:"absolute",top:"-1000px",left:"-1000px"})),q=p[0],r={aborted:0,responseText:null,responseXML:null,status:0,statusText:"n/a",getAllResponseHeaders:function(){},getResponseHeader:function(){},setRequestHeader:function(){},abort:function(b){var c="timeout"===b?"timeout":"aborted";d("aborting upload... "+c),this.aborted=1;try{q.contentWindow.document.execCommand&&q.contentWindow.document.execCommand("Stop")}catch(a){}p.attr("src",k.iframeSrc),r.error=c,k.error&&k.error.call(k.context,r,c,b),m&&a.event.trigger("ajaxError",[r,k,c]),k.complete&&k.complete.call(k.context,r,c)}},m=k.global,m&&0==a.active++&&a.event.trigger("ajaxStart"),m&&a.event.trigger("ajaxSend",[r,k]),k.beforeSend&&k.beforeSend.call(k.context,r,k)===!1)return k.global&&a.active--,y.reject(),y;if(r.aborted)return y.reject(),y;(t=x.clk)&&(u=t.name)&&!t.disabled&&(k.extraData=k.extraData||{},k.extraData[u]=t.value,"image"===t.type&&(k.extraData[u+".x"]=x.clk_x,k.extraData[u+".y"]=x.clk_y));var B=a("meta[name=csrf-token]").attr("content"),C=a("meta[name=csrf-param]").attr("content");C&&B&&(k.extraData=k.extraData||{},k.extraData[C]=B),k.forceSync?g():setTimeout(g,10);var D,E,F,G=50,H=a.parseXML||function(a,b){return window.ActiveXObject?(b=new ActiveXObject("Microsoft.XMLDOM"),b.async="false",b.loadXML(a)):b=(new DOMParser).parseFromString(a,"text/xml"),b&&b.documentElement&&"parsererror"!==b.documentElement.nodeName?b:null},I=a.parseJSON||function(a){return window.eval("("+a+")")},J=function(b,c,d){var e=b.getResponseHeader("content-type")||"",f=("xml"===c||!c)&&e.indexOf("xml")>=0,g=f?b.responseXML:b.responseText;return f&&"parsererror"===g.documentElement.nodeName&&a.error&&a.error("parsererror"),d&&d.dataFilter&&(g=d.dataFilter(g,c)),"string"==typeof g&&(("json"===c||!c)&&e.indexOf("json")>=0?g=I(g):("script"===c||!c)&&e.indexOf("javascript")>=0&&a.globalEval(g)),g};return y}if(!this.length)return d("ajaxSubmit: skipping submit process - no element selected"),this;var l,m,n,o=this;"function"==typeof b?b={success:b}:"string"==typeof b||b===!1&&arguments.length>0?(b={url:b,data:c,dataType:g},"function"==typeof h&&(b.success=h)):void 0===b&&(b={}),l=b.method||b.type||this.attr2("method"),m=b.url||this.attr2("action"),n="string"==typeof m?a.trim(m):"",n=n||window.location.href||"",n&&(n=(n.match(/^([^#]+)/)||[])[1]),b=a.extend(!0,{url:n,success:a.ajaxSettings.success,type:l||a.ajaxSettings.type,iframeSrc:/^https/i.test(window.location.href||"")?"javascript:false":"about:blank"},b);var p={};if(this.trigger("form-pre-serialize",[this,b,p]),p.veto)return d("ajaxSubmit: submit vetoed via form-pre-serialize trigger"),this;if(b.beforeSerialize&&b.beforeSerialize(this,b)===!1)return d("ajaxSubmit: submit aborted via beforeSerialize callback"),this;var q=b.traditional;void 0===q&&(q=a.ajaxSettings.traditional);var r,s=[],t=this.formToArray(b.semantic,s,b.filtering);if(b.data){var u=a.isFunction(b.data)?b.data(t):b.data;b.extraData=u,r=a.param(u,q)}if(b.beforeSubmit&&b.beforeSubmit(t,this,b)===!1)return d("ajaxSubmit: submit aborted via beforeSubmit callback"),this;if(this.trigger("form-submit-validate",[t,this,b,p]),p.veto)return d("ajaxSubmit: submit vetoed via form-submit-validate trigger"),this;var v=a.param(t,q);r&&(v=v?v+"&"+r:r),"GET"===b.type.toUpperCase()?(b.url+=(b.url.indexOf("?")>=0?"&":"?")+v,b.data=null):b.data=v;var w=[];if(b.resetForm&&w.push(function(){o.resetForm()}),b.clearForm&&w.push(function(){o.clearForm(b.includeHidden)}),!b.dataType&&b.target){var x=b.success||function(){};w.push(function(c,d,e){var f=arguments,g=b.replaceTarget?"replaceWith":"html";a(b.target)[g](c).each(function(){x.apply(this,f)})})}else b.success&&(a.isArray(b.success)?a.merge(w,b.success):w.push(b.success));if(b.success=function(a,c,d){for(var e=b.context||this,f=0,g=w.length;f0,C="multipart/form-data",D=o.attr("enctype")===C||o.attr("encoding")===C,E=e.fileapi&&e.formdata;d("fileAPI :"+E);var F,G=(B||D)&&!E;b.iframe!==!1&&(b.iframe||G)?b.closeKeepAlive?a.get(b.closeKeepAlive,function(){F=k(t)}):F=k(t):F=(B||D)&&E?j(t):a.ajax(b),o.removeData("jqxhr").data("jqxhr",F);for(var H=0;H0)&&(e={url:e,data:f,dataType:g},"function"==typeof h&&(e.success=h)),e=e||{},e.delegation=e.delegation&&a.isFunction(a.fn.on),!e.delegation&&0===this.length){var i={s:this.selector,c:this.context};return!a.isReady&&i.s?(d("DOM not ready, queuing ajaxForm"),a(function(){a(i.s,i.c).ajaxForm(e)}),this):(d("terminating; zero elements found by selector"+(a.isReady?"":" (DOM not ready)")),this)}return e.delegation?(a(document).off("submit.form-plugin",this.selector,b).off("click.form-plugin",this.selector,c).on("submit.form-plugin",this.selector,e,b).on("click.form-plugin",this.selector,e,c),this):this.ajaxFormUnbind().on("submit.form-plugin",e,b).on("click.form-plugin",e,c)},a.fn.ajaxFormUnbind=function(){return this.off("submit.form-plugin click.form-plugin")},a.fn.formToArray=function(b,c,d){var f=[];if(0===this.length)return f;var g,h=this[0],i=this.attr("id"),j=b||void 0===h.elements?h.getElementsByTagName("*"):h.elements;if(j&&(j=a.makeArray(j)),i&&(b||/(Edge|Trident)\//.test(navigator.userAgent))&&(g=a(':input[form="'+i+'"]').get(),g.length&&(j=(j||[]).concat(g))),!j||!j.length)return f;a.isFunction(d)&&(j=a.map(j,d));var k,l,m,n,o,p,q;for(k=0,p=j.length;k + {% csrf_token %} + {{ form.non_field_errors }} +
    + {% for message in messages %} + {{ message }} + {% endfor %} +
    +
    +
    + + {{ form.name.errors|striptags}} +
    +
    + + {{ form.email.errors|striptags}} +
    +
    + + + diff --git a/datacenterlight/templates/datacenterlight/beta_success.html b/datacenterlight/templates/datacenterlight/beta_success.html new file mode 100644 index 00000000..ffcfcce9 --- /dev/null +++ b/datacenterlight/templates/datacenterlight/beta_success.html @@ -0,0 +1,47 @@ +{% load i18n %} + + + + diff --git a/datacenterlight/templates/datacenterlight/index.html b/datacenterlight/templates/datacenterlight/index.html index 953ce2c6..848d0685 100755 --- a/datacenterlight/templates/datacenterlight/index.html +++ b/datacenterlight/templates/datacenterlight/index.html @@ -261,43 +261,9 @@
    -
    -
    - {% csrf_token %} - {{ form.non_field_errors }} - {{ form.email.errors|striptags}} -
    - {% for message in messages %} - {{ message }} - {% endfor %} -
    -
    -
    - -
    -
    - -
    -
    - -
    -
    - + +
    +
    @@ -389,12 +355,12 @@ windowPadding: 10, }); - var hash = window.location.hash.substr(1); - console.log(hash); - if (hash == 'requestform'){ - $('#reques-success-message').modal('show'); - } - + $.ajax({ + url: "{% url 'datacenterlight:beta_access' %}", + context: document.body + }).done(function(response) { + $('#beta_access_form').html(response); + }); }; @@ -403,6 +369,8 @@ + + diff --git a/datacenterlight/urls.py b/datacenterlight/urls.py index 58aa3de9..bd88b5ba 100644 --- a/datacenterlight/urls.py +++ b/datacenterlight/urls.py @@ -1,10 +1,12 @@ from django.conf.urls import url -from .views import IndexView, BetaProgramView, LandingProgramView +from .views import IndexView, BetaProgramView, LandingProgramView, \ + BetaAccessView urlpatterns = [ url(r'^/?$', IndexView.as_view(), name='index'), url(r'^/beta-program/?$', BetaProgramView.as_view(), name='beta'), url(r'^/landing/?$', LandingProgramView.as_view(), name='landing'), + url(r'^/beta_access?$', BetaAccessView.as_view(), name='beta_access'), ] diff --git a/datacenterlight/views.py b/datacenterlight/views.py index ce50bd5a..c38e1119 100644 --- a/datacenterlight/views.py +++ b/datacenterlight/views.py @@ -5,6 +5,7 @@ from .models import BetaAccess, BetaAccessVMType, BetaAccessVM from django.contrib import messages from django.core.urlresolvers import reverse_lazy, reverse from utils.mailer import BaseEmail +from django.shortcuts import render from opennebula_api.models import OpenNebulaManager from opennebula_api.serializers import VirtualMachineTemplateSerializer @@ -12,6 +13,43 @@ from opennebula_api.serializers import VirtualMachineTemplateSerializer class LandingProgramView(TemplateView): template_name = "datacenterlight/landing.html" +class BetaAccessView(FormView): + template_name = "datacenterlight/beta_access.html" + form_class = BetaAccessForm + success_message = "Thank you, we will contact you as soon as possible" + + def form_valid(self, form): + + context = { + 'base_url': "{0}://{1}".format(self.request.scheme, self.request.get_host()) + } + + email_data = { + 'subject': 'DatacenterLight Beta Access Request', + 'to': form.cleaned_data.get('email'), + 'context': context, + 'template_name': 'request_access_confirmation', + 'template_path': 'datacenterlight/emails/' + } + email = BaseEmail(**email_data) + email.send() + + context.update({ + 'email': form.cleaned_data.get('email') + }) + + email_data = { + 'subject': 'DatacenterLight Beta Access Request', + 'to': 'info@ungleich.ch', + 'context': context, + 'template_name': 'request_access_notification', + 'template_path': 'datacenterlight/emails/' + } + email = BaseEmail(**email_data) + email.send() + + 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" From 88731d63714a0024c8afec85e9175c113317e1d0 Mon Sep 17 00:00:00 2001 From: modulos Date: Mon, 22 May 2017 18:25:56 +0200 Subject: [PATCH 12/19] Change buy now to order now and add link --- datacenterlight/templates/datacenterlight/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/datacenterlight/templates/datacenterlight/index.html b/datacenterlight/templates/datacenterlight/index.html index 953ce2c6..a642a667 100755 --- a/datacenterlight/templates/datacenterlight/index.html +++ b/datacenterlight/templates/datacenterlight/index.html @@ -243,7 +243,7 @@

    {% trans "15 GiB storage(SSD)" %}

    - {% trans "Buy Now!" %} + {% trans "Order Now!" %} From 021a8e784dce1964ebaddcb5059a6474172f6021 Mon Sep 17 00:00:00 2001 From: modulos Date: Tue, 23 May 2017 10:36:57 +0200 Subject: [PATCH 13/19] Remove 'public-' prefix --- opennebula_api/serializers.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/opennebula_api/serializers.py b/opennebula_api/serializers.py index c72af4e3..577dec28 100644 --- a/opennebula_api/serializers.py +++ b/opennebula_api/serializers.py @@ -73,8 +73,7 @@ class VirtualMachineTemplateSerializer(serializers.Serializer): return int(obj.template.memory)/1024 def get_name(self, obj): - # TODO: Filter public- away - return obj.name + return obj.name.strip('public-') class VirtualMachineSerializer(serializers.Serializer): """Serializer to map the virtual machine instance into JSON format.""" From 4c8a4d0be8cd66f3b7ac588d02ecc9c1b047fcc5 Mon Sep 17 00:00:00 2001 From: modulos Date: Tue, 23 May 2017 11:17:38 +0200 Subject: [PATCH 14/19] Typo --- opennebula_api/serializers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opennebula_api/serializers.py b/opennebula_api/serializers.py index 622d89f6..d762587f 100644 --- a/opennebula_api/serializers.py +++ b/opennebula_api/serializers.py @@ -155,7 +155,7 @@ class VirtualMachineSerializer(serializers.Serializer): def get_ip(self, obj): nic = obj.template.nics[0] - if 'vm-ipv6-nat64-ipv4' is in nic.network and is_in_v4_range(nic.mac): + if 'vm-ipv6-nat64-ipv4' in nic.network and is_in_v4_range(nic.mac): return str(v4_from_mac(nic.mac)) else: return '-' From adf9b77e4e1db305dd17cd3ef11a8741b72f9735 Mon Sep 17 00:00:00 2001 From: modulos Date: Tue, 23 May 2017 11:30:10 +0200 Subject: [PATCH 15/19] Show ipv6 address --- .../templates/hosting/virtual_machine_detail.html | 12 +++++++++--- opennebula_api/serializers.py | 8 ++++++-- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/hosting/templates/hosting/virtual_machine_detail.html b/hosting/templates/hosting/virtual_machine_detail.html index 0b17878d..188afd8e 100644 --- a/hosting/templates/hosting/virtual_machine_detail.html +++ b/hosting/templates/hosting/virtual_machine_detail.html @@ -41,11 +41,17 @@

    {{virtual_machine.hosting_company_name}}

    - {% if virtual_machine.ip %} + {% if virtual_machine.ipv6 %}
    - +
    {% else %} diff --git a/opennebula_api/serializers.py b/opennebula_api/serializers.py index d762587f..32fd139e 100644 --- a/opennebula_api/serializers.py +++ b/opennebula_api/serializers.py @@ -88,7 +88,8 @@ class VirtualMachineSerializer(serializers.Serializer): disk_size = serializers.SerializerMethodField() - ip = 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() @@ -153,13 +154,16 @@ class VirtualMachineSerializer(serializers.Serializer): template = OpenNebulaManager().get_template(template_id) return template.name - def get_ip(self, obj): + def get_ipv4(self, obj): nic = obj.template.nics[0] if 'vm-ipv6-nat64-ipv4' in nic.network and is_in_v4_range(nic.mac): return str(v4_from_mac(nic.mac)) else: return '-' + def get_ipv6(self, obj): + nic = obj.template.nics[0] + return nic.ip6_global def hexstr2int(string): From 8d812202025c73caf81d427efd3681d14a31b433 Mon Sep 17 00:00:00 2001 From: Levi Date: Tue, 23 May 2017 11:48:02 -0500 Subject: [PATCH 16/19] changed virtual machine list --- datacenterlight/templates/datacenterlight/index.html | 2 +- hosting/templates/hosting/create_virtual_machine.html | 2 +- hosting/templates/hosting/virtual_machine_detail.html | 2 +- hosting/templates/hosting/virtual_machines.html | 6 ++++-- 4 files changed, 7 insertions(+), 5 deletions(-) diff --git a/datacenterlight/templates/datacenterlight/index.html b/datacenterlight/templates/datacenterlight/index.html index 953ce2c6..d097dec1 100755 --- a/datacenterlight/templates/datacenterlight/index.html +++ b/datacenterlight/templates/datacenterlight/index.html @@ -227,7 +227,7 @@

    {% trans "VM hosting" %}

    - 15CHF + 15CHF/month
    diff --git a/hosting/templates/hosting/create_virtual_machine.html b/hosting/templates/hosting/create_virtual_machine.html index ac6ae1d1..ac72046c 100644 --- a/hosting/templates/hosting/create_virtual_machine.html +++ b/hosting/templates/hosting/create_virtual_machine.html @@ -36,7 +36,7 @@ CORE: {{config.cpu|floatformat}}, RAM: {{config.memory|floatformat}} GiB, SSD: {{config.disk_size|floatformat}} GiB, - PRICE: {{config.price|floatformat}} CHF + PRICE: {{config.price|floatformat}} CHF/Month {% endfor %} diff --git a/hosting/templates/hosting/virtual_machine_detail.html b/hosting/templates/hosting/virtual_machine_detail.html index 0b17878d..227cbd8f 100644 --- a/hosting/templates/hosting/virtual_machine_detail.html +++ b/hosting/templates/hosting/virtual_machine_detail.html @@ -98,7 +98,7 @@

    {% trans "Current pricing"%}

    - {{virtual_machine.price|floatformat}} CHF/mo + {{virtual_machine.price|floatformat}} CHF/month
    diff --git a/hosting/templates/hosting/virtual_machines.html b/hosting/templates/hosting/virtual_machines.html index e7dee999..4a75ec24 100644 --- a/hosting/templates/hosting/virtual_machines.html +++ b/hosting/templates/hosting/virtual_machines.html @@ -26,7 +26,7 @@ {% trans "ID"%} - {% trans "Amount"%} + {% trans "Ipv4"%} {% trans "Status"%} @@ -35,7 +35,9 @@ {% for vm in vms %} {{vm.vm_id}} - {{vm.price}} CHF + {% if virtual_machine.ip %} + {{vm.price}} + {% endif %} {% if vm.state == 'ACTIVE' %} From 60fc2890f11ab1b2f1331ce37d92973f82f1e0ec Mon Sep 17 00:00:00 2001 From: Levi Date: Tue, 23 May 2017 11:50:02 -0500 Subject: [PATCH 17/19] added ipv4 and ipv6 to virtualmachine list --- hosting/templates/hosting/virtual_machines.html | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/hosting/templates/hosting/virtual_machines.html b/hosting/templates/hosting/virtual_machines.html index 27a02297..b43e1b86 100644 --- a/hosting/templates/hosting/virtual_machines.html +++ b/hosting/templates/hosting/virtual_machines.html @@ -26,7 +26,8 @@ {% trans "ID"%} - {% trans "Ipv4"%} + {% trans "Ipv4"%} + {% trans "Ipv6"%} {% trans "Status"%} @@ -35,9 +36,12 @@ {% for vm in vms %} {{vm.vm_id}} - {% if virtual_machine.ip %} - {{vm.price}} + {% if virtual_machine.ipv6 + {{virtual_machine.ipv4}} + + {{virtual_machine.ipv6}} {% endif %} + {% if vm.state == 'ACTIVE' %} From 3d03d00201f314befb6f41af4e9b84c8664df46d Mon Sep 17 00:00:00 2001 From: Levi Date: Tue, 23 May 2017 11:52:53 -0500 Subject: [PATCH 18/19] fixed ip format in virtual machine list --- hosting/templates/hosting/virtual_machines.html | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/hosting/templates/hosting/virtual_machines.html b/hosting/templates/hosting/virtual_machines.html index b43e1b86..f71dac2a 100644 --- a/hosting/templates/hosting/virtual_machines.html +++ b/hosting/templates/hosting/virtual_machines.html @@ -36,10 +36,10 @@ {% for vm in vms %} {{vm.vm_id}} - {% if virtual_machine.ipv6 - {{virtual_machine.ipv4}} + {% if vm.ipv6 %} + {{vm.ipv4}} - {{virtual_machine.ipv6}} + {{vm.ipv6}} {% endif %} From da3194fee33ccfbe4615f4678f4e4207e91baa76 Mon Sep 17 00:00:00 2001 From: Levi Date: Tue, 23 May 2017 11:58:48 -0500 Subject: [PATCH 19/19] fixed configuration name in vm detail --- opennebula_api/serializers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opennebula_api/serializers.py b/opennebula_api/serializers.py index a472105f..6c86776a 100644 --- a/opennebula_api/serializers.py +++ b/opennebula_api/serializers.py @@ -151,7 +151,7 @@ class VirtualMachineSerializer(serializers.Serializer): def get_configuration(self, obj): template_id = obj.template.template_id template = OpenNebulaManager().get_template(template_id) - return template.name + return template.name.strip('public-') def get_ipv4(self, obj): nic = obj.template.nics[0]