052aa55d34
There are no longer two separate projects living inside the horizon repository. There is a single project now with a single setup.py, single README, etc. The openstack-dashboard/dashboard django project is now named "openstack_dashboard" and lives as an example project in the topmost horizon directory. The "horizon/horizon" directory has been bumped up a level and now is directly on the path when the root horizon directory is on your python path. Javascript media which the horizon module directly relies upon now ships in the horizon/static dir rather than openstack-dashboard/dashboard/static. All the corresponding setup, installation, build, and env scripts have been updated accordingly. Implements blueprint unified-packaging. Change-Id: Ieed8e3c777432cd046c3e0298869a9428756ab62
142 lines
4.9 KiB
Python
142 lines
4.9 KiB
Python
from __future__ import division
|
|
|
|
import datetime
|
|
import logging
|
|
|
|
from dateutil.relativedelta import relativedelta
|
|
from django.contrib import messages
|
|
from django.utils.translation import ugettext as _
|
|
|
|
from horizon import api
|
|
from horizon import exceptions
|
|
from horizon import forms
|
|
from horizon import time
|
|
|
|
|
|
LOG = logging.getLogger(__name__)
|
|
|
|
|
|
class BaseUsage(object):
|
|
show_terminated = False
|
|
|
|
def __init__(self, request, tenant_id=None):
|
|
self.tenant_id = tenant_id or request.user.tenant_id
|
|
self.request = request
|
|
self.summary = {}
|
|
self.usage_list = []
|
|
|
|
@property
|
|
def today(self):
|
|
return time.today()
|
|
|
|
@staticmethod
|
|
def get_datetime(date, now=False):
|
|
if now:
|
|
now = time.utcnow()
|
|
current_time = time.time(now.hour, now.minute, now.second)
|
|
else:
|
|
current_time = time.time()
|
|
return datetime.datetime.combine(date, current_time)
|
|
|
|
@staticmethod
|
|
def get_start(year, month, day=1):
|
|
return datetime.date(year, month, day)
|
|
|
|
@staticmethod
|
|
def get_end(year, month, day=1):
|
|
period = relativedelta(months=1)
|
|
date_end = BaseUsage.get_start(year, month, day) + period
|
|
if date_end > time.today():
|
|
date_end = time.today()
|
|
return date_end
|
|
|
|
def get_instances(self):
|
|
instance_list = []
|
|
[instance_list.extend(u.server_usages) for u in self.usage_list]
|
|
return instance_list
|
|
|
|
def get_date_range(self):
|
|
if not hasattr(self, "start") or not hasattr(self, "end"):
|
|
args = (self.today.year, self.today.month)
|
|
form = self.get_form()
|
|
if form.is_valid():
|
|
args = (int(form.cleaned_data['year']),
|
|
int(form.cleaned_data['month']))
|
|
self.start = self.get_start(*args)
|
|
self.end = self.get_end(*args)
|
|
return self.start, self.end
|
|
|
|
def get_form(self):
|
|
if not hasattr(self, 'form'):
|
|
if (any(key in ['month', 'year']
|
|
for key in self.request.GET.keys())):
|
|
# bound form
|
|
self.form = forms.DateForm(self.request.GET)
|
|
else:
|
|
# non-bound form
|
|
self.form = forms.DateForm(initial={
|
|
'month': self.today.month,
|
|
'year': self.today.year})
|
|
return self.form
|
|
|
|
def get_usage_list(self, start, end):
|
|
raise NotImplementedError("You must define a get_usage method.")
|
|
|
|
def summarize(self, start, end):
|
|
if start <= end <= time.today():
|
|
# Convert to datetime.datetime just for API call.
|
|
start = BaseUsage.get_datetime(start)
|
|
end = BaseUsage.get_datetime(end, now=True)
|
|
try:
|
|
self.usage_list = self.get_usage_list(start, end)
|
|
except:
|
|
exceptions.handle(self.request,
|
|
_('Unable to retrieve usage information.'))
|
|
else:
|
|
messages.info(self.request,
|
|
_("You are viewing data for the future, "
|
|
"which may or may not exist."))
|
|
|
|
for tenant_usage in self.usage_list:
|
|
tenant_summary = tenant_usage.get_summary()
|
|
for key, value in tenant_summary.items():
|
|
self.summary.setdefault(key, 0)
|
|
self.summary[key] += value
|
|
|
|
def csv_link(self):
|
|
return "?date_month=%s&date_year=%s&format=csv" % self.get_date_range()
|
|
|
|
|
|
class GlobalUsage(BaseUsage):
|
|
show_terminated = True
|
|
|
|
def get_usage_list(self, start, end):
|
|
return api.usage_list(self.request, start, end)
|
|
|
|
|
|
class TenantUsage(BaseUsage):
|
|
attrs = ('memory_mb', 'vcpus', 'uptime',
|
|
'hours', 'local_gb')
|
|
|
|
def get_usage_list(self, start, end):
|
|
show_terminated = self.request.GET.get('show_terminated',
|
|
self.show_terminated)
|
|
instances = []
|
|
terminated_instances = []
|
|
usage = api.usage_get(self.request, self.tenant_id, start, end)
|
|
# Attribute may not exist if there are no instances
|
|
if hasattr(usage, 'server_usages'):
|
|
now = datetime.datetime.now()
|
|
for server_usage in usage.server_usages:
|
|
# This is a way to phrase uptime in a way that is compatible
|
|
# with the 'timesince' filter. (Use of local time intentional.)
|
|
server_uptime = server_usage['uptime']
|
|
total_uptime = now - datetime.timedelta(seconds=server_uptime)
|
|
server_usage['uptime_at'] = total_uptime
|
|
if server_usage['ended_at'] and not show_terminated:
|
|
terminated_instances.append(server_usage)
|
|
else:
|
|
instances.append(server_usage)
|
|
usage.server_usages = instances
|
|
return (usage,)
|