Statistics
| Branch: | Tag: | Revision:

root / snf-cyclades-app / synnefo / quotas / util.py @ dfc7aab7

History | View | Annotate | Download (8 kB)

1
# Copyright 2012, 2013 GRNET S.A. All rights reserved.
2
#
3
# Redistribution and use in source and binary forms, with or
4
# without modification, are permitted provided that the following
5
# conditions are met:
6
#
7
#   1. Redistributions of source code must retain the above
8
#      copyright notice, this list of conditions and the following
9
#      disclaimer.
10
#
11
#   2. Redistributions in binary form must reproduce the above
12
#      copyright notice, this list of conditions and the following
13
#      disclaimer in the documentation and/or other materials
14
#      provided with the distribution.
15
#
16
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
17
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
20
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27
# POSSIBILITY OF SUCH DAMAGE.
28
#
29
# The views and conclusions contained in the software and
30
# documentation are those of the authors and should not be
31
# interpreted as representing official policies, either expressed
32
# or implied, of GRNET S.A.
33

    
34
from django.db.models import Sum, Count, Q
35

    
36
from synnefo.db.models import VirtualMachine, Network, IPAddress
37
from synnefo.quotas import Quotaholder
38
from collections import defaultdict
39

    
40
QuotaDict = lambda: defaultdict(lambda: defaultdict(dict))
41

    
42
MiB = 2 ** 20
43
GiB = 2 ** 30
44

    
45

    
46
def get_db_holdings(user=None, project=None):
47
    """Get holdings from Cyclades DB."""
48
    holdings = QuotaDict()
49

    
50
    vms = VirtualMachine.objects.filter(deleted=False)
51
    networks = Network.objects.filter(deleted=False)
52
    floating_ips = IPAddress.objects.filter(deleted=False, floating_ip=True)
53

    
54
    if user is not None:
55
        vms = vms.filter(userid=user)
56
        networks = networks.filter(userid=user)
57
        floating_ips = floating_ips.filter(userid=user)
58

    
59
    if project is not None:
60
        vms = vms.filter(project=project)
61
        networks = networks.filter(project=project)
62
        floating_ips = floating_ips.filter(project=project)
63

    
64
    # Get resources related with VMs
65
    vm_resources = vms.values("userid", "project")\
66
        .annotate(num=Count("id"),
67
                  total_ram=Sum("flavor__ram"),
68
                  total_cpu=Sum("flavor__cpu"),
69
                  disk=Sum("flavor__disk"))
70

    
71
    for vm_res in vm_resources.iterator():
72
        user = vm_res['userid']
73
        project = vm_res['project']
74
        res = {"cyclades.vm": vm_res["num"],
75
               "cyclades.total_cpu": vm_res["total_cpu"],
76
               "cyclades.disk": vm_res["disk"] * GiB,
77
               "cyclades.total_ram": vm_res["total_ram"] * MiB}
78
        holdings[user][project] = res
79

    
80
    vm_active_resources = vms.values("userid", "project")\
81
        .filter(Q(operstate="STARTED") | Q(operstate="BUILD") |
82
                Q(operstate="ERROR"))\
83
        .annotate(ram=Sum("flavor__ram"),
84
                  cpu=Sum("flavor__cpu"))
85

    
86
    for vm_res in vm_active_resources.iterator():
87
        user = vm_res['userid']
88
        project = vm_res['project']
89
        holdings[user][project]["cyclades.cpu"] = vm_res["cpu"]
90
        holdings[user][project]["cyclades.ram"] = vm_res["ram"] * MiB
91

    
92
    # Get resources related with networks
93
    net_resources = networks.values("userid", "project")\
94
                            .annotate(num=Count("id"))
95

    
96
    for net_res in net_resources.iterator():
97
        user = net_res['userid']
98
        if user is None:
99
            continue
100
        project = net_res['project']
101
        holdings[user][project]["cyclades.network.private"] = net_res["num"]
102

    
103
    floating_ips_resources = floating_ips.values("userid", "project")\
104
                                         .annotate(num=Count("id"))
105

    
106
    for floating_ip_res in floating_ips_resources.iterator():
107
        user = floating_ip_res["userid"]
108
        project = floating_ip_res["project"]
109
        holdings[user][project]["cyclades.floating_ip"] = \
110
            floating_ip_res["num"]
111

    
112
    return holdings
113

    
114

    
115
def get_db_project_holdings(project=None):
116
    """Get holdings from Cyclades DB."""
117
    holdings = QuotaDict()
118

    
119
    vms = VirtualMachine.objects.filter(deleted=False)
120
    networks = Network.objects.filter(deleted=False)
121
    floating_ips = IPAddress.objects.filter(deleted=False, floating_ip=True)
122

    
123
    if project is not None:
124
        vms = vms.filter(project=project)
125
        networks = networks.filter(project=project)
126
        floating_ips = floating_ips.filter(project=project)
127

    
128
    # Get resources related with VMs
129
    vm_resources = vms.values("project")\
130
        .annotate(num=Count("id"),
131
                  total_ram=Sum("flavor__ram"),
132
                  total_cpu=Sum("flavor__cpu"),
133
                  disk=Sum("flavor__disk"))
134

    
135
    for vm_res in vm_resources.iterator():
136
        project = vm_res['project']
137
        res = {"cyclades.vm": vm_res["num"],
138
               "cyclades.total_cpu": vm_res["total_cpu"],
139
               "cyclades.disk": vm_res["disk"] * GiB,
140
               "cyclades.total_ram": vm_res["total_ram"] * MiB}
141
        holdings[project] = res
142

    
143
    vm_active_resources = vms.values("project")\
144
        .filter(Q(operstate="STARTED") | Q(operstate="BUILD") |
145
                Q(operstate="ERROR"))\
146
        .annotate(ram=Sum("flavor__ram"),
147
                  cpu=Sum("flavor__cpu"))
148

    
149
    for vm_res in vm_active_resources.iterator():
150
        project = vm_res['project']
151
        holdings[project]["cyclades.cpu"] = vm_res["cpu"]
152
        holdings[project]["cyclades.ram"] = vm_res["ram"] * MiB
153

    
154
    # Get resources related with networks
155
    net_resources = networks.values("project").annotate(num=Count("id"))
156

    
157
    for net_res in net_resources.iterator():
158
        project = net_res['project']
159
        if project is None:
160
            continue
161
        holdings[project]["cyclades.network.private"] = net_res["num"]
162

    
163
    floating_ips_resources = floating_ips.values("project")\
164
        .annotate(num=Count("id"))
165

    
166
    for floating_ip_res in floating_ips_resources.iterator():
167
        project = floating_ip_res["project"]
168
        holdings[project]["cyclades.floating_ip"] = floating_ip_res["num"]
169

    
170
    return holdings
171

    
172

    
173
def get_quotaholder_holdings(user=None):
174
    """Get quotas from Quotaholder for all Cyclades resources.
175

176
    Returns quotas for all users, unless a single user is specified.
177
    """
178
    qh = Quotaholder.get()
179
    return qh.service_get_quotas(user)
180

    
181

    
182
def get_qh_users_holdings(users=None):
183
    qh = Quotaholder.get()
184
    if users is None or len(users) != 1:
185
        req = None
186
    else:
187
        req = users[0]
188
    quotas = qh.service_get_quotas(req)
189

    
190
    if users is None:
191
        return quotas
192

    
193
    qs = {}
194
    for user in users:
195
        try:
196
            qs[user] = quotas[user]
197
        except KeyError:
198
            pass
199
    return qs
200

    
201

    
202
def get_qh_project_holdings(projects=None):
203
    qh = Quotaholder.get()
204
    if projects is None or len(projects) != 1:
205
        req = None
206
    else:
207
        req = projects[0]
208
    quotas = qh.service_get_project_quotas(req)
209

    
210
    if projects is None:
211
        return quotas
212

    
213
    qs = {}
214
    for project in projects:
215
        try:
216
            qs[project] = quotas[project]
217
        except KeyError:
218
            pass
219
    return qs
220

    
221

    
222
def transform_quotas(quotas):
223
    d = {}
224
    for resource, counters in quotas.iteritems():
225
        used = counters['usage']
226
        limit = counters['limit']
227
        pending = counters['pending']
228
        d[resource] = (used, limit, pending)
229
    return d
230

    
231

    
232
def transform_project_quotas(quotas):
233
    d = {}
234
    for resource, counters in quotas.iteritems():
235
        used = counters['project_usage']
236
        limit = counters['project_limit']
237
        pending = counters['project_pending']
238
        d[resource] = (used, limit, pending)
239
    return d