Revision 452d2391 db/models.py

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

  
8 7
import datetime
9 8

  
......
50 49
    
51 50
    def debit_account(self, amount, vm, description):
52 51
        """Charges the user with the specified amount of credits for a vm (resource)"""
53
        return
52
        date_now = datetime.datetime.now()
53

  
54
        # first reduce the user's credits and save
55
        self.credit = self.credit - amount
56
        self.save()
57

  
58
        # then write the debit entry!
59
        debit = Debit()
60

  
61
        debit.user = self
62
        debit.vm = vm
63
        debit.when = date_now
64
        debit.description = description
65

  
66
        debit.save()
54 67

  
55 68
    def credit_account(self, amount, creditor, description):
56 69
        """No clue :)"""
......
78 91
        verbose_name = u'Image'
79 92

  
80 93
    def __unicode__(self):
81
        return u'%s' % (self.name)
94
        return u'%s' % ( self.name, )
82 95

  
83 96

  
84 97
class ImageMetadata(models.Model):
......
107 120
        verbose_name = u'Enforced limit for user'
108 121
    
109 122
    def __unicode__(self):
110
        return u'Limit %s for user %s: %d' % (self.limit, self.user, self.value)
123
        return u'Limit %s for user %s: %d' % (self.value, self.user, self.value)
111 124

  
112 125

  
113 126
class Flavor(models.Model):
......
122 135
    def _get_name(self):
123 136
        """Returns flavor name (generated)"""
124 137
        return u'C%dR%dD%d' % (self.cpu, self.ram, self.disk)
125
        
126
    def _current_cost_active(self):
138

  
139
    def _current_cost(self, active):
140
        """Returns active/inactive cost value
141

  
142
        set active = True to get active cost and False for the inactive.
143

  
144
        """
127 145
        fch_list = FlavorCost.objects.filter(flavor=self).order_by('-effective_from')
128 146
        if len(fch_list) > 0:
129
            return fch_list[0].cost_active
130
        
147
            if active:
148
                return fch_list[0].cost_active
149
            else:
150
                return fch_list[0].cost_inactive
151

  
131 152
        return 0
153
        
154

  
155
    def _current_cost_active(self):
156
        """Returns current active cost (property method)"""
157
        return self._current_cost(True)
132 158

  
133 159
    def _current_cost_inactive(self):
134
        fch_list = FlavorCost.objects.filter(flavor=self).order_by('-effective_from')
135
        if len(fch_list) > 0:
136
            return fch_list[0].cost_inactive
137
        
138
        return 0
160
        """Returns current inactive cost (property method)"""
161
        return self._current_cost(False)
139 162

  
140 163
    name = property(_get_name)
141 164
    current_cost_active = property(_current_cost_active)
......
143 166

  
144 167
    def __unicode__(self):
145 168
        return self.name
146
    
169

  
170
    def _get_costs(self, start_datetime, end_datetime, active):
171
        """Return a list with FlavorCost objects for the specified duration"""
172
        def between(enh_fc, a_date):
173
            """Checks if a date is between a FlavorCost duration"""
174
            if enh_fc.effective_from <= a_date and enh_fc.effective_to is None:
175
                return True
176

  
177
            return enh_fc.effective_from <= a_date and enh_fc.effective_to >= a_date
178

  
179
        def calculate_cost(start_date, end_date, cost):
180
            """Calculate the total cost for the specified duration"""
181
            td = end_date - start_date
182
            sec = float(td.microseconds + (td.seconds + td.days * 24 * 3600) * 10**6) / float(10**6)
183
            total_hours = float(sec) / float(60.0*60.0)
184
            total_cost = float(cost)*total_hours
185

  
186
            return round(total_cost)
187

  
188
        price_list = FlavorCost.objects.filter(flavor=self).order_by('effective_from')
189

  
190
        for idx in range(0, len(price_list)):
191
            if idx + 1 == len(price_list):
192
                price_list[idx].effective_to = None
193
            else:
194
                price_list[idx].effective_to = price_list[idx + 1].effective_from
195

  
196
        price_result = []
197
        found_start = False
198

  
199
        for p in price_list:
200
            if between(p, start_datetime):
201
                found_start = True
202
                p.effective_from = start_datetime
203
            if between(p, end_datetime):
204
                p.effective_to = end_datetime
205
                price_result.append(p)
206
                break
207
            if found_start:
208
                price_result.append(p)
209

  
210
        results = []
211

  
212
        for p in price_result:
213
            if active:
214
                cost = p.cost_active
215
            else:
216
                cost = p.cost_inactive
217

  
218
            results.append( ( str(p.effective_from), calculate_cost(p.effective_from, p.effective_to, cost)) )
219

  
220
        return results
221

  
147 222
    def get_cost_active(self, start_datetime, end_datetime):
148 223
        """Returns a list with the active costs for the specified duration"""
149
        
150
        return []
151
        
224
        return self._get_costs(start_datetime, end_datetime, True)
225

  
152 226
    def get_cost_inactive(self, start_datetime, end_datetime):
153 227
        """Returns a list with the active costs for the specified duration"""
154
        return []
228
        return self._get_costs(start_datetime, end_datetime, False)
155 229

  
156 230

  
157 231
class FlavorCost(models.Model):
158 232
    cost_active = models.PositiveIntegerField('Active Cost')
159 233
    cost_inactive = models.PositiveIntegerField('Inactive Cost')
160
    effective_from = models.DateField()
234
    effective_from = models.DateTimeField()
161 235
    flavor = models.ForeignKey(Flavor)
162 236
    
163 237
    class Meta:
......
377 451
        Charges the VM owner from vm.charged to datetime.now()
378 452
        
379 453
        """
380
        return
454
        cur_datetime = datetime.datetime.now()
455
        cost_list = []
456

  
457
        if self._operstate == 'STARTED':
458
            cost_list = self.flavor.get_cost_active(self.charged, cur_datetime)
459
        else:
460
            cost_list = self.flavot.get_cost_inactive(self.charged, cur_datetime)
461

  
462
        total_cost = 0
463

  
464
        for cl in cost_list:
465
            total_cost = total_cost + cl[1]
466

  
467
        # still need to set correctly the message
468
        self.owner.debit_account(total_cost, self, "Charged Credits to User")
469

  
470
        self.charged = cur_datetime
471
        self.save()
381 472

  
382 473

  
383 474
class VirtualMachineGroup(models.Model):
......
419 510
        verbose_name = u'Accounting log'
420 511

  
421 512
    def __unicode__(self):
422
        return u'%s - %s - %s' % (self.vm.name, str(self.date), self.state)
513
        return u'%s - %s - %s - %s' % ( self.user.id, self.vm.name, str(self.when), self.description)
423 514

  
424 515

  
425 516
class Disk(models.Model):

Also available in: Unified diff