Add hosting bill view, model and urls
This commit is contained in:
		
					parent
					
						
							
								9884eefa19
							
						
					
				
			
			
				commit
				
					
						2ff8b9e4a5
					
				
			
		
					 9 changed files with 330 additions and 3 deletions
				
			
		| 
						 | 
				
			
			@ -5,7 +5,8 @@ from django.core.urlresolvers import reverse
 | 
			
		|||
from utils.mailer import BaseEmail
 | 
			
		||||
 | 
			
		||||
from .forms import HostingOrderAdminForm
 | 
			
		||||
from .models import VirtualMachineType, VirtualMachinePlan, HostingOrder, ManageVM
 | 
			
		||||
from .models import VirtualMachineType, VirtualMachinePlan, HostingOrder, \
 | 
			
		||||
                    ManageVM, HostingBill
 | 
			
		||||
from .opennebula_functions import HostingManageVMAdmin
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -98,3 +99,4 @@ admin.site.register(HostingOrder, HostingOrderAdmin)
 | 
			
		|||
admin.site.register(VirtualMachineType)
 | 
			
		||||
admin.site.register(VirtualMachinePlan, VirtualMachinePlanAdmin)
 | 
			
		||||
admin.site.register(ManageVM, HostingManageVMAdmin)
 | 
			
		||||
admin.site.register(HostingBill)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										24
									
								
								hosting/migrations/0028_managevms.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								hosting/migrations/0028_managevms.py
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,24 @@
 | 
			
		|||
# -*- coding: utf-8 -*-
 | 
			
		||||
# Generated by Django 1.9.4 on 2017-04-24 04:24
 | 
			
		||||
from __future__ import unicode_literals
 | 
			
		||||
 | 
			
		||||
from django.db import migrations, models
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Migration(migrations.Migration):
 | 
			
		||||
 | 
			
		||||
    dependencies = [
 | 
			
		||||
        ('hosting', '0027_auto_20160711_0210'),
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
    operations = [
 | 
			
		||||
        migrations.CreateModel(
 | 
			
		||||
            name='ManageVMs',
 | 
			
		||||
            fields=[
 | 
			
		||||
                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
 | 
			
		||||
            ],
 | 
			
		||||
            options={
 | 
			
		||||
                'managed': False,
 | 
			
		||||
            },
 | 
			
		||||
        ),
 | 
			
		||||
    ]
 | 
			
		||||
							
								
								
									
										24
									
								
								hosting/migrations/0029_managevm.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								hosting/migrations/0029_managevm.py
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,24 @@
 | 
			
		|||
# -*- coding: utf-8 -*-
 | 
			
		||||
# Generated by Django 1.9.4 on 2017-04-24 04:25
 | 
			
		||||
from __future__ import unicode_literals
 | 
			
		||||
 | 
			
		||||
from django.db import migrations, models
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Migration(migrations.Migration):
 | 
			
		||||
 | 
			
		||||
    dependencies = [
 | 
			
		||||
        ('hosting', '0028_managevms'),
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
    operations = [
 | 
			
		||||
        migrations.CreateModel(
 | 
			
		||||
            name='ManageVM',
 | 
			
		||||
            fields=[
 | 
			
		||||
                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
 | 
			
		||||
            ],
 | 
			
		||||
            options={
 | 
			
		||||
                'managed': False,
 | 
			
		||||
            },
 | 
			
		||||
        ),
 | 
			
		||||
    ]
 | 
			
		||||
							
								
								
									
										31
									
								
								hosting/migrations/0030_hostingbill.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								hosting/migrations/0030_hostingbill.py
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,31 @@
 | 
			
		|||
# -*- coding: utf-8 -*-
 | 
			
		||||
# Generated by Django 1.9.4 on 2017-05-05 11:50
 | 
			
		||||
from __future__ import unicode_literals
 | 
			
		||||
 | 
			
		||||
from django.db import migrations, models
 | 
			
		||||
import django.db.models.deletion
 | 
			
		||||
import utils.mixins
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Migration(migrations.Migration):
 | 
			
		||||
 | 
			
		||||
    dependencies = [
 | 
			
		||||
        ('utils', '0005_auto_20170322_1443'),
 | 
			
		||||
        ('membership', '0006_auto_20160526_0445'),
 | 
			
		||||
        ('hosting', '0029_managevm'),
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
    operations = [
 | 
			
		||||
        migrations.CreateModel(
 | 
			
		||||
            name='HostingBill',
 | 
			
		||||
            fields=[
 | 
			
		||||
                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
 | 
			
		||||
                ('billing_address', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='utils.BillingAddress')),
 | 
			
		||||
                ('customer', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='membership.StripeCustomer')),
 | 
			
		||||
            ],
 | 
			
		||||
            options={
 | 
			
		||||
                'permissions': (('view_hostingbill', 'View Hosting Bill'),),
 | 
			
		||||
            },
 | 
			
		||||
            bases=(utils.mixins.AssignPermissionsMixin, models.Model),
 | 
			
		||||
        ),
 | 
			
		||||
    ]
 | 
			
		||||
| 
						 | 
				
			
			@ -1,5 +1,6 @@
 | 
			
		|||
import os
 | 
			
		||||
 | 
			
		||||
import oca
 | 
			
		||||
from django.db import models
 | 
			
		||||
from django.utils.translation import ugettext_lazy as _
 | 
			
		||||
from django.utils.functional import cached_property
 | 
			
		||||
| 
						 | 
				
			
			@ -233,3 +234,18 @@ class ManageVM(models.Model):
 | 
			
		|||
 | 
			
		||||
    class Meta:
 | 
			
		||||
        managed = False
 | 
			
		||||
 | 
			
		||||
class HostingBill(AssignPermissionsMixin, models.Model):
 | 
			
		||||
    customer = models.ForeignKey(StripeCustomer)
 | 
			
		||||
    billing_address = models.ForeignKey(BillingAddress)
 | 
			
		||||
 | 
			
		||||
    permissions = ('view_hostingbill',)
 | 
			
		||||
 | 
			
		||||
    class Meta:
 | 
			
		||||
        permissions = (
 | 
			
		||||
            ('view_hostingbill', 'View Hosting Bill'),
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
    def __str__(self):
 | 
			
		||||
        return "%s" % (self.customer.user.email)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										93
									
								
								hosting/templates/hosting/bill_detail.html
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										93
									
								
								hosting/templates/hosting/bill_detail.html
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,93 @@
 | 
			
		|||
{% extends "hosting/base_short.html" %}
 | 
			
		||||
{% load staticfiles bootstrap3 %}
 | 
			
		||||
{% load i18n %}
 | 
			
		||||
{% block content %}
 | 
			
		||||
 | 
			
		||||
<h1> {{ bill }} </h1>
 | 
			
		||||
<div class="container">
 | 
			
		||||
	{# Adress bar  #}
 | 
			
		||||
    <div class="row">
 | 
			
		||||
            <div class="invoice-title">
 | 
			
		||||
                <h2>{% trans "Invoice"%}</h2><h3 class="pull-right">{% trans "Order #"%} {{bill.id}}</h3>
 | 
			
		||||
            </div>
 | 
			
		||||
	</div>
 | 
			
		||||
    <hr>
 | 
			
		||||
	<div class="row">
 | 
			
		||||
                <div class="col-sm-6">
 | 
			
		||||
                    <address>
 | 
			
		||||
                        {{bill.customer.user.name}}<br>
 | 
			
		||||
                        {{bill.billing_address.street_address}},{{bill.billing_address.postal_code}}<br>
 | 
			
		||||
                        {{bill.billing_address.city}}, {{bill.billing_address.country}}.
 | 
			
		||||
                    </address>
 | 
			
		||||
                </div>
 | 
			
		||||
                <div class="col-sm-6 text-right">
 | 
			
		||||
                    <address>
 | 
			
		||||
							{% trans "ungleich GmbH" %}<br>
 | 
			
		||||
							{% trans "buchhaltung@ungleich.ch" %}<br>
 | 
			
		||||
							{% trans "Hauptstrasse 14"%}<br>
 | 
			
		||||
							{% trans "CH-8775 Luchsingen"%}<br>
 | 
			
		||||
							{% trans "Mwst-Nummer: CHE-109.549.333 MWST"%}<br>
 | 
			
		||||
 | 
			
		||||
                    </address>
 | 
			
		||||
				</div>
 | 
			
		||||
	</div>
 | 
			
		||||
	<hr>
 | 
			
		||||
	<table class="table table-bordered"> 
 | 
			
		||||
	    {# Bill header #}
 | 
			
		||||
        <thead>
 | 
			
		||||
            <tr>
 | 
			
		||||
                <th>Name</th>
 | 
			
		||||
                <th>Cores</th>
 | 
			
		||||
                <th>Memory</th>
 | 
			
		||||
                <th>Disk Size</th>
 | 
			
		||||
                <th>Price</th>
 | 
			
		||||
            </tr>
 | 
			
		||||
        </thead>
 | 
			
		||||
        <tbody>
 | 
			
		||||
	        {# Bill items#}
 | 
			
		||||
            {% for vm in vms %}
 | 
			
		||||
                <tr>
 | 
			
		||||
                    <td>{{ vm.name }}</td>
 | 
			
		||||
                    <td>{{ vm.cores }}</td>
 | 
			
		||||
                    <td>{{ vm.memory }}</td>
 | 
			
		||||
                    <td>{{ vm.disk_size }}</td>
 | 
			
		||||
                    <td>{{ vm.price }}</td>
 | 
			
		||||
 | 
			
		||||
                </tr>
 | 
			
		||||
            {% endfor %}
 | 
			
		||||
	        {# Bill total#}
 | 
			
		||||
            <tr>
 | 
			
		||||
                <td> {% trans "Total:" %} </td>
 | 
			
		||||
                <td>  </td>
 | 
			
		||||
                <td>  </td>
 | 
			
		||||
                <td> {% trans "Brutto" %} </td>
 | 
			
		||||
                <td> {% trans "Netto" %} </td>
 | 
			
		||||
            </tr>
 | 
			
		||||
        </tbody>
 | 
			
		||||
    </table>
 | 
			
		||||
	<hr>
 | 
			
		||||
    {# Bill Footer #}
 | 
			
		||||
	<div class="row">
 | 
			
		||||
			{% trans "Alles Preise in CHF mit 8% Mehrwertsteuer." %}
 | 
			
		||||
			{% trans "Betrag zahlbar innerhalb von 30 Tagen ab Rechnungseingang." %}
 | 
			
		||||
			{% trans "Kontoverbindung:" %}
 | 
			
		||||
			<div class="row">
 | 
			
		||||
				<div class="col-sm-6">
 | 
			
		||||
					{% trans "IBAN:" %}
 | 
			
		||||
				</div>
 | 
			
		||||
				<div class="col-sm-6">
 | 
			
		||||
					{% trans "BIC:" %}
 | 
			
		||||
				</div>
 | 
			
		||||
			</div>
 | 
			
		||||
			<div class="row">
 | 
			
		||||
				<div class="col-sm-6">
 | 
			
		||||
					{% trans "CH02 ............" %}
 | 
			
		||||
				</div>
 | 
			
		||||
				<div class="col-sm-6">
 | 
			
		||||
					{% trans "POFICHBEXXX" %}
 | 
			
		||||
				</div>
 | 
			
		||||
			</div>
 | 
			
		||||
	</div>
 | 
			
		||||
</div>
 | 
			
		||||
{% endblock %}
 | 
			
		||||
			
 | 
			
		||||
							
								
								
									
										60
									
								
								hosting/templates/hosting/bills.html
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										60
									
								
								hosting/templates/hosting/bills.html
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,60 @@
 | 
			
		|||
{% extends "hosting/base_short.html" %}
 | 
			
		||||
{% load staticfiles bootstrap3 %}
 | 
			
		||||
{% load i18n %}
 | 
			
		||||
 | 
			
		||||
{% block content %}
 | 
			
		||||
 | 
			
		||||
    <div>
 | 
			
		||||
        <div class="container orders-container">
 | 
			
		||||
            <div class="row">
 | 
			
		||||
                <div class="col-md-8 col-md-offset-2">
 | 
			
		||||
                    <table class="table borderless table-hover">
 | 
			
		||||
                        <h3>{% trans "Customers"%}</h3>
 | 
			
		||||
                        <br/>
 | 
			
		||||
                        <thead>
 | 
			
		||||
                        <tr>
 | 
			
		||||
                            <th>{% trans "Name"%}</th>
 | 
			
		||||
                            <th>{% trans "Email"%}</th>
 | 
			
		||||
                            <th></th>
 | 
			
		||||
                        </tr>
 | 
			
		||||
                        </thead>
 | 
			
		||||
                        <tbody>
 | 
			
		||||
                        {% for user in users %}
 | 
			
		||||
                            <tr>
 | 
			
		||||
                                <td>{{ user.name}}</td>
 | 
			
		||||
                                <td>{{ user.email}} CHF</td>
 | 
			
		||||
                                <td>
 | 
			
		||||
                                    <button type="button" class="btn btn-default"><a
 | 
			
		||||
                                            href="{% url 'hosting:bills' user.id %}">{% trans "View Bill"%}</a>
 | 
			
		||||
                                    </button>
 | 
			
		||||
                                </td>
 | 
			
		||||
                            </tr>
 | 
			
		||||
                        {% endfor %}
 | 
			
		||||
 | 
			
		||||
                        </tbody>
 | 
			
		||||
                    </table>
 | 
			
		||||
 | 
			
		||||
                    {% if is_paginated %}
 | 
			
		||||
                        <div class="pagination">
 | 
			
		||||
			            <span class="page-links">
 | 
			
		||||
			                {% if page_obj.has_previous %}
 | 
			
		||||
                                <a href="{{ request.path }}?page={{ page_obj.previous_page_number }}">{% trans "previous"%}</a>
 | 
			
		||||
                            {% endif %}
 | 
			
		||||
                            <span class="page-current">
 | 
			
		||||
			                    Page {{ page_obj.number }} of {{ page_obj.paginator.num_pages }}.
 | 
			
		||||
			                </span>
 | 
			
		||||
                            {% if page_obj.has_next %}
 | 
			
		||||
                                <a href="{{ request.path }}?page={{ page_obj.next_page_number }}">{% trans "next"%}</a>
 | 
			
		||||
                            {% endif %}
 | 
			
		||||
			            </span>
 | 
			
		||||
                        </div>
 | 
			
		||||
                    {% endif %}
 | 
			
		||||
 | 
			
		||||
                </div>
 | 
			
		||||
 | 
			
		||||
            </div>
 | 
			
		||||
        </div>
 | 
			
		||||
 | 
			
		||||
    </div>
 | 
			
		||||
 | 
			
		||||
{% endblock %}
 | 
			
		||||
| 
						 | 
				
			
			@ -4,7 +4,8 @@ from .views import DjangoHostingView, RailsHostingView, PaymentVMView,\
 | 
			
		|||
    NodeJSHostingView, LoginView, SignupView, IndexView, \
 | 
			
		||||
    OrdersHostingListView, OrdersHostingDetailView, VirtualMachinesPlanListView,\
 | 
			
		||||
    VirtualMachineView, GenerateVMSSHKeysView, OrdersHostingDeleteView, NotificationsView, \
 | 
			
		||||
    MarkAsReadNotificationView, PasswordResetView, PasswordResetConfirmView, HostingPricingView
 | 
			
		||||
    MarkAsReadNotificationView, PasswordResetView, PasswordResetConfirmView, \
 | 
			
		||||
    HostingPricingView, HostingBillListView, HostingBillDetailView
 | 
			
		||||
 | 
			
		||||
urlpatterns = [
 | 
			
		||||
    url(r'index/?$', IndexView.as_view(), name='index'),
 | 
			
		||||
| 
						 | 
				
			
			@ -15,6 +16,8 @@ urlpatterns = [
 | 
			
		|||
    url(r'payment/?$', PaymentVMView.as_view(), name='payment'),
 | 
			
		||||
    url(r'orders/?$', OrdersHostingListView.as_view(), name='orders'),
 | 
			
		||||
    url(r'orders/(?P<pk>\d+)/?$', OrdersHostingDetailView.as_view(), name='orders'),
 | 
			
		||||
    url(r'bills/?$', HostingBillListView.as_view(), name='bills'),
 | 
			
		||||
    url(r'bills/(?P<pk>\d+)/?$', HostingBillDetailView.as_view(), name='bills'),
 | 
			
		||||
    url(r'cancel_order/(?P<pk>\d+)/?$', OrdersHostingDeleteView.as_view(), name='delete_order'),
 | 
			
		||||
    url(r'my-virtual-machines/?$', VirtualMachinesPlanListView.as_view(), name='virtual_machines'),
 | 
			
		||||
    url(r'my-virtual-machines/(?P<pk>\d+)/?$', VirtualMachineView.as_view(),
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,3 +1,4 @@
 | 
			
		|||
import oca
 | 
			
		||||
 | 
			
		||||
from django.shortcuts import render
 | 
			
		||||
from django.core.urlresolvers import reverse_lazy, reverse
 | 
			
		||||
| 
						 | 
				
			
			@ -19,7 +20,7 @@ from utils.stripe_utils import StripeUtils
 | 
			
		|||
from utils.forms import BillingAddressForm, PasswordResetRequestForm
 | 
			
		||||
from utils.views import PasswordResetViewMixin, PasswordResetConfirmViewMixin, LoginViewMixin
 | 
			
		||||
from utils.mailer import BaseEmail
 | 
			
		||||
from .models import VirtualMachineType, VirtualMachinePlan, HostingOrder
 | 
			
		||||
from .models import VirtualMachineType, VirtualMachinePlan, HostingOrder, HostingBill
 | 
			
		||||
from .forms import HostingUserSignupForm, HostingUserLoginForm
 | 
			
		||||
from .mixins import ProcessVMSelectionMixin
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -328,6 +329,10 @@ class OrdersHostingDetailView(PermissionRequiredMixin, LoginRequiredMixin, Detai
 | 
			
		|||
    permission_required = ['view_hostingorder']
 | 
			
		||||
    model = HostingOrder
 | 
			
		||||
 | 
			
		||||
    def get_context_data(self, **kwargs):
 | 
			
		||||
        context = super(DetailView, self).get_context_data(**kwargs)
 | 
			
		||||
        print(context)
 | 
			
		||||
        return context
 | 
			
		||||
 | 
			
		||||
class OrdersHostingListView(LoginRequiredMixin, ListView):
 | 
			
		||||
    template_name = "hosting/orders.html"
 | 
			
		||||
| 
						 | 
				
			
			@ -396,3 +401,72 @@ class VirtualMachineView(PermissionRequiredMixin, LoginRequiredMixin, UpdateView
 | 
			
		|||
        email.send()
 | 
			
		||||
 | 
			
		||||
        return HttpResponseRedirect(self.get_success_url())
 | 
			
		||||
 | 
			
		||||
class HostingBillListView(LoginRequiredMixin, ListView):
 | 
			
		||||
    template_name = "hosting/bills.html"
 | 
			
		||||
    login_url = reverse_lazy('hosting:login')
 | 
			
		||||
    context_object_name = "users"
 | 
			
		||||
    model = StripeCustomer
 | 
			
		||||
    paginate_by = 10
 | 
			
		||||
    ordering = '-id'
 | 
			
		||||
    #TODO show only clients i.e. get_query_set
 | 
			
		||||
 | 
			
		||||
class HostingBillDetailView(PermissionRequiredMixin, LoginRequiredMixin, DetailView):
 | 
			
		||||
    template_name = "hosting/bill_detail.html"
 | 
			
		||||
    login_url = reverse_lazy('hosting:login')
 | 
			
		||||
    permission_required = ['view_hostingview']
 | 
			
		||||
    context_object_name = "bill"
 | 
			
		||||
    model = HostingBill
 | 
			
		||||
 | 
			
		||||
    def get_object(self, queryset=None):
 | 
			
		||||
        #Get HostingBill for primary key (Select from customer users)
 | 
			
		||||
        pk = self.kwargs['pk']
 | 
			
		||||
        return HostingBill.objects.filter(customer__id=pk).first()
 | 
			
		||||
 | 
			
		||||
    def get_context_data(self, **kwargs):
 | 
			
		||||
        # Get User
 | 
			
		||||
        user_email = self.object.customer.user.email
 | 
			
		||||
        # Get context
 | 
			
		||||
        context = super(DetailView, self).get_context_data(**kwargs)
 | 
			
		||||
        # Add VMs to context
 | 
			
		||||
        context['vms'] = []
 | 
			
		||||
 | 
			
		||||
        # Connect to open nebula server
 | 
			
		||||
        client = oca.Client("{0}:{1}".format(settings.OPENNEBULA_USERNAME,
 | 
			
		||||
                                             settings.OPENNEBULA_PASSWORD),
 | 
			
		||||
                            "{protocol}://{domain}:{port}{endpoint}".format(
 | 
			
		||||
                                protocol=settings.OPENNEBULA_PROTOCOL,
 | 
			
		||||
                                domain=settings.OPENNEBULA_DOMAIN,
 | 
			
		||||
                                port=settings.OPENNEBULA_PORT,
 | 
			
		||||
                                endpoint=settings.OPENNEBULA_ENDPOINT
 | 
			
		||||
                            ))
 | 
			
		||||
        # Get open nebula user id for given email 
 | 
			
		||||
        user_pool = oca.UserPool(client)
 | 
			
		||||
        user_pool.info()
 | 
			
		||||
        user_id = user_pool.get_by_name('alain').id
 | 
			
		||||
 | 
			
		||||
        # Get vm_pool for given user_id
 | 
			
		||||
        vm_pool = oca.VirtualMachinePool(client)
 | 
			
		||||
        vm_pool.info(filter=user_id)
 | 
			
		||||
        # Add vm in vm_pool to context
 | 
			
		||||
        for vm in vm_pool:
 | 
			
		||||
            #TODO: Replace with vm plan 
 | 
			
		||||
            name = vm.name
 | 
			
		||||
            cores = int(vm.template.vcpu)
 | 
			
		||||
            memory = int(vm.template.memory) / 1024
 | 
			
		||||
            # Check if vm has more than one disk
 | 
			
		||||
            if 'DISK' in vm.template.multiple:
 | 
			
		||||
                disk_size = 0
 | 
			
		||||
                for disk in vm.template.disks:
 | 
			
		||||
                    disk_size += int(disk.size) / 1024
 | 
			
		||||
            else:
 | 
			
		||||
                disk_size = int(vm.template.disk.size) / 1024
 | 
			
		||||
            vm = {}
 | 
			
		||||
            vm['name'] = name
 | 
			
		||||
            vm['price'] = 0.6 * disk_size + 2 * memory + 5 * cores
 | 
			
		||||
            vm['disk_size'] = disk_size
 | 
			
		||||
            vm['cores'] = cores 
 | 
			
		||||
            vm['memory'] = memory
 | 
			
		||||
            context['vms'].append(vm)
 | 
			
		||||
 | 
			
		||||
        return context
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue