models.py 3.39 KB
Newer Older
1 2 3
# coding=utf-8

import logging
4
from django.db import models
5
from django.utils.translation import ugettext_lazy as _
6
from django.db.models.signals import post_delete
7 8 9 10 11 12 13 14
from model_utils.models import TimeStampedModel

from .tasks import StorageDriver

logger = logging.getLogger(__name__)


class DataStore(models.Model):
15 16
    """Collection of virtual disks.
    """
17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
    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):
32 33 34 35 36 37 38 39
    """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)
40
    type = models.CharField(max_length=10, choices=TYPES)
41
    size = models.IntegerField()
42 43 44
    base = models.ForeignKey('self', blank=True, null=True,
                             related_name='derivatives')
    ready = models.BooleanField(default=False)
45 46
    dev_num = models.CharField(default='a', max_length=1,
                               verbose_name="device number")
47 48 49 50 51 52

    class Meta:
        ordering = ['name']
        verbose_name = _('disk')
        verbose_name_plural = _('disks')

53 54 55 56 57 58 59 60 61 62 63 64 65 66
    @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]

67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85
    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 {
86
            'source': self.path,
87 88 89 90 91 92 93 94
            '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)

95 96 97
    def deploy(self):
        if self.ready:
            return
98

99 100 101 102 103 104 105 106 107 108 109
        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()
110 111

    @classmethod
112 113 114 115
    def delete_signal(cls, sender, instance, using, **kwargs):
        # TODO
        # StorageDriver.delete_disk.delay(instance.to_json()).get()
        pass
116 117

post_delete.connect(Disk.delete_signal, sender=Disk)