Added status field to a booked VM. Added the capability to change a booked VM status from the admin panel. Send email to user after his VM is approved
This commit is contained in:
parent
5da39e8ed3
commit
c33c4f4148
14 changed files with 177 additions and 15 deletions
|
@ -1,6 +1,32 @@
|
|||
from django.contrib import admin
|
||||
|
||||
from utils.mailer import BaseEmail
|
||||
from .models import VirtualMachineType, VirtualMachinePlan
|
||||
|
||||
|
||||
class VirtualMachinePlanAdmin(admin.ModelAdmin):
|
||||
list_display = ('name', 'id', 'email')
|
||||
|
||||
def email(self, obj):
|
||||
return obj.hosting_orders.latest('id').customer.user.email
|
||||
|
||||
def save_model(self, request, obj, form, change):
|
||||
email = self.email(obj)
|
||||
if 'status' in form.changed_data and obj.status == VirtualMachinePlan.ONLINE_STATUS:
|
||||
context = {
|
||||
'vm': obj
|
||||
}
|
||||
email_data = {
|
||||
'subject': 'Your VM has been activated',
|
||||
'to': email,
|
||||
'context': context,
|
||||
'template_name': 'vm_activated',
|
||||
'template_path': 'emails/'
|
||||
}
|
||||
email = BaseEmail(**email_data)
|
||||
email.send()
|
||||
obj.save()
|
||||
|
||||
|
||||
admin.site.register(VirtualMachineType)
|
||||
admin.site.register(VirtualMachinePlan)
|
||||
admin.site.register(VirtualMachinePlan, VirtualMachinePlanAdmin)
|
||||
|
|
20
hosting/migrations/0019_virtualmachineplan_status.py
Normal file
20
hosting/migrations/0019_virtualmachineplan_status.py
Normal file
|
@ -0,0 +1,20 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.9.4 on 2016-05-26 02:57
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('hosting', '0018_virtualmachineplan_public_key'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='virtualmachineplan',
|
||||
name='status',
|
||||
field=models.CharField(choices=[('pending', 'Pending for activation'), ('online', 'Online')], default='online', max_length=20),
|
||||
),
|
||||
]
|
20
hosting/migrations/0020_auto_20160526_0258.py
Normal file
20
hosting/migrations/0020_auto_20160526_0258.py
Normal file
|
@ -0,0 +1,20 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.9.4 on 2016-05-26 02:58
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('hosting', '0019_virtualmachineplan_status'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='virtualmachineplan',
|
||||
name='status',
|
||||
field=models.CharField(choices=[('pending', 'Pending for activation'), ('online', 'Online')], default='pending', max_length=20),
|
||||
),
|
||||
]
|
20
hosting/migrations/0021_auto_20160526_0445.py
Normal file
20
hosting/migrations/0021_auto_20160526_0445.py
Normal file
|
@ -0,0 +1,20 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.9.4 on 2016-05-26 04:45
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('hosting', '0020_auto_20160526_0258'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='virtualmachineplan',
|
||||
name='status',
|
||||
field=models.CharField(choices=[('pending', 'Pending for activation'), ('online', 'Online'), ('canceled', 'Canceled')], default='pending', max_length=20),
|
||||
),
|
||||
]
|
|
@ -81,12 +81,24 @@ class VirtualMachineType(models.Model):
|
|||
|
||||
|
||||
class VirtualMachinePlan(models.Model):
|
||||
|
||||
PENDING_STATUS = 'pending'
|
||||
ONLINE_STATUS = 'online'
|
||||
CANCELED_STATUS = 'canceled'
|
||||
|
||||
VM_STATUS_CHOICES = (
|
||||
(PENDING_STATUS, 'Pending for activation'),
|
||||
(ONLINE_STATUS, 'Online'),
|
||||
(CANCELED_STATUS, 'Canceled')
|
||||
)
|
||||
|
||||
cores = models.IntegerField()
|
||||
memory = models.IntegerField()
|
||||
disk_size = models.IntegerField()
|
||||
vm_type = models.ForeignKey(VirtualMachineType)
|
||||
price = models.FloatField()
|
||||
public_key = models.TextField()
|
||||
status = models.CharField(max_length=20, choices=VM_STATUS_CHOICES, default=PENDING_STATUS)
|
||||
|
||||
objects = VMPlansManager()
|
||||
|
||||
|
@ -97,6 +109,10 @@ class VirtualMachinePlan(models.Model):
|
|||
def hosting_company_name(self):
|
||||
return self.vm_type.get_hosting_company_display()
|
||||
|
||||
@cached_property
|
||||
def location(self):
|
||||
return self.vm_type.get_location_display()
|
||||
|
||||
@cached_property
|
||||
def name(self):
|
||||
name = 'vm-%s' % self.id
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
|
||||
<<!DOCTYPE html>
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title></title>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
|
||||
<<!DOCTYPE html>
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title></title>
|
||||
|
|
13
hosting/templates/emails/vm_activated.html
Normal file
13
hosting/templates/emails/vm_activated.html
Normal file
|
@ -0,0 +1,13 @@
|
|||
|
||||
{% load staticfiles bootstrap3%}
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title></title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
You virtual machine {{vm.name}} has been activated. You can manage your vm on this <a href="{{request.HOS}}{% url 'hosting:virtual_machines' vm.id %}"> link </a>
|
||||
|
||||
</body>
|
||||
</html>
|
15
hosting/templates/emails/vm_activated.txt
Normal file
15
hosting/templates/emails/vm_activated.txt
Normal file
|
@ -0,0 +1,15 @@
|
|||
|
||||
{% load staticfiles bootstrap3%}
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title></title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
You virtual machine {{vm.name}} has been activated. You can manage your vm in this <a href="{% url 'hosting:virtual_machines' vm.id %}"> link </a>
|
||||
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -122,12 +122,16 @@
|
|||
</div><!--/row-->
|
||||
</div>
|
||||
<div class="tab-pane" id="status-v">
|
||||
|
||||
<div class="row ">
|
||||
<div class="col-md-12 inline-headers">
|
||||
<h3>Current status</h3>
|
||||
<span class="h3 pull-right label label-success"><strong>Online</strong></span>
|
||||
<hr>
|
||||
{% if virtual_machine.status == 'pending' %}
|
||||
<span class="h3 pull-right label label-warning"><strong>{{virtual_machine.get_status_display}}</strong></span>
|
||||
{% elif virtual_machine.status == 'online' %}
|
||||
<span class="h3 pull-right label label-success"><strong>{{virtual_machine.get_status_display}}</strong></span>
|
||||
{% else %}
|
||||
<span class="h3 pull-right label label-error"><strong>{{virtual_machine.get_status_display}}</strong></span>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
<thead>
|
||||
<tr>
|
||||
<th>ID</th>
|
||||
<th>Type</th>
|
||||
<th>Location</th>
|
||||
<th>Amount</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
|
@ -20,7 +20,7 @@
|
|||
{% for vm in vms %}
|
||||
<tr>
|
||||
<td scope="row">{{vm.name}}</td>
|
||||
<td>{{vm.hosting_company_name}}</td>
|
||||
<td>{{vm.location}}</td>
|
||||
<td>{{vm.price}} CHF</td>
|
||||
<td>
|
||||
<button type="button" class="btn btn-default"><a href="{% url 'hosting:virtual_machines' vm.id %}">View Detail</a></button>
|
||||
|
|
31
membership/migrations/0006_auto_20160526_0445.py
Normal file
31
membership/migrations/0006_auto_20160526_0445.py
Normal file
|
@ -0,0 +1,31 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.9.4 on 2016-05-26 04:45
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('auth', '0007_alter_validators_add_error_messages'),
|
||||
('membership', '0005_customuser_is_admin'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='customuser',
|
||||
name='groups',
|
||||
field=models.ManyToManyField(blank=True, help_text='The groups this user belongs to. A user will get all permissions granted to each of their groups.', related_name='user_set', related_query_name='user', to='auth.Group', verbose_name='groups'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='customuser',
|
||||
name='is_superuser',
|
||||
field=models.BooleanField(default=False, help_text='Designates that this user has all permissions without explicitly assigning them.', verbose_name='superuser status'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='customuser',
|
||||
name='user_permissions',
|
||||
field=models.ManyToManyField(blank=True, help_text='Specific permissions for this user.', related_name='user_set', related_query_name='user', to='auth.Permission', verbose_name='user permissions'),
|
||||
),
|
||||
]
|
|
@ -2,7 +2,7 @@ from datetime import datetime
|
|||
|
||||
from django.db import models
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.contrib.auth.models import User, AbstractBaseUser, BaseUserManager, AbstractUser
|
||||
from django.contrib.auth.models import User, AbstractBaseUser, BaseUserManager, AbstractUser, PermissionsMixin
|
||||
from django.contrib.auth.hashers import make_password
|
||||
from django.core.validators import RegexValidator
|
||||
from django.contrib.auth.models import User
|
||||
|
@ -47,7 +47,7 @@ class MyUserManager(BaseUserManager):
|
|||
return user
|
||||
|
||||
|
||||
class CustomUser(AbstractBaseUser):
|
||||
class CustomUser(AbstractBaseUser, PermissionsMixin):
|
||||
VALIDATED_CHOICES = ((0, 'Not validated'), (1, 'Validated'))
|
||||
site = models.ForeignKey(Site, default=1)
|
||||
name = models.CharField(max_length=50)
|
||||
|
|
|
@ -16,11 +16,8 @@ class BaseEmail(object):
|
|||
self.subject = kwargs.get('subject')
|
||||
self.context = kwargs.get('context', {})
|
||||
self.template_full_path = '%s%s' % (self.template_path, self.template_name)
|
||||
|
||||
text_content = render_to_string('%s.txt' % self.template_full_path,
|
||||
{'data': self.context})
|
||||
html_content = render_to_string('%s.html' % self.template_full_path,
|
||||
{'data': self.context})
|
||||
text_content = render_to_string('%s.txt' % self.template_full_path, self.context)
|
||||
html_content = render_to_string('%s.html' % self.template_full_path, self.context)
|
||||
|
||||
self.email = EmailMultiAlternatives(self.subject, text_content)
|
||||
self.email.attach_alternative(html_content, "text/html")
|
||||
|
|
Loading…
Reference in a new issue