~ubuntu-branches/ubuntu/raring/horizon/raring

« back to all changes in this revision

Viewing changes to openstack_dashboard/usage/quotas.py

  • Committer: Package Import Robot
  • Author(s): Chuck Short, Adam Gandelman, Chuck Short
  • Date: 2012-11-23 08:49:14 UTC
  • mfrom: (1.1.22)
  • Revision ID: package-import@ubuntu.com-20121123084914-95m0mzmiicdw64ti
Tags: 2013.1~g1-0ubuntu1
[ Adam Gandelman ]
* debian/patches/add_juju_settings_pannel.patch: Disable during
  Grizzly dev. cycle. 

[ Chuck Short ]
* New upstream relase.
* Refreshed patches.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
from collections import defaultdict
 
2
import itertools
 
3
 
 
4
from horizon import exceptions
 
5
from horizon.utils.memoized import memoized
 
6
 
 
7
from openstack_dashboard.api import nova, cinder
 
8
from openstack_dashboard.api.base import is_service_enabled, QuotaSet
 
9
 
 
10
 
 
11
class QuotaUsage(dict):
 
12
    """ Tracks quota limit, used, and available for a given set of quotas."""
 
13
 
 
14
    def __init__(self):
 
15
        self.usages = defaultdict(dict)
 
16
 
 
17
    def __getitem__(self, key):
 
18
        return self.usages[key]
 
19
 
 
20
    def __setitem__(self, key, value):
 
21
        raise NotImplemented("Directly setting QuotaUsage values is not "
 
22
                             "supported. Please use the add_quota and "
 
23
                             "tally methods.")
 
24
 
 
25
    def __repr__(self):
 
26
        return repr(dict(self.usages))
 
27
 
 
28
    def add_quota(self, quota):
 
29
        """ Adds an internal tracking reference for the given quota. """
 
30
        if quota.limit is None:
 
31
            # Handle "unlimited" quotas.
 
32
            self.usages[quota.name]['quota'] = float("inf")
 
33
            self.usages[quota.name]['available'] = float("inf")
 
34
        else:
 
35
            self.usages[quota.name]['quota'] = int(quota.limit)
 
36
 
 
37
    def tally(self, name, value):
 
38
        """ Adds to the "used" metric for the given quota. """
 
39
        value = value or 0  # Protection against None.
 
40
        # Start at 0 if this is the first value.
 
41
        if 'used' not in self.usages[name]:
 
42
            self.usages[name]['used'] = 0
 
43
        # Increment our usage and update the "available" metric.
 
44
        self.usages[name]['used'] += int(value)  # Fail if can't coerce to int.
 
45
        self.update_available(name)
 
46
 
 
47
    def update_available(self, name):
 
48
        """ Updates the "available" metric for the given quota. """
 
49
        available = self.usages[name]['quota'] - self.usages[name]['used']
 
50
        if available < 0:
 
51
            available = 0
 
52
        self.usages[name]['available'] = available
 
53
 
 
54
 
 
55
def _get_quota_data(request, method_name, disabled_quotas=[]):
 
56
    quotasets = []
 
57
    tenant_id = request.user.tenant_id
 
58
    quotasets.append(getattr(nova, method_name)(request, tenant_id))
 
59
    qs = QuotaSet()
 
60
    if 'volumes' not in disabled_quotas:
 
61
        quotasets.append(getattr(cinder, method_name)(request, tenant_id))
 
62
    for quota in itertools.chain(*quotasets):
 
63
        if quota.name not in disabled_quotas:
 
64
            qs[quota.name] = quota.limit
 
65
    return qs
 
66
 
 
67
 
 
68
def get_default_quota_data(request, disabled_quotas=[]):
 
69
    return _get_quota_data(request, "default_quota_get", disabled_quotas)
 
70
 
 
71
 
 
72
def get_tenant_quota_data(request, disabled_quotas=[]):
 
73
    return _get_quota_data(request, "tenant_quota_get", disabled_quotas)
 
74
 
 
75
 
 
76
@memoized
 
77
def tenant_quota_usages(request):
 
78
    # Get our quotas and construct our usage object.
 
79
    disabled_quotas = []
 
80
    if not is_service_enabled(request, 'volume'):
 
81
        disabled_quotas.extend(['volumes', 'gigabytes'])
 
82
 
 
83
    usages = QuotaUsage()
 
84
    for quota in get_tenant_quota_data(request, disabled_quotas):
 
85
        usages.add_quota(quota)
 
86
 
 
87
    # Get our usages.
 
88
    floating_ips = nova.tenant_floating_ip_list(request)
 
89
    flavors = dict([(f.id, f) for f in nova.flavor_list(request)])
 
90
    instances = nova.server_list(request)
 
91
    # Fetch deleted flavors if necessary.
 
92
    missing_flavors = [instance.flavor['id'] for instance in instances
 
93
                       if instance.flavor['id'] not in flavors]
 
94
    for missing in missing_flavors:
 
95
        if missing not in flavors:
 
96
            try:
 
97
                flavors[missing] = nova.flavor_get(request, missing)
 
98
            except:
 
99
                flavors[missing] = {}
 
100
                exceptions.handle(request, ignore=True)
 
101
 
 
102
    usages.tally('instances', len(instances))
 
103
    usages.tally('floating_ips', len(floating_ips))
 
104
 
 
105
    if 'volumes' not in disabled_quotas:
 
106
        volumes = cinder.volume_list(request)
 
107
        usages.tally('gigabytes', sum([int(v.size) for v in volumes]))
 
108
        usages.tally('volumes', len(volumes))
 
109
 
 
110
    # Sum our usage based on the flavors of the instances.
 
111
    for flavor in [flavors[instance.flavor['id']] for instance in instances]:
 
112
        usages.tally('cores', getattr(flavor, 'vcpus', None))
 
113
        usages.tally('ram', getattr(flavor, 'ram', None))
 
114
 
 
115
    return usages