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…
	
	Add table
		Add a link
		
	
		Reference in a new issue