Move django-based uncloud to top-level
This commit is contained in:
		
					parent
					
						
							
								0560063326
							
						
					
				
			
			
				commit
				
					
						95d43f002f
					
				
			
		
					 265 changed files with 0 additions and 0 deletions
				
			
		
							
								
								
									
										198
									
								
								uncloud_vm/models.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										198
									
								
								uncloud_vm/models.py
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,198 @@
 | 
			
		|||
import uuid
 | 
			
		||||
 | 
			
		||||
from django.db import models
 | 
			
		||||
from django.contrib.auth import get_user_model
 | 
			
		||||
 | 
			
		||||
from uncloud_pay.models import Product, RecurringPeriod
 | 
			
		||||
from uncloud.models import UncloudModel, UncloudStatus
 | 
			
		||||
 | 
			
		||||
import uncloud_pay.models as pay_models
 | 
			
		||||
import uncloud_storage.models
 | 
			
		||||
 | 
			
		||||
class VMCluster(UncloudModel):
 | 
			
		||||
    uuid = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
 | 
			
		||||
    name = models.CharField(max_length=128, unique=True)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class VMHost(UncloudModel):
 | 
			
		||||
    uuid = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
 | 
			
		||||
 | 
			
		||||
    # 253 is the maximum DNS name length
 | 
			
		||||
    hostname = models.CharField(max_length=253, unique=True)
 | 
			
		||||
 | 
			
		||||
    vmcluster = models.ForeignKey(
 | 
			
		||||
        VMCluster, on_delete=models.CASCADE, editable=False, blank=True, null=True
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    # indirectly gives a maximum number of cores / VM - f.i. 32
 | 
			
		||||
    physical_cores = models.IntegerField(default=0)
 | 
			
		||||
 | 
			
		||||
    # determines the maximum usable cores - f.i. 320 if you overbook by a factor of 10
 | 
			
		||||
    usable_cores = models.IntegerField(default=0)
 | 
			
		||||
 | 
			
		||||
    # ram that can be used of the server
 | 
			
		||||
    usable_ram_in_gb = models.FloatField(default=0)
 | 
			
		||||
 | 
			
		||||
    status = models.CharField(
 | 
			
		||||
        max_length=32, choices=UncloudStatus.choices, default=UncloudStatus.PENDING
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    @property
 | 
			
		||||
    def vms(self):
 | 
			
		||||
        return VMProduct.objects.filter(vmhost=self)
 | 
			
		||||
 | 
			
		||||
    @property
 | 
			
		||||
    def used_ram_in_gb(self):
 | 
			
		||||
        return sum([vm.ram_in_gb for vm in VMProduct.objects.filter(vmhost=self)])
 | 
			
		||||
 | 
			
		||||
    @property
 | 
			
		||||
    def available_ram_in_gb(self):
 | 
			
		||||
        return self.usable_ram_in_gb - self.used_ram_in_gb
 | 
			
		||||
 | 
			
		||||
    @property
 | 
			
		||||
    def available_cores(self):
 | 
			
		||||
        return self.usable_cores - sum([vm.cores for vm in self.vms ])
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class VMProduct(Product):
 | 
			
		||||
    vmhost = models.ForeignKey(
 | 
			
		||||
        VMHost, on_delete=models.CASCADE, editable=False, blank=True, null=True
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    vmcluster = models.ForeignKey(
 | 
			
		||||
        VMCluster, on_delete=models.CASCADE, editable=False, blank=True, null=True
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    # VM-specific. The name is only intended for customers: it's a pain to
 | 
			
		||||
    # remember IDs (speaking from experience as ungleich customer)!
 | 
			
		||||
    name = models.CharField(max_length=32, blank=True, null=True)
 | 
			
		||||
    cores = models.IntegerField()
 | 
			
		||||
    ram_in_gb = models.FloatField()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    @property
 | 
			
		||||
    def recurring_price(self):
 | 
			
		||||
        return self.cores * 3 + self.ram_in_gb * 4
 | 
			
		||||
 | 
			
		||||
    def __str__(self):
 | 
			
		||||
        return "VM {} ({}): {} cores {} gb ram".format(self.uuid,
 | 
			
		||||
                                                       self.name,
 | 
			
		||||
                                                       self.cores,
 | 
			
		||||
                                                       self.ram_in_gb)
 | 
			
		||||
 | 
			
		||||
    @property
 | 
			
		||||
    def description(self):
 | 
			
		||||
        return "Virtual machine '{}': {} core(s), {}GB memory".format(
 | 
			
		||||
                self.name, self.cores, self.ram_in_gb)
 | 
			
		||||
 | 
			
		||||
    @staticmethod
 | 
			
		||||
    def allowed_recurring_periods():
 | 
			
		||||
        return list(filter(
 | 
			
		||||
            lambda pair: pair[0] in [RecurringPeriod.PER_YEAR,
 | 
			
		||||
                RecurringPeriod.PER_MONTH, RecurringPeriod.PER_HOUR],
 | 
			
		||||
            RecurringPeriod.choices))
 | 
			
		||||
 | 
			
		||||
    def __str__(self):
 | 
			
		||||
        return "VM {} ({} Cores/{} GB RAM) running on {} in cluster {}".format(
 | 
			
		||||
            self.uuid, self.cores, self.ram_in_gb,
 | 
			
		||||
            self.vmhost, self.vmcluster)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class VMWithOSProduct(VMProduct):
 | 
			
		||||
    pass
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class VMDiskImageProduct(UncloudModel):
 | 
			
		||||
    """
 | 
			
		||||
    Images are used for cloning/linking.
 | 
			
		||||
 | 
			
		||||
    They are the base for images.
 | 
			
		||||
 | 
			
		||||
    """
 | 
			
		||||
 | 
			
		||||
    uuid = models.UUIDField(
 | 
			
		||||
        primary_key=True, default=uuid.uuid4, editable=False
 | 
			
		||||
    )
 | 
			
		||||
    owner = models.ForeignKey(
 | 
			
		||||
        get_user_model(), on_delete=models.CASCADE, editable=False
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    name = models.CharField(max_length=256)
 | 
			
		||||
    is_os_image = models.BooleanField(default=False)
 | 
			
		||||
    is_public = models.BooleanField(default=False, editable=False) # only allow admins to set this
 | 
			
		||||
 | 
			
		||||
    size_in_gb = models.FloatField(null=True, blank=True)
 | 
			
		||||
    import_url = models.URLField(null=True, blank=True)
 | 
			
		||||
    image_source = models.CharField(max_length=128, null=True)
 | 
			
		||||
    image_source_type = models.CharField(max_length=128, null=True)
 | 
			
		||||
 | 
			
		||||
    storage_class = models.CharField(max_length=32,
 | 
			
		||||
                                     choices = uncloud_storage.models.StorageClass.choices,
 | 
			
		||||
                                     default = uncloud_storage.models.StorageClass.SSD)
 | 
			
		||||
 | 
			
		||||
    status = models.CharField(
 | 
			
		||||
        max_length=32, choices=UncloudStatus.choices, default=UncloudStatus.PENDING
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    def __str__(self):
 | 
			
		||||
        return "VMDiskImage {} ({}): {} gb".format(self.uuid,
 | 
			
		||||
                                                   self.name,
 | 
			
		||||
                                                   self.size_in_gb)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class VMDiskProduct(Product):
 | 
			
		||||
    """
 | 
			
		||||
    The VMDiskProduct is attached to a VM.
 | 
			
		||||
 | 
			
		||||
    It is based on a VMDiskImageProduct that will be used as a basis.
 | 
			
		||||
 | 
			
		||||
    It can be enlarged, but not shrinked compared to the VMDiskImageProduct.
 | 
			
		||||
    """
 | 
			
		||||
 | 
			
		||||
    vm = models.ForeignKey(VMProduct, on_delete=models.CASCADE)
 | 
			
		||||
    image = models.ForeignKey(VMDiskImageProduct, on_delete=models.CASCADE)
 | 
			
		||||
 | 
			
		||||
    size_in_gb = models.FloatField(blank=True)
 | 
			
		||||
 | 
			
		||||
    @property
 | 
			
		||||
    def description(self):
 | 
			
		||||
        return "Disk for VM '{}': {}GB".format(self.vm.name, self.size_in_gb)
 | 
			
		||||
 | 
			
		||||
    @property
 | 
			
		||||
    def recurring_price(self):
 | 
			
		||||
        return (self.size_in_gb / 10) * 3.5
 | 
			
		||||
 | 
			
		||||
    # Sample code for clean method
 | 
			
		||||
 | 
			
		||||
    # Ensures that a VMDiskProduct can only be created from a VMDiskImageProduct
 | 
			
		||||
    # that is in status 'active'
 | 
			
		||||
 | 
			
		||||
    # def clean(self):
 | 
			
		||||
    #     if self.image.status != 'active':
 | 
			
		||||
    #         raise ValidationError({
 | 
			
		||||
    #             'image': 'VM Disk must be created from an active disk image.'
 | 
			
		||||
    #         })
 | 
			
		||||
 | 
			
		||||
    def save(self, *args, **kwargs):
 | 
			
		||||
        self.full_clean()
 | 
			
		||||
        super().save(*args, **kwargs)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class VMNetworkCard(models.Model):
 | 
			
		||||
    vm = models.ForeignKey(VMProduct, on_delete=models.CASCADE)
 | 
			
		||||
 | 
			
		||||
    mac_address = models.BigIntegerField()
 | 
			
		||||
 | 
			
		||||
    ip_address = models.GenericIPAddressField(blank=True,
 | 
			
		||||
                                              null=True)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class VMSnapshotProduct(Product):
 | 
			
		||||
    gb_ssd = models.FloatField(editable=False)
 | 
			
		||||
    gb_hdd = models.FloatField(editable=False)
 | 
			
		||||
 | 
			
		||||
    vm = models.ForeignKey(VMProduct,
 | 
			
		||||
                           related_name='snapshots',
 | 
			
		||||
                           on_delete=models.CASCADE)
 | 
			
		||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue