Statistics
| Branch: | Tag: | Revision:

root / logic / credits.py @ dfd19c2d

History | View | Annotate | Download (4 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 09c936a7 Vassilios Karakoidas
9 8d97deff Vassilios Karakoidas
from db.models import Debit, FlavorCost
10 c8926262 Vassilios Karakoidas
11 7b7f9205 Vassilios Karakoidas
from django.db import transaction
12 c8926262 Vassilios Karakoidas
13 7b7f9205 Vassilios Karakoidas
@transaction.commit_on_success
14 7b7f9205 Vassilios Karakoidas
def debit_account(user , amount, vm, description):
15 7b7f9205 Vassilios Karakoidas
    """Charges the user with the specified amount of credits for a vm (resource)"""
16 92c53da1 Vassilios Karakoidas
    date_now = datetime.now()
17 7b7f9205 Vassilios Karakoidas
    user.credit = user.credit - amount
18 7b7f9205 Vassilios Karakoidas
    user.save()
19 7b7f9205 Vassilios Karakoidas
20 7b7f9205 Vassilios Karakoidas
    # then write the debit entry
21 7b7f9205 Vassilios Karakoidas
    debit = Debit()
22 7b7f9205 Vassilios Karakoidas
    debit.user = user
23 7b7f9205 Vassilios Karakoidas
    debit.vm = vm
24 7b7f9205 Vassilios Karakoidas
    debit.when = date_now
25 7b7f9205 Vassilios Karakoidas
    debit.description = description
26 7b7f9205 Vassilios Karakoidas
    debit.save()
27 7b7f9205 Vassilios Karakoidas
28 7b7f9205 Vassilios Karakoidas
29 7b7f9205 Vassilios Karakoidas
@transaction.commit_on_success
30 7b7f9205 Vassilios Karakoidas
def credit_account(self, amount, creditor, description):
31 7b7f9205 Vassilios Karakoidas
    """No clue :)"""
32 7b7f9205 Vassilios Karakoidas
    return
33 92c53da1 Vassilios Karakoidas
34 92c53da1 Vassilios Karakoidas
35 92c53da1 Vassilios Karakoidas
@transaction.commit_on_success
36 92c53da1 Vassilios Karakoidas
def charge(vm):
37 92c53da1 Vassilios Karakoidas
    """Charges the owner of this VM.
38 92c53da1 Vassilios Karakoidas

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

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