# coding=utf-8 import logging from django.db import models from django.utils.translation import ugettext_lazy as _ from django.db.models.signals import post_delete from model_utils.models import TimeStampedModel from .tasks import StorageDriver logger = logging.getLogger(__name__) class DataStore(models.Model): """Collection of virtual disks. """ name = models.CharField(max_length=100, unique=True, verbose_name=_('name')) path = models.CharField(max_length=200, unique=True, verbose_name=_('path')) class Meta: ordering = ['name'] verbose_name = _('datastore') verbose_name_plural = _('datastores') def __unicode__(self): return u'%s (%s)' % (self.name, self.path) class Disk(TimeStampedModel): """A virtual disk. """ TYPES = [('qcow2-norm', 'qcow2 normal'), ('qcow2-snap', 'qcow2 snapshot'), ('iso', 'iso'), ('raw-ro', 'raw read-only'), ('raw-rw', 'raw')] name = models.CharField(max_length=100, verbose_name=_('name')) filename = models.CharField(max_length=256, unique=True, verbose_name=_('filename')) datastore = models.ForeignKey(DataStore) type = models.CharField(max_length=10, choices=TYPES) size = models.IntegerField() base = models.ForeignKey('self', blank=True, null=True, related_name='derivatives') ready = models.BooleanField(default=False) dev_num = models.CharField(default='a', max_length=1, verbose_name="device number") class Meta: ordering = ['name'] verbose_name = _('disk') verbose_name_plural = _('disks') @property def path(self): return self.datastore.path + '/' + self.filename @property def format(self): return { 'qcow2-norm': 'qcow2', 'qcow2-snap': 'qcow2', 'iso': 'iso', 'raw-ro': 'raw', 'raw-rw': 'raw', }[self.type] def get_exclusive(self): """Get an instance of the disk for exclusive usage. It might mean copying the disk, creating a snapshot or creating a symbolic link to a read-only image. """ # TODO implement (or call) logic return self @property def device_type(self): return { 'qcow2': 'vd', 'raw': 'vd', 'iso': 'hd', }[self.format] def get_vmdisk_desc(self): return { 'source': self.path, 'driver_type': self.format, 'driver_cache': 'default', 'target_device': self.device_type + self.dev_num } def __unicode__(self): return u"%s (#%d)" % (self.name, self.id) def deploy(self): if self.ready: return disk_desc = { 'name': self.name, 'dir': self.datastore.path, 'format': self.format, 'size': self.size, 'base_name': self.base.name if self.base else None, 'type': self.type } StorageDriver.create_disk.delay(disk_desc).get() self.ready = True self.save() @classmethod def delete_signal(cls, sender, instance, using, **kwargs): # TODO # StorageDriver.delete_disk.delay(instance.to_json()).get() pass post_delete.connect(Disk.delete_signal, sender=Disk)