Statistics
| Branch: | Tag: | Revision:

root / logic / credits.py @ fc30c430

History | View | Annotate | Download (4.1 kB)

1 09c936a7 Vassilios Karakoidas
#
2 09c936a7 Vassilios Karakoidas
# Business Logic for all Credit related activity
3 09c936a7 Vassilios Karakoidas
#
4 09c936a7 Vassilios Karakoidas
# Copyright 2010 Greek Research and Technology Network
5 09c936a7 Vassilios Karakoidas
#
6 92c53da1 Vassilios Karakoidas
7 7b7f9205 Vassilios Karakoidas
from datetime import datetime
8 7b7f9205 Vassilios Karakoidas
from django.db import transaction
9 c8926262 Vassilios Karakoidas
10 234f8b07 Vangelis Koukis
from synnefo.db.models import Debit, FlavorCost
11 234f8b07 Vangelis Koukis
12 7b7f9205 Vassilios Karakoidas
@transaction.commit_on_success
13 7b7f9205 Vassilios Karakoidas
def debit_account(user , amount, vm, description):
14 7b7f9205 Vassilios Karakoidas
    """Charges the user with the specified amount of credits for a vm (resource)"""
15 92c53da1 Vassilios Karakoidas
    date_now = datetime.now()
16 7b7f9205 Vassilios Karakoidas
    user.credit = user.credit - amount
17 7b7f9205 Vassilios Karakoidas
    user.save()
18 7b7f9205 Vassilios Karakoidas
19 7b7f9205 Vassilios Karakoidas
    # then write the debit entry
20 7b7f9205 Vassilios Karakoidas
    debit = Debit()
21 7b7f9205 Vassilios Karakoidas
    debit.user = user
22 7b7f9205 Vassilios Karakoidas
    debit.vm = vm
23 7b7f9205 Vassilios Karakoidas
    debit.when = date_now
24 7b7f9205 Vassilios Karakoidas
    debit.description = description
25 7b7f9205 Vassilios Karakoidas
    debit.save()
26 7b7f9205 Vassilios Karakoidas
27 7b7f9205 Vassilios Karakoidas
28 7b7f9205 Vassilios Karakoidas
@transaction.commit_on_success
29 7b7f9205 Vassilios Karakoidas
def credit_account(self, amount, creditor, description):
30 7b7f9205 Vassilios Karakoidas
    """No clue :)"""
31 7b7f9205 Vassilios Karakoidas
    return
32 92c53da1 Vassilios Karakoidas
33 92c53da1 Vassilios Karakoidas
34 92c53da1 Vassilios Karakoidas
@transaction.commit_on_success
35 92c53da1 Vassilios Karakoidas
def charge(vm):
36 92c53da1 Vassilios Karakoidas
    """Charges the owner of this VM.
37 92c53da1 Vassilios Karakoidas

38 92c53da1 Vassilios Karakoidas
    Charges the owner of a VM for the period
39 92c53da1 Vassilios Karakoidas
    from vm.charged to datetime.now(), based on the
40 92c53da1 Vassilios Karakoidas
    current operating state.
41 92c53da1 Vassilios Karakoidas

42 92c53da1 Vassilios Karakoidas
    """
43 92c53da1 Vassilios Karakoidas
    charged_states = ('STARTED', 'STOPPED')
44 92c53da1 Vassilios Karakoidas
45 92c53da1 Vassilios Karakoidas
    start_datetime = vm.charged
46 92c53da1 Vassilios Karakoidas
    vm.charged = datetime.now()
47 92c53da1 Vassilios Karakoidas
48 92c53da1 Vassilios Karakoidas
    # Only charge for a specific set of states
49 dfd19c2d Vassilios Karakoidas
    if vm.operstate in charged_states:
50 92c53da1 Vassilios Karakoidas
        cost_list = []
51 92c53da1 Vassilios Karakoidas
52 92c53da1 Vassilios Karakoidas
        # remember, we charge only for Started and Stopped
53 dfd19c2d Vassilios Karakoidas
        if vm.operstate == 'STARTED':
54 8d97deff Vassilios Karakoidas
            cost_list = get_cost_active(vm.flavor, start_datetime, vm.charged)
55 dfd19c2d Vassilios Karakoidas
        elif vm.operstate == 'STOPPED':
56 8d97deff Vassilios Karakoidas
            cost_list = get_cost_inactive(vm.flavor, start_datetime, vm.charged)
57 92c53da1 Vassilios Karakoidas
58 92c53da1 Vassilios Karakoidas
        # find the total vost
59 92c53da1 Vassilios Karakoidas
        total_cost = sum([x[1] for x in cost_list])
60 92c53da1 Vassilios Karakoidas
61 92c53da1 Vassilios Karakoidas
        # add the debit entry
62 dfd19c2d Vassilios Karakoidas
        description = "Server = %s, charge = %d for state: %s" % (vm.name, total_cost, vm.operstate)
63 92c53da1 Vassilios Karakoidas
        debit_account(vm.owner, total_cost, vm, description)
64 92c53da1 Vassilios Karakoidas
65 92c53da1 Vassilios Karakoidas
    vm.save()
66 111b2cda Vassilios Karakoidas
67 8d97deff Vassilios Karakoidas
68 111b2cda Vassilios Karakoidas
def get_costs(vm, start_datetime, end_datetime, active):
69 111b2cda Vassilios Karakoidas
    """Return a list with FlavorCost objects for the specified duration"""
70 111b2cda Vassilios Karakoidas
    def between(enh_fc, a_date):
71 111b2cda Vassilios Karakoidas
        """Checks if a date is between a FlavorCost duration"""
72 111b2cda Vassilios Karakoidas
        if enh_fc.effective_from <= a_date and enh_fc.effective_to is None:
73 111b2cda Vassilios Karakoidas
            return True
74 111b2cda Vassilios Karakoidas
75 111b2cda Vassilios Karakoidas
        return enh_fc.effective_from <= a_date and enh_fc.effective_to >= a_date
76 111b2cda Vassilios Karakoidas
77 111b2cda Vassilios Karakoidas
    # Get the related FlavorCost objects, sorted.
78 111b2cda Vassilios Karakoidas
    price_list = FlavorCost.objects.filter(flavor=vm).order_by('effective_from')
79 111b2cda Vassilios Karakoidas
80 111b2cda Vassilios Karakoidas
    # add the extra field FlavorCost.effective_to
81 111b2cda Vassilios Karakoidas
    for idx in range(0, len(price_list)):
82 111b2cda Vassilios Karakoidas
        if idx + 1 == len(price_list):
83 111b2cda Vassilios Karakoidas
            price_list[idx].effective_to = None
84 111b2cda Vassilios Karakoidas
        else:
85 111b2cda Vassilios Karakoidas
            price_list[idx].effective_to = price_list[idx + 1].effective_from
86 111b2cda Vassilios Karakoidas
87 111b2cda Vassilios Karakoidas
    price_result = []
88 111b2cda Vassilios Karakoidas
    found_start = False
89 111b2cda Vassilios Karakoidas
90 111b2cda Vassilios Karakoidas
    # Find the affected FlavorCost, according to the
91 111b2cda Vassilios Karakoidas
    # dates, and put them in price_result
92 111b2cda Vassilios Karakoidas
    for p in price_list:
93 111b2cda Vassilios Karakoidas
        if between(p, start_datetime):
94 111b2cda Vassilios Karakoidas
            found_start = True
95 111b2cda Vassilios Karakoidas
            p.effective_from = start_datetime
96 111b2cda Vassilios Karakoidas
        if between(p, end_datetime):
97 111b2cda Vassilios Karakoidas
            p.effective_to = end_datetime
98 111b2cda Vassilios Karakoidas
            price_result.append(p)
99 111b2cda Vassilios Karakoidas
            break
100 111b2cda Vassilios Karakoidas
        if found_start:
101 111b2cda Vassilios Karakoidas
            price_result.append(p)
102 111b2cda Vassilios Karakoidas
103 111b2cda Vassilios Karakoidas
    results = []
104 111b2cda Vassilios Karakoidas
105 111b2cda Vassilios Karakoidas
    # Create the list and the result tuples
106 111b2cda Vassilios Karakoidas
    for p in price_result:
107 111b2cda Vassilios Karakoidas
        if active:
108 111b2cda Vassilios Karakoidas
            cost = p.cost_active
109 111b2cda Vassilios Karakoidas
        else:
110 111b2cda Vassilios Karakoidas
            cost = p.cost_inactive
111 111b2cda Vassilios Karakoidas
112 c8926262 Vassilios Karakoidas
        results.append( ( p.effective_from, calculate_cost(p.effective_from, p.effective_to, cost)) )
113 111b2cda Vassilios Karakoidas
114 111b2cda Vassilios Karakoidas
    return results
115 c8926262 Vassilios Karakoidas
116 c8926262 Vassilios Karakoidas
117 c8926262 Vassilios Karakoidas
def calculate_cost(start_date, end_date, cost):
118 c8926262 Vassilios Karakoidas
    """Calculate the total cost for the specified duration"""
119 c8926262 Vassilios Karakoidas
    td = end_date - start_date
120 c8926262 Vassilios Karakoidas
    sec = float(td.microseconds + (td.seconds + td.days * 24 * 3600) * 10**6) / float(10**6)
121 c8926262 Vassilios Karakoidas
    total_hours = float(sec) / float(60.0*60.0)
122 c8926262 Vassilios Karakoidas
    total_cost = float(cost)*total_hours
123 c8926262 Vassilios Karakoidas
124 c8926262 Vassilios Karakoidas
    return round(total_cost)
125 8d97deff Vassilios Karakoidas
126 8d97deff Vassilios Karakoidas
127 8d97deff Vassilios Karakoidas
def get_cost_active(vm, start_datetime, end_datetime):
128 8d97deff Vassilios Karakoidas
    """Returns a list with the active costs for the specified duration"""
129 8d97deff Vassilios Karakoidas
    return get_costs(vm, start_datetime, end_datetime, True)
130 8d97deff Vassilios Karakoidas
131 8d97deff Vassilios Karakoidas
132 8d97deff Vassilios Karakoidas
def get_cost_inactive(vm, start_datetime, end_datetime):
133 8d97deff Vassilios Karakoidas
    """Returns a list with the inactive costs for the specified duration"""
134 8d97deff Vassilios Karakoidas
    return get_costs(vm, start_datetime, end_datetime, False)