2017-08-20 19:11:46 +00:00
|
|
|
import os
|
2017-05-12 17:13:18 +00:00
|
|
|
import logging
|
2017-09-30 12:25:49 +00:00
|
|
|
from dateutil.relativedelta import relativedelta
|
2017-05-12 17:13:18 +00:00
|
|
|
|
2015-05-27 10:21:30 +00:00
|
|
|
from django.db import models
|
2017-09-30 12:35:02 +00:00
|
|
|
from django.utils import timezone
|
2016-05-03 05:59:40 +00:00
|
|
|
from django.utils.functional import cached_property
|
2017-08-20 19:11:46 +00:00
|
|
|
from Crypto.PublicKey import RSA
|
2018-04-16 01:23:09 +00:00
|
|
|
|
2018-07-01 16:33:10 +00:00
|
|
|
from datacenterlight.models import VMPricing, VMTemplate
|
2017-05-04 04:19:32 +00:00
|
|
|
from membership.models import StripeCustomer, CustomUser
|
2017-08-17 16:16:36 +00:00
|
|
|
from utils.models import BillingAddress
|
2017-08-20 19:11:46 +00:00
|
|
|
from utils.mixins import AssignPermissionsMixin
|
2016-05-03 05:59:40 +00:00
|
|
|
|
2017-05-08 10:53:03 +00:00
|
|
|
logger = logging.getLogger(__name__)
|
2016-04-18 00:52:19 +00:00
|
|
|
|
2016-04-26 06:16:03 +00:00
|
|
|
|
2017-05-13 11:47:53 +00:00
|
|
|
class HostingPlan(models.Model):
|
|
|
|
disk_size = models.FloatField(default=0.0)
|
|
|
|
cpu_cores = models.FloatField(default=0.0)
|
|
|
|
memory = models.FloatField(default=0.0)
|
|
|
|
|
|
|
|
def serialize(self):
|
|
|
|
return {
|
|
|
|
'id': self.id,
|
2017-06-29 14:34:40 +00:00
|
|
|
'cpu': self.cpu_cores,
|
2017-05-13 11:47:53 +00:00
|
|
|
'memory': self.memory,
|
|
|
|
'disk_size': self.disk_size,
|
|
|
|
'price': self.price(),
|
|
|
|
}
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def get_serialized_configs(cls):
|
|
|
|
return [cfg.serialize()
|
|
|
|
for cfg in cls.objects.all()]
|
|
|
|
|
|
|
|
def price(self):
|
2017-05-14 00:17:48 +00:00
|
|
|
price = self.disk_size * 0.6
|
2017-05-13 11:47:53 +00:00
|
|
|
price += self.cpu_cores * 5
|
|
|
|
price += self.memory * 2
|
|
|
|
return price
|
|
|
|
|
2017-06-29 14:34:40 +00:00
|
|
|
|
2018-07-01 20:30:23 +00:00
|
|
|
class OrderDetail(AssignPermissionsMixin, models.Model):
|
2018-07-01 17:23:05 +00:00
|
|
|
vm_template = models.ForeignKey(
|
|
|
|
VMTemplate, blank=True, null=True, default=None,
|
|
|
|
on_delete=models.SET_NULL
|
|
|
|
)
|
2018-07-01 16:33:10 +00:00
|
|
|
cores = models.IntegerField(default=0)
|
|
|
|
memory = models.IntegerField(default=0)
|
|
|
|
hdd_size = models.IntegerField(default=0)
|
|
|
|
ssd_size = models.IntegerField(default=0)
|
|
|
|
|
|
|
|
def __str__(self):
|
2018-07-01 17:46:21 +00:00
|
|
|
return "%s - %s, %s cores, %s GB RAM, %s GB SSD" % (
|
|
|
|
self.vm_template.name, self.vm_template.vm_type, self.cores,
|
|
|
|
self.memory, self.ssd_size
|
2018-07-01 16:33:10 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
|
2016-07-11 03:08:51 +00:00
|
|
|
class HostingOrder(AssignPermissionsMixin, models.Model):
|
2016-05-03 05:59:40 +00:00
|
|
|
ORDER_APPROVED_STATUS = 'Approved'
|
|
|
|
ORDER_DECLINED_STATUS = 'Declined'
|
|
|
|
|
2017-05-12 10:07:05 +00:00
|
|
|
vm_id = models.IntegerField(default=0)
|
2016-04-26 06:16:03 +00:00
|
|
|
customer = models.ForeignKey(StripeCustomer)
|
|
|
|
billing_address = models.ForeignKey(BillingAddress)
|
|
|
|
created_at = models.DateTimeField(auto_now_add=True)
|
|
|
|
approved = models.BooleanField(default=False)
|
2016-05-03 05:59:40 +00:00
|
|
|
last4 = models.CharField(max_length=4)
|
|
|
|
cc_brand = models.CharField(max_length=10)
|
2016-04-26 06:16:03 +00:00
|
|
|
stripe_charge_id = models.CharField(max_length=100, null=True)
|
2017-05-12 17:13:18 +00:00
|
|
|
price = models.FloatField()
|
2017-08-17 16:16:36 +00:00
|
|
|
subscription_id = models.CharField(max_length=100, null=True)
|
2018-04-16 01:23:09 +00:00
|
|
|
vm_pricing = models.ForeignKey(VMPricing)
|
2018-07-01 20:30:23 +00:00
|
|
|
order_detail = models.ForeignKey(
|
|
|
|
OrderDetail, null=True, blank=True, default=None,
|
2018-07-01 17:23:05 +00:00
|
|
|
on_delete=models.SET_NULL
|
|
|
|
)
|
2016-04-26 06:16:03 +00:00
|
|
|
|
2016-07-11 03:08:51 +00:00
|
|
|
permissions = ('view_hostingorder',)
|
|
|
|
|
|
|
|
class Meta:
|
|
|
|
permissions = (
|
|
|
|
('view_hostingorder', 'View Hosting Order'),
|
|
|
|
)
|
|
|
|
|
2016-05-14 06:42:42 +00:00
|
|
|
def __str__(self):
|
|
|
|
return "%s" % (self.id)
|
|
|
|
|
2016-05-03 05:59:40 +00:00
|
|
|
@cached_property
|
|
|
|
def status(self):
|
|
|
|
return self.ORDER_APPROVED_STATUS if self.approved else self.ORDER_DECLINED_STATUS
|
|
|
|
|
2016-04-26 06:16:03 +00:00
|
|
|
@classmethod
|
2018-04-21 16:57:43 +00:00
|
|
|
def create(cls, price=None, vm_id=0, customer=None,
|
2018-04-16 01:36:56 +00:00
|
|
|
billing_address=None, vm_pricing=None):
|
2017-05-12 17:13:18 +00:00
|
|
|
instance = cls.objects.create(
|
|
|
|
price=price,
|
|
|
|
vm_id=vm_id,
|
|
|
|
customer=customer,
|
2018-04-16 01:36:56 +00:00
|
|
|
billing_address=billing_address,
|
|
|
|
vm_pricing=vm_pricing
|
2017-05-12 17:13:18 +00:00
|
|
|
)
|
2016-07-11 03:08:51 +00:00
|
|
|
instance.assign_permissions(customer.user)
|
2016-04-26 06:16:03 +00:00
|
|
|
return instance
|
|
|
|
|
|
|
|
def set_approved(self):
|
|
|
|
self.approved = True
|
|
|
|
self.save()
|
|
|
|
|
|
|
|
def set_stripe_charge(self, stripe_charge):
|
|
|
|
self.stripe_charge_id = stripe_charge.id
|
2016-05-03 05:59:40 +00:00
|
|
|
self.last4 = stripe_charge.source.last4
|
|
|
|
self.cc_brand = stripe_charge.source.brand
|
2016-04-26 06:16:03 +00:00
|
|
|
self.save()
|
|
|
|
|
2017-09-29 06:42:17 +00:00
|
|
|
def set_subscription_id(self, subscription_id, cc_details):
|
2017-08-17 16:16:36 +00:00
|
|
|
"""
|
2017-08-24 06:29:38 +00:00
|
|
|
When creating a Stripe subscription, we have subscription id.
|
|
|
|
We store this in the subscription_id field.
|
2017-09-29 06:42:17 +00:00
|
|
|
This method sets the subscription id
|
|
|
|
and the last4 and credit card brands used for this order.
|
2017-08-17 16:16:36 +00:00
|
|
|
|
2017-09-29 06:42:17 +00:00
|
|
|
:param subscription_id: Stripe's subscription id
|
2017-08-24 06:29:38 +00:00
|
|
|
:param cc_details: A dict containing card details
|
|
|
|
{last4, brand}
|
2017-08-17 16:16:36 +00:00
|
|
|
:return:
|
|
|
|
"""
|
2017-09-29 06:42:17 +00:00
|
|
|
self.subscription_id = subscription_id
|
2017-08-24 07:21:55 +00:00
|
|
|
self.last4 = cc_details.get('last4')
|
|
|
|
self.cc_brand = cc_details.get('brand')
|
2017-08-17 16:16:36 +00:00
|
|
|
self.save()
|
|
|
|
|
2017-05-11 05:11:33 +00:00
|
|
|
def get_cc_data(self):
|
|
|
|
return {
|
|
|
|
'last4': self.last4,
|
|
|
|
'cc_brand': self.cc_brand,
|
|
|
|
} if self.last4 and self.cc_brand else None
|
|
|
|
|
2016-04-23 07:22:44 +00:00
|
|
|
|
2017-05-04 04:19:32 +00:00
|
|
|
class UserHostingKey(models.Model):
|
|
|
|
user = models.ForeignKey(CustomUser)
|
|
|
|
public_key = models.TextField()
|
2017-08-17 16:16:36 +00:00
|
|
|
private_key = models.FileField(upload_to='private_keys', blank=True)
|
2017-05-04 04:19:32 +00:00
|
|
|
created_at = models.DateTimeField(auto_now_add=True)
|
|
|
|
name = models.CharField(max_length=100)
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
def generate_RSA(bits=2048):
|
|
|
|
'''
|
|
|
|
Generate an RSA keypair with an exponent of 65537 in PEM format
|
|
|
|
param: bits The key length in bits
|
|
|
|
Return private key and public key
|
|
|
|
'''
|
|
|
|
new_key = RSA.generate(2048, os.urandom)
|
|
|
|
public_key = new_key.publickey().exportKey("OpenSSH")
|
|
|
|
private_key = new_key.exportKey("PEM")
|
|
|
|
return private_key, public_key
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def generate_keys(cls):
|
|
|
|
private_key, public_key = cls.generate_RSA()
|
|
|
|
# self.public_key = public_key
|
|
|
|
# self.save(update_fields=['public_key'])
|
|
|
|
return private_key, public_key
|
|
|
|
|
2017-06-29 14:34:40 +00:00
|
|
|
|
2017-05-05 12:59:11 +00:00
|
|
|
class HostingBill(AssignPermissionsMixin, models.Model):
|
|
|
|
customer = models.ForeignKey(StripeCustomer)
|
|
|
|
billing_address = models.ForeignKey(BillingAddress)
|
2017-05-06 12:44:08 +00:00
|
|
|
total_price = models.FloatField(default=0.0)
|
2017-05-05 12:59:11 +00:00
|
|
|
|
|
|
|
permissions = ('view_hostingbill',)
|
|
|
|
|
|
|
|
class Meta:
|
|
|
|
permissions = (
|
|
|
|
('view_hostingbill', 'View Hosting Bill'),
|
|
|
|
)
|
|
|
|
|
|
|
|
def __str__(self):
|
|
|
|
return "%s" % (self.customer.user.email)
|
|
|
|
|
2017-05-09 02:41:45 +00:00
|
|
|
@classmethod
|
|
|
|
def create(cls, customer=None, billing_address=None):
|
2017-08-24 06:29:38 +00:00
|
|
|
instance = cls.objects.create(customer=customer,
|
|
|
|
billing_address=billing_address)
|
2017-05-09 02:41:45 +00:00
|
|
|
return instance
|
2017-09-24 18:30:45 +00:00
|
|
|
|
|
|
|
|
|
|
|
class VMDetail(models.Model):
|
|
|
|
user = models.ForeignKey(CustomUser)
|
|
|
|
vm_id = models.IntegerField(default=0)
|
|
|
|
disk_size = models.FloatField(default=0.0)
|
|
|
|
cores = models.FloatField(default=0.0)
|
|
|
|
memory = models.FloatField(default=0.0)
|
|
|
|
configuration = models.CharField(default='', max_length=25)
|
|
|
|
ipv4 = models.TextField(default='')
|
|
|
|
ipv6 = models.TextField(default='')
|
|
|
|
created_at = models.DateTimeField(auto_now_add=True)
|
|
|
|
terminated_at = models.DateTimeField(null=True)
|
2017-09-30 12:25:49 +00:00
|
|
|
|
|
|
|
def end_date(self):
|
2017-09-30 12:35:02 +00:00
|
|
|
end_date = self.terminated_at if self.terminated_at else timezone.now()
|
2017-09-30 12:38:02 +00:00
|
|
|
months = relativedelta(end_date, self.created_at).months or 1
|
2017-09-30 12:40:34 +00:00
|
|
|
end_date = self.created_at + relativedelta(months=months, days=-1)
|
2017-09-30 12:25:49 +00:00
|
|
|
return end_date
|