1
from __future__ import division
6
from dateutil.relativedelta import relativedelta
7
from django.contrib import messages
8
from django.utils.translation import ugettext as _
10
from horizon import api
11
from horizon import exceptions
12
from horizon import forms
13
from horizon import time
16
LOG = logging.getLogger(__name__)
19
class BaseUsage(object):
20
show_terminated = False
22
def __init__(self, request, tenant_id=None):
23
self.tenant_id = tenant_id or request.user.tenant_id
24
self.request = request
33
def get_datetime(date, now=False):
36
current_time = time.time(now.hour, now.minute, now.second)
38
current_time = time.time()
39
return datetime.datetime.combine(date, current_time)
42
def get_start(year, month, day=1):
43
return datetime.date(year, month, day)
46
def get_end(year, month, day=1):
47
period = relativedelta(months=1)
48
date_end = BaseUsage.get_start(year, month, day) + period
49
if date_end > time.today():
50
date_end = time.today()
53
def get_instances(self):
55
[instance_list.extend(u.server_usages) for u in self.usage_list]
58
def get_date_range(self):
59
if not hasattr(self, "start") or not hasattr(self, "end"):
60
args = (self.today.year, self.today.month)
61
form = self.get_form()
63
args = (int(form.cleaned_data['year']),
64
int(form.cleaned_data['month']))
65
self.start = self.get_start(*args)
66
self.end = self.get_end(*args)
67
return self.start, self.end
70
if not hasattr(self, 'form'):
71
if (any(key in ['month', 'year']
72
for key in self.request.GET.keys())):
74
self.form = forms.DateForm(self.request.GET)
77
self.form = forms.DateForm(initial={
78
'month': self.today.month,
79
'year': self.today.year})
82
def get_usage_list(self, start, end):
83
raise NotImplementedError("You must define a get_usage method.")
85
def summarize(self, start, end):
86
if start <= end <= time.today():
87
# Convert to datetime.datetime just for API call.
88
start = BaseUsage.get_datetime(start)
89
end = BaseUsage.get_datetime(end, now=True)
91
self.usage_list = self.get_usage_list(start, end)
93
exceptions.handle(self.request,
94
_('Unable to retrieve usage information.'))
96
messages.info(self.request,
97
_("You are viewing data for the future, "
98
"which may or may not exist."))
100
for tenant_usage in self.usage_list:
101
tenant_summary = tenant_usage.get_summary()
102
for key, value in tenant_summary.items():
103
self.summary.setdefault(key, 0)
104
self.summary[key] += value
107
return "?date_month=%s&date_year=%s&format=csv" % self.get_date_range()
110
class GlobalUsage(BaseUsage):
111
show_terminated = True
113
def get_usage_list(self, start, end):
114
return api.usage_list(self.request, start, end)
117
class TenantUsage(BaseUsage):
118
attrs = ('memory_mb', 'vcpus', 'uptime',
121
def get_usage_list(self, start, end):
122
show_terminated = self.request.GET.get('show_terminated',
123
self.show_terminated)
125
terminated_instances = []
126
usage = api.usage_get(self.request, self.tenant_id, start, end)
127
# Attribute may not exist if there are no instances
128
if hasattr(usage, 'server_usages'):
129
now = datetime.datetime.now()
130
for server_usage in usage.server_usages:
131
# This is a way to phrase uptime in a way that is compatible
132
# with the 'timesince' filter. (Use of local time intentional.)
133
server_uptime = server_usage['uptime']
134
total_uptime = now - datetime.timedelta(seconds=server_uptime)
135
server_usage['uptime_at'] = total_uptime
136
if server_usage['ended_at'] and not show_terminated:
137
terminated_instances.append(server_usage)
139
instances.append(server_usage)
140
usage.server_usages = instances