Merge branch 'master' of ssh://git.planet-lab.org/git/plstackapi
[plstackapi.git] / planetstack / tests / generate_billing_sample.py
1 """
2     Basic Sliver Test
3
4     1) Create a slice1
5     2) Create sliver1 on slice1
6 """
7
8 import datetime
9 import os
10 import operator
11 import pytz
12 import json
13 import random
14 import sys
15 import time
16
17 MINUTE_SECONDS = 60
18 HOUR_SECONDS = MINUTE_SECONDS * 60
19 DAY_SECONDS = HOUR_SECONDS * 24
20 MONTH_SECONDS = DAY_SECONDS * 30
21
22
23 sys.path.append("/opt/planetstack")
24 #sys.path.append("/home/smbaker/projects/vicci/plstackapi/planetstack")
25
26 os.environ.setdefault("DJANGO_SETTINGS_MODULE", "planetstack.settings")
27 #from openstack.manager import OpenStackManager
28 from core.models import Slice, Sliver, ServiceClass, Reservation, Tag, Network, User, Node, Image, Deployment, Site, NetworkTemplate, NetworkSlice
29 from core.models import Invoice, Charge, Account, UsableObject, Payment
30
31 def delete_all(model):
32    for item in model.objects.all():
33        item.delete()
34
35 def get_usable_object(name):
36    objs = UsableObject.objects.filter(name=name)
37    if objs:
38        return objs[0]
39    obj = UsableObject(name=name)
40    obj.save()
41    return obj
42
43 def generate_invoice(account, batch):
44    invoice = Invoice(date=batch[-1].date, account=account)
45    invoice.save()
46    for charge in batch:
47        charge.invoice = invoice
48        charge.state = "invoiced"
49        charge.save()
50
51 def generate_invoices(account):
52    invoices = sorted(Invoice.objects.filter(account=account), key=operator.attrgetter('date'))
53    charges = sorted(Charge.objects.filter(account=account, state="pending"), key=operator.attrgetter('date'))
54
55    if invoices:
56        latest_invoice_date = invoices[-1].date()
57    else:
58        latest_invoice_date = None
59
60    batch = []
61    last_week = 0
62    for charge in charges:
63        # check to see if we crossed a week boundary. If we did, then generate
64        # an invoice for the last week's batch of charges
65        week = charge.date.isocalendar()[1]
66        if (week != last_week) and (batch):
67            generate_invoice(account, batch)
68            batch = []
69            last_week = week
70        batch.append(charge)
71
72    # we might still have last week's data batched up, and no data for this week
73    # if so, invoice the batch
74    this_week = datetime.datetime.now().isocalendar()[1]
75    if (this_week != last_week) and (batch):
76        generate_invoice(account, batch)
77
78 def generate_payments(account):
79     invoices = Invoice.objects.filter(account=account)
80     for invoice in invoices:
81         # let's be optomistic and assume everyone pays exactly two weeks after
82         # receiving an invoice
83         payment_time = int(invoice.date.strftime("%s")) + 14 * DAY_SECONDS
84         if payment_time < time.time():
85              payment_time = datetime.datetime.utcfromtimestamp(payment_time).replace(tzinfo=pytz.utc)
86              payment = Payment(account=account, amount=invoice.amount, date=payment_time)
87              payment.save()
88
89 delete_all(Invoice)
90 delete_all(Charge)
91 delete_all(Payment)
92 delete_all(Account)
93 delete_all(UsableObject)
94
95 for site in Site.objects.all():
96     # only create accounts for sites where some slices exist
97     if len(site.slices.all()) > 0:
98         account = Account(site=site)
99         account.save()
100
101 for slice in Slice.objects.all():
102     site = slice.site
103     account = site.accounts.all()[0]
104     serviceClass =slice.serviceClass
105
106     if not (slice.name in ["DnsRedir", "DnsDemux", "HyperCache"]):
107         continue
108
109     now = int(time.time())/HOUR_SECONDS*HOUR_SECONDS
110
111     charge_kind=None
112     for resource in slice.serviceClass.resources.all():
113         if resource.name == "cpu.cores":
114             charge_kind = "reservation"
115             cost = resource.cost
116         elif (resource.name == "cycles") or (resource.name == "Cycles"):
117             charge_kind = "besteffort"
118             cost = resource.cost
119
120     if not charge_kind:
121         print "failed to find resource for", slice.serviceClass
122         continue
123
124     for sliver in slice.slivers.all():
125         hostname = sliver.node.name
126         for i in range(now-MONTH_SECONDS, now, HOUR_SECONDS):
127             if charge_kind == "besteffort":
128                 core_hours = random.randint(1,60)/100.0
129             else:
130                 core_hours = 1
131
132             amount = core_hours * cost
133
134             object = get_usable_object(hostname)
135
136             date = datetime.datetime.utcfromtimestamp(i).replace(tzinfo=pytz.utc)
137
138             charge = Charge(account=account, slice=slice, kind=charge_kind, state="pending", date=date, object=object, coreHours=core_hours, amount=amount)
139             charge.save()
140
141 for account in Account.objects.all():
142     generate_invoices(account)
143     generate_payments(account)
144
145
146