Statistics
| Branch: | Tag: | Revision:

root / db / models.py @ a31ff6cb

History | View | Annotate | Download (6.8 kB)

1
# vim: ts=4 sts=4 et ai sw=4 fileencoding=utf-8
2

    
3
from django.conf import settings
4
from django.db import models
5
from django.contrib.auth.models import User
6
from django.utils.translation import gettext_lazy as _
7

    
8
import datetime
9

    
10
import vocabs
11

    
12
backend_prefix_id = settings.BACKEND_PREFIX_ID
13

    
14
#this needs to be called not only from inside VirtualMachine. 
15
#atm it is not working with the current ganeti naming - machine1, machine2
16
def id_from_instance_name(name):
17
    """ Returns VirtualMachine's Django id, given a ganeti machine name.
18

19
    Strips the ganeti prefix atm. Needs a better name!
20
    """
21
    return '%s' % (str(name).strip(backend_prefix_id))
22

    
23

    
24
class Limit(models.Model):
25
    description = models.CharField(max_length=45)
26
    
27
    class Meta:
28
        verbose_name = u'User limit'
29
    
30
    def __unicode__(self):
31
        return self.description
32

    
33

    
34
class OceanUser(models.Model):
35
    name = models.CharField(max_length=255)
36
    credit = models.IntegerField()
37
    quota = models.IntegerField()
38
    created = models.DateField()
39
    monthly_rate = models.IntegerField()
40
    #user = models.ForeignKey(User, unique=True)
41
    limits = models.ManyToManyField(Limit, through='UserLimit')
42
    
43
    class Meta:
44
        verbose_name = u'Ocean User'
45
    
46
    def __unicode__(self):
47
        return self.name
48
    
49
    def _total_hours(self, start, end):
50
        """Calculate duration in hours"""
51
        td = end - start
52
        sec = float(td.microseconds + (td.seconds + td.days * 24 * 3600) * 10**6) / float(10**6)
53
        
54
        return float(sec) / float(60.0*60.0)
55
    
56
    def charge_credits(self, cost, start, end):
57
        """Reduce user credits for specified duration. 
58
        Returns amount of credits remaining. Negative if the user surpassed his limit."""
59
        total_cost = float(cost)*self._total_hours(start, end)
60
        
61
        self.credit = self.credit - round(total_cost)
62
        rcredit = self.credit
63
                
64
        if self.credit < 0:
65
            self.credit = 0
66
        
67
        return rcredit 
68
    
69
    def allocate_credits(self):
70
        """Allocate credits. Add monthly rate to user credit reserve."""
71
        self.credit = self.credit + self.monthly_rate
72
        
73
        # ensure that the user has not more credits than his quota
74
        if self.credit > self.quota:
75
            self.credit = self.quota
76

    
77

    
78
class UserLimit(models.Model):
79
    user = models.ForeignKey(OceanUser)
80
    limit = models.ForeignKey(Limit)
81
    value = models.IntegerField()
82
    
83
    class Meta:
84
        unique_together = ('user', 'limit')
85
        verbose_name = u'Enforced limit for user'
86
    
87
    def __unicode__(self):
88
        return u'Limit %s for user %s: %d' % (self.limit, self.user, self.value)
89

    
90

    
91
class Flavor(models.Model):
92
    cpu = models.IntegerField(default=0)
93
    ram = models.IntegerField(default=0)
94
    disk = models.IntegerField(default=0)
95
    
96
    class Meta:
97
        verbose_name = u'Virtual machine flavor'
98
            
99
    def _get_name(self):
100
        """Returns flavor name"""
101
        return u'C%dR%dD%d' % ( self.cpu, self.ram, self.disk )
102

    
103
    def _get_cost_inactive(self):
104
        self._update_costs()
105
        return self._cost_inactive
106

    
107
    def _get_cost_active(self):
108
        self._update_costs()
109
        return self._cost_active
110
    
111
    def _update_costs(self):
112
        # if _cost
113
        if '_cost_active' not in dir(self):
114
            fch = FlavorCostHistory.objects.filter(flavor=self).order_by('-effective_from')[0]
115
            self._cost_active = fch.cost_active
116
            self._cost_inactive = fch.cost_inactive
117

    
118
    name = property(_get_name)
119
    cost_active = property(_get_cost_active)
120
    cost_inactive = property(_get_cost_inactive)
121

    
122
    def __unicode__(self):
123
        return self.name
124

    
125

    
126
class FlavorCostHistory(models.Model):
127
    cost_active = models.PositiveIntegerField()
128
    cost_inactive = models.PositiveIntegerField()
129
    effective_from = models.DateField()
130
    flavor = models.ForeignKey(Flavor)
131
    
132
    class Meta:
133
        verbose_name = u'Pricing history for flavors'
134
    
135
    def __unicode__(self):
136
        return u'Costs (up, down)=(%d, %d) for %s since %s' % ( cost_active, cost_inactive, flavor.name, effective_from )
137

    
138

    
139
class VirtualMachine(models.Model):
140
    name = models.CharField(max_length=255)
141
    created = models.DateTimeField()
142
    state = models.CharField(choices=vocabs.STATES, max_length=30)
143
    charged = models.DateTimeField()
144
    imageid = models.IntegerField()
145
    hostid = models.CharField(max_length=100)
146
    server_label = models.CharField(max_length=100)
147
    image_version = models.CharField(max_length=100)
148
    ipfour = models.IPAddressField()
149
    ipsix = models.CharField(max_length=100)
150
    owner = models.ForeignKey(OceanUser)
151
    flavor = models.ForeignKey(Flavor)
152
    
153
    class Meta:
154
        verbose_name = u'Virtual machine instance'
155
        get_latest_by = 'created'
156
    
157
    def __unicode__(self):
158
        return self.name
159

    
160
    def _get_backend_id(self):
161
        """Returns the backend id for this VM by prepending backend-prefix."""
162
        return '%s%s' % (backend_prefix_id, str(self.id))
163

    
164
    backend_id = property(_get_backend_id)
165

    
166

    
167
class VirtualMachineGroup(models.Model):
168
    "Groups of VM's for OceanUsers"
169
    name = models.CharField(max_length=255)
170
    owner = models.ForeignKey(User)
171
    machines = models.ManyToManyField(VirtualMachine)
172
    created = models.DateTimeField(help_text=_("Group creation date"), default=datetime.datetime.now)
173

    
174
    class Meta:
175
        verbose_name = u'Virtual Machine Group'
176
        verbose_name_plural = 'Virtual Machine Groups'
177
        ordering = ['name']
178
    
179
    def __unicode__(self):
180
        return self.name
181

    
182
class VirtualMachineMetadata(models.Model):
183
    meta_key = models.CharField(max_length=50)
184
    meta_value = models.CharField(max_length=500)
185
    vm = models.ForeignKey(VirtualMachine)
186
    
187
    class Meta:
188
        verbose_name = u'Key-value pair of metadata for a VM.'
189
    
190
    def __unicode__(self):
191
        return u'%s, %s for %s' % ( self.key, self.value, self.vm.name )
192

    
193

    
194
class AccountingLog(models.Model):
195
    vm = models.ForeignKey(VirtualMachine)
196
    date = models.DateTimeField()
197
    state = models.CharField(choices=vocabs.STATES, max_length=30)
198
    
199
    class Meta:
200
        verbose_name = u'Accounting log'
201

    
202
    def __unicode__(self):
203
        return u'%s %s %s' % ( self.vm.name, self.date, self.state )
204

    
205

    
206
class Image(models.Model):
207
    name = models.CharField(max_length=255, help_text=_('description'))
208
    updated = models.DateTimeField(help_text=_("Image update date"))
209
    created = models.DateTimeField(help_text=_("Image creation date"), default=datetime.datetime.now)
210
    state = models.CharField(choices=vocabs.STATES, max_length=30)
211
    description = models.TextField(help_text=_('description'))
212
    serverid = models.IntegerField(help_text=_('description'))
213
    vm = models.ForeignKey(VirtualMachine)
214
    
215
    class Meta:
216
        verbose_name = u'Image'
217

    
218
    def __unicode__(self):
219
        return u'%s' % ( self.name )