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:
Levi 2016-05-27 00:51:10 -05:00
parent 5da39e8ed3
commit c33c4f4148
14 changed files with 177 additions and 15 deletions

View file

@ -1,6 +1,32 @@
from django.contrib import admin from django.contrib import admin
from utils.mailer import BaseEmail
from .models import VirtualMachineType, VirtualMachinePlan 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(VirtualMachineType)
admin.site.register(VirtualMachinePlan) admin.site.register(VirtualMachinePlan, VirtualMachinePlanAdmin)

View 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),
),
]

View 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),
),
]

View 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),
),
]

View file

@ -81,12 +81,24 @@ class VirtualMachineType(models.Model):
class VirtualMachinePlan(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() cores = models.IntegerField()
memory = models.IntegerField() memory = models.IntegerField()
disk_size = models.IntegerField() disk_size = models.IntegerField()
vm_type = models.ForeignKey(VirtualMachineType) vm_type = models.ForeignKey(VirtualMachineType)
price = models.FloatField() price = models.FloatField()
public_key = models.TextField() public_key = models.TextField()
status = models.CharField(max_length=20, choices=VM_STATUS_CHOICES, default=PENDING_STATUS)
objects = VMPlansManager() objects = VMPlansManager()
@ -97,6 +109,10 @@ class VirtualMachinePlan(models.Model):
def hosting_company_name(self): def hosting_company_name(self):
return self.vm_type.get_hosting_company_display() return self.vm_type.get_hosting_company_display()
@cached_property
def location(self):
return self.vm_type.get_location_display()
@cached_property @cached_property
def name(self): def name(self):
name = 'vm-%s' % self.id name = 'vm-%s' % self.id

View file

@ -1,5 +1,5 @@
<<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<head> <head>
<title></title> <title></title>

View file

@ -1,5 +1,5 @@
<<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<head> <head>
<title></title> <title></title>

View 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>

View 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>

View file

@ -122,12 +122,16 @@
</div><!--/row--> </div><!--/row-->
</div> </div>
<div class="tab-pane" id="status-v"> <div class="tab-pane" id="status-v">
<div class="row "> <div class="row ">
<div class="col-md-12 inline-headers"> <div class="col-md-12 inline-headers">
<h3>Current status</h3> <h3>Current status</h3>
<span class="h3 pull-right label label-success"><strong>Online</strong></span> {% if virtual_machine.status == 'pending' %}
<hr> <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> </div>
</div> </div>

View file

@ -11,7 +11,7 @@
<thead> <thead>
<tr> <tr>
<th>ID</th> <th>ID</th>
<th>Type</th> <th>Location</th>
<th>Amount</th> <th>Amount</th>
<th></th> <th></th>
</tr> </tr>
@ -20,7 +20,7 @@
{% for vm in vms %} {% for vm in vms %}
<tr> <tr>
<td scope="row">{{vm.name}}</td> <td scope="row">{{vm.name}}</td>
<td>{{vm.hosting_company_name}}</td> <td>{{vm.location}}</td>
<td>{{vm.price}} CHF</td> <td>{{vm.price}} CHF</td>
<td> <td>
<button type="button" class="btn btn-default"><a href="{% url 'hosting:virtual_machines' vm.id %}">View Detail</a></button> <button type="button" class="btn btn-default"><a href="{% url 'hosting:virtual_machines' vm.id %}">View Detail</a></button>

View 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'),
),
]

View file

@ -2,7 +2,7 @@ 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 from django.contrib.auth.models import User, AbstractBaseUser, BaseUserManager, AbstractUser, 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.auth.models import User
@ -47,7 +47,7 @@ class MyUserManager(BaseUserManager):
return user return user
class CustomUser(AbstractBaseUser): class CustomUser(AbstractBaseUser, PermissionsMixin):
VALIDATED_CHOICES = ((0, 'Not validated'), (1, 'Validated')) VALIDATED_CHOICES = ((0, 'Not validated'), (1, 'Validated'))
site = models.ForeignKey(Site, default=1) site = models.ForeignKey(Site, default=1)
name = models.CharField(max_length=50) name = models.CharField(max_length=50)

View file

@ -16,11 +16,8 @@ class BaseEmail(object):
self.subject = kwargs.get('subject') self.subject = kwargs.get('subject')
self.context = kwargs.get('context', {}) self.context = kwargs.get('context', {})
self.template_full_path = '%s%s' % (self.template_path, self.template_name) self.template_full_path = '%s%s' % (self.template_path, self.template_name)
text_content = render_to_string('%s.txt' % self.template_full_path, self.context)
text_content = render_to_string('%s.txt' % self.template_full_path, html_content = render_to_string('%s.html' % self.template_full_path, self.context)
{'data': self.context})
html_content = render_to_string('%s.html' % self.template_full_path,
{'data': self.context})
self.email = EmailMultiAlternatives(self.subject, text_content) self.email = EmailMultiAlternatives(self.subject, text_content)
self.email.attach_alternative(html_content, "text/html") self.email.attach_alternative(html_content, "text/html")