blob: b1413e34434280f58e7724450c037f02cd5a2cdb [file] [log] [blame]
Scott Baker43105042013-12-06 23:23:36 -08001"""
Scott Baker8a818df2014-05-13 17:06:28 -07002 Generates billing sample data
Scott Baker43105042013-12-06 23:23:36 -08003"""
4
5import datetime
6import os
7import operator
8import pytz
9import json
10import random
11import sys
12import time
13
Scott Baker8a818df2014-05-13 17:06:28 -070014# The granularity at which the charge collection system collects charges. Once
15# per hour makes for a very slow UI, so I upped it to once per 8 hours.
16CHARGE_HOURS = 8
17
Scott Baker43105042013-12-06 23:23:36 -080018MINUTE_SECONDS = 60
19HOUR_SECONDS = MINUTE_SECONDS * 60
20DAY_SECONDS = HOUR_SECONDS * 24
21MONTH_SECONDS = DAY_SECONDS * 30
22
23
24sys.path.append("/opt/planetstack")
25#sys.path.append("/home/smbaker/projects/vicci/plstackapi/planetstack")
26
27os.environ.setdefault("DJANGO_SETTINGS_MODULE", "planetstack.settings")
28#from openstack.manager import OpenStackManager
29from core.models import Slice, Sliver, ServiceClass, Reservation, Tag, Network, User, Node, Image, Deployment, Site, NetworkTemplate, NetworkSlice
30from core.models import Invoice, Charge, Account, UsableObject, Payment
31
32def delete_all(model):
33 for item in model.objects.all():
34 item.delete()
35
36def get_usable_object(name):
37 objs = UsableObject.objects.filter(name=name)
38 if objs:
39 return objs[0]
40 obj = UsableObject(name=name)
41 obj.save()
42 return obj
43
44def generate_invoice(account, batch):
45 invoice = Invoice(date=batch[-1].date, account=account)
46 invoice.save()
47 for charge in batch:
48 charge.invoice = invoice
49 charge.state = "invoiced"
50 charge.save()
51
52def generate_invoices(account):
53 invoices = sorted(Invoice.objects.filter(account=account), key=operator.attrgetter('date'))
54 charges = sorted(Charge.objects.filter(account=account, state="pending"), key=operator.attrgetter('date'))
55
56 if invoices:
57 latest_invoice_date = invoices[-1].date()
58 else:
59 latest_invoice_date = None
60
61 batch = []
62 last_week = 0
63 for charge in charges:
64 # check to see if we crossed a week boundary. If we did, then generate
65 # an invoice for the last week's batch of charges
66 week = charge.date.isocalendar()[1]
67 if (week != last_week) and (batch):
68 generate_invoice(account, batch)
69 batch = []
70 last_week = week
71 batch.append(charge)
72
73 # we might still have last week's data batched up, and no data for this week
74 # if so, invoice the batch
75 this_week = datetime.datetime.now().isocalendar()[1]
76 if (this_week != last_week) and (batch):
77 generate_invoice(account, batch)
78
79def generate_payments(account):
80 invoices = Invoice.objects.filter(account=account)
81 for invoice in invoices:
82 # let's be optomistic and assume everyone pays exactly two weeks after
83 # receiving an invoice
84 payment_time = int(invoice.date.strftime("%s")) + 14 * DAY_SECONDS
85 if payment_time < time.time():
86 payment_time = datetime.datetime.utcfromtimestamp(payment_time).replace(tzinfo=pytz.utc)
87 payment = Payment(account=account, amount=invoice.amount, date=payment_time)
88 payment.save()
89
Scott Baker8a818df2014-05-13 17:06:28 -070090print "deleting old stuff"
91
Scott Baker43105042013-12-06 23:23:36 -080092delete_all(Invoice)
93delete_all(Charge)
94delete_all(Payment)
95delete_all(Account)
96delete_all(UsableObject)
97
Scott Baker8a818df2014-05-13 17:06:28 -070098print "creating accounts"
99
Scott Baker43105042013-12-06 23:23:36 -0800100for site in Site.objects.all():
101 # only create accounts for sites where some slices exist
102 if len(site.slices.all()) > 0:
103 account = Account(site=site)
104 account.save()
105
Scott Baker8a818df2014-05-13 17:06:28 -0700106print "generating charges"
107
Scott Baker43105042013-12-06 23:23:36 -0800108for slice in Slice.objects.all():
109 site = slice.site
110 account = site.accounts.all()[0]
111 serviceClass =slice.serviceClass
112
Scott Baker8a818df2014-05-13 17:06:28 -0700113 if not (slice.name in ["DnsRedir", "DnsDemux", "HyperCache", "Hadoop", "Owl", "Stork", "Syndicate", "test-slice-1", "test-slice-2", "test", "test2"]):
Scott Baker43105042013-12-06 23:23:36 -0800114 continue
115
Scott Baker8a818df2014-05-13 17:06:28 -0700116 print " generating charges for", slice.name
117
Scott Baker43105042013-12-06 23:23:36 -0800118 now = int(time.time())/HOUR_SECONDS*HOUR_SECONDS
119
120 charge_kind=None
Sapan Bhatia0273d402014-11-11 19:25:29 -0500121 for resource in slice.serviceClass.serviceresources.all():
Scott Baker8a818df2014-05-13 17:06:28 -0700122 if resource.name == "numberCores":
Scott Baker43105042013-12-06 23:23:36 -0800123 charge_kind = "reservation"
124 cost = resource.cost
Scott Baker8a818df2014-05-13 17:06:28 -0700125 elif (charge_kind==None) and (resource.name == "cycles") or (resource.name == "Cycles"):
Scott Baker43105042013-12-06 23:23:36 -0800126 charge_kind = "besteffort"
127 cost = resource.cost
128
129 if not charge_kind:
130 print "failed to find resource for", slice.serviceClass
131 continue
132
Scott Baker8a818df2014-05-13 17:06:28 -0700133 for sliver in slice.slivers.all()[:4]: # only do up to 4 slivers; it's way too much data otherwise
Scott Baker43105042013-12-06 23:23:36 -0800134 hostname = sliver.node.name
Scott Baker8a818df2014-05-13 17:06:28 -0700135 for i in range(now-MONTH_SECONDS, now, CHARGE_HOURS*HOUR_SECONDS):
Scott Baker43105042013-12-06 23:23:36 -0800136 if charge_kind == "besteffort":
Scott Baker8a818df2014-05-13 17:06:28 -0700137 core_hours = random.randint(20,60)/100.0
Scott Baker43105042013-12-06 23:23:36 -0800138 else:
139 core_hours = 1
140
Scott Baker8a818df2014-05-13 17:06:28 -0700141 core_hours = core_hours * CHARGE_HOURS
142
143 amount = float(core_hours * cost) / 100.0
Scott Baker43105042013-12-06 23:23:36 -0800144
145 object = get_usable_object(hostname)
146
147 date = datetime.datetime.utcfromtimestamp(i).replace(tzinfo=pytz.utc)
148
149 charge = Charge(account=account, slice=slice, kind=charge_kind, state="pending", date=date, object=object, coreHours=core_hours, amount=amount)
150 charge.save()
151
Scott Baker8a818df2014-05-13 17:06:28 -0700152print "doing invoices and payments"
153
Scott Baker43105042013-12-06 23:23:36 -0800154for account in Account.objects.all():
155 generate_invoices(account)
156 generate_payments(account)
157
158
159