Statistics
| Branch: | Tag: | Revision:

root / snf-cyclades-app / synnefo / quotas / __init__.py @ 498b2bd0

History | View | Annotate | Download (11.7 kB)

1 bfe7ba3c Christos Stavrakakis
# Copyright 2012 GRNET S.A. All rights reserved.
2 bfe7ba3c Christos Stavrakakis
#
3 bfe7ba3c Christos Stavrakakis
# Redistribution and use in source and binary forms, with or without
4 bfe7ba3c Christos Stavrakakis
# modification, are permitted provided that the following conditions
5 bfe7ba3c Christos Stavrakakis
# are met:
6 bfe7ba3c Christos Stavrakakis
#
7 bfe7ba3c Christos Stavrakakis
#   1. Redistributions of source code must retain the above copyright
8 bfe7ba3c Christos Stavrakakis
#      notice, this list of conditions and the following disclaimer.
9 bfe7ba3c Christos Stavrakakis
#
10 bfe7ba3c Christos Stavrakakis
#  2. Redistributions in binary form must reproduce the above copyright
11 bfe7ba3c Christos Stavrakakis
#     notice, this list of conditions and the following disclaimer in the
12 bfe7ba3c Christos Stavrakakis
#     documentation and/or other materials provided with the distribution.
13 bfe7ba3c Christos Stavrakakis
#
14 bfe7ba3c Christos Stavrakakis
# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
15 bfe7ba3c Christos Stavrakakis
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 bfe7ba3c Christos Stavrakakis
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 bfe7ba3c Christos Stavrakakis
# ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
18 bfe7ba3c Christos Stavrakakis
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 bfe7ba3c Christos Stavrakakis
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 bfe7ba3c Christos Stavrakakis
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 bfe7ba3c Christos Stavrakakis
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 bfe7ba3c Christos Stavrakakis
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 bfe7ba3c Christos Stavrakakis
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 bfe7ba3c Christos Stavrakakis
# SUCH DAMAGE.
25 bfe7ba3c Christos Stavrakakis
#
26 bfe7ba3c Christos Stavrakakis
# The views and conclusions contained in the software and documentation are
27 bfe7ba3c Christos Stavrakakis
# those of the authors and should not be interpreted as representing official
28 bfe7ba3c Christos Stavrakakis
# policies, either expressed or implied, of GRNET S.A.
29 bfe7ba3c Christos Stavrakakis
30 bfe7ba3c Christos Stavrakakis
from functools import wraps
31 bfe7ba3c Christos Stavrakakis
from contextlib import contextmanager
32 bfe7ba3c Christos Stavrakakis
33 b14f55b5 Christos Stavrakakis
34 b14f55b5 Christos Stavrakakis
from synnefo.db.models import QuotaHolderSerial, VirtualMachine, Network
35 bfe7ba3c Christos Stavrakakis
from synnefo.api.faults import OverLimit
36 6dbd90c0 Christos Stavrakakis
from synnefo.settings import CYCLADES_USE_QUOTAHOLDER
37 6dbd90c0 Christos Stavrakakis
38 6dbd90c0 Christos Stavrakakis
if CYCLADES_USE_QUOTAHOLDER:
39 6dbd90c0 Christos Stavrakakis
    from synnefo.settings import (CYCLADES_QUOTAHOLDER_URL,
40 6dbd90c0 Christos Stavrakakis
                                  CYCLADES_QUOTAHOLDER_TOKEN)
41 6dbd90c0 Christos Stavrakakis
    from kamaki.clients.quotaholder import QuotaholderClient
42 6dbd90c0 Christos Stavrakakis
else:
43 6dbd90c0 Christos Stavrakakis
    from synnefo.settings import (VMS_USER_QUOTA, MAX_VMS_PER_USER,
44 6dbd90c0 Christos Stavrakakis
                                  NETWORKS_USER_QUOTA, MAX_NETWORKS_PER_USER)
45 bfe7ba3c Christos Stavrakakis
46 498b2bd0 Georgios D. Tsoukalas
from kamaki.clients.quotaholder.api import (NoCapacityError, NoQuantityError,
47 498b2bd0 Georgios D. Tsoukalas
                                            NoEntityError)
48 7f849a28 Georgios D. Tsoukalas
from kamaki.clients.commissioning import CallError
49 bfe7ba3c Christos Stavrakakis
50 bfe7ba3c Christos Stavrakakis
import logging
51 bfe7ba3c Christos Stavrakakis
log = logging.getLogger(__name__)
52 bfe7ba3c Christos Stavrakakis
53 bfe7ba3c Christos Stavrakakis
54 b14f55b5 Christos Stavrakakis
class DummySerial(QuotaHolderSerial):
55 b14f55b5 Christos Stavrakakis
    accepted = True
56 b14f55b5 Christos Stavrakakis
    rejected = True
57 b14f55b5 Christos Stavrakakis
    pending = True
58 b14f55b5 Christos Stavrakakis
    id = None
59 b14f55b5 Christos Stavrakakis
60 b14f55b5 Christos Stavrakakis
    def save(*args, **kwargs):
61 b14f55b5 Christos Stavrakakis
        pass
62 b14f55b5 Christos Stavrakakis
63 b14f55b5 Christos Stavrakakis
64 b14f55b5 Christos Stavrakakis
class DummyQuotaholderClient(object):
65 b14f55b5 Christos Stavrakakis
    def issue_commission(self, **commission_info):
66 b14f55b5 Christos Stavrakakis
        provisions = commission_info["provisions"]
67 b14f55b5 Christos Stavrakakis
        userid = commission_info["target"]
68 b14f55b5 Christos Stavrakakis
        for provision in provisions:
69 b14f55b5 Christos Stavrakakis
            entity, resource, size = provision
70 e8f8f4aa Christos Stavrakakis
            if resource == "cyclades.vm" and size > 0:
71 b14f55b5 Christos Stavrakakis
                user_vms = VirtualMachine.objects.filter(userid=userid,
72 b14f55b5 Christos Stavrakakis
                                                         deleted=False).count()
73 b14f55b5 Christos Stavrakakis
                user_vm_limit = VMS_USER_QUOTA.get(userid, MAX_VMS_PER_USER)
74 718a601d root
                log.debug("Users VMs %s User Limits %s", user_vms,
75 718a601d root
                          user_vm_limit)
76 5a70b1a3 Christos Stavrakakis
                if user_vms + size > user_vm_limit:
77 5a70b1a3 Christos Stavrakakis
                    raise NoQuantityError(source='cyclades',
78 5a70b1a3 Christos Stavrakakis
                                          target=userid,
79 5a70b1a3 Christos Stavrakakis
                                          resource=resource,
80 5a70b1a3 Christos Stavrakakis
                                          requested=size,
81 5a70b1a3 Christos Stavrakakis
                                          current=user_vms,
82 5a70b1a3 Christos Stavrakakis
                                          limit=user_vm_limit)
83 e8f8f4aa Christos Stavrakakis
            if resource == "cyclades.network.private" and size > 0:
84 b14f55b5 Christos Stavrakakis
                user_networks = Network.objects.filter(userid=userid,
85 b14f55b5 Christos Stavrakakis
                                                       deleted=False).count()
86 68b952f9 Christos Stavrakakis
                user_network_limit =\
87 68b952f9 Christos Stavrakakis
                    NETWORKS_USER_QUOTA.get(userid, MAX_NETWORKS_PER_USER)
88 5a70b1a3 Christos Stavrakakis
                if user_networks + size > user_network_limit:
89 5a70b1a3 Christos Stavrakakis
                    raise NoQuantityError(source='cyclades',
90 5a70b1a3 Christos Stavrakakis
                                          target=userid,
91 5a70b1a3 Christos Stavrakakis
                                          resource=resource,
92 5a70b1a3 Christos Stavrakakis
                                          requested=size,
93 5a70b1a3 Christos Stavrakakis
                                          current=user_networks,
94 5a70b1a3 Christos Stavrakakis
                                          limit=user_network_limit)
95 b14f55b5 Christos Stavrakakis
96 b14f55b5 Christos Stavrakakis
        return None
97 b14f55b5 Christos Stavrakakis
98 b14f55b5 Christos Stavrakakis
    def accept_commission(self, *args, **kwargs):
99 b14f55b5 Christos Stavrakakis
        pass
100 b14f55b5 Christos Stavrakakis
101 b14f55b5 Christos Stavrakakis
    def reject_commission(self, *args, **kwargs):
102 b14f55b5 Christos Stavrakakis
        pass
103 b14f55b5 Christos Stavrakakis
104 b14f55b5 Christos Stavrakakis
    def get_pending_commissions(self, *args, **kwargs):
105 b14f55b5 Christos Stavrakakis
        return []
106 b14f55b5 Christos Stavrakakis
107 b14f55b5 Christos Stavrakakis
108 bfe7ba3c Christos Stavrakakis
@contextmanager
109 bfe7ba3c Christos Stavrakakis
def get_quota_holder():
110 bfe7ba3c Christos Stavrakakis
    """Context manager for using a QuotaHolder."""
111 45855947 Georgios D. Tsoukalas
    if CYCLADES_USE_QUOTAHOLDER:
112 45855947 Georgios D. Tsoukalas
        quotaholder = QuotaholderClient(CYCLADES_QUOTAHOLDER_URL,
113 45855947 Georgios D. Tsoukalas
                                        token=CYCLADES_QUOTAHOLDER_TOKEN)
114 b14f55b5 Christos Stavrakakis
    else:
115 b14f55b5 Christos Stavrakakis
        quotaholder = DummyQuotaholderClient()
116 bfe7ba3c Christos Stavrakakis
117 bfe7ba3c Christos Stavrakakis
    try:
118 bfe7ba3c Christos Stavrakakis
        yield quotaholder
119 bfe7ba3c Christos Stavrakakis
    finally:
120 bfe7ba3c Christos Stavrakakis
        pass
121 bfe7ba3c Christos Stavrakakis
122 bfe7ba3c Christos Stavrakakis
123 bfe7ba3c Christos Stavrakakis
def uses_commission(func):
124 bfe7ba3c Christos Stavrakakis
    """Decorator for wrapping functions that needs commission.
125 bfe7ba3c Christos Stavrakakis

126 bfe7ba3c Christos Stavrakakis
    All decorated functions must take as first argument the `serials` list in
127 bfe7ba3c Christos Stavrakakis
    order to extend them with the needed serial numbers, as return by the
128 bfe7ba3c Christos Stavrakakis
    Quotaholder
129 bfe7ba3c Christos Stavrakakis

130 bfe7ba3c Christos Stavrakakis
    On successful competition of the decorated function, all serials are
131 bfe7ba3c Christos Stavrakakis
    accepted to the quotaholder, otherwise they are rejected.
132 bfe7ba3c Christos Stavrakakis

133 bfe7ba3c Christos Stavrakakis
    """
134 bfe7ba3c Christos Stavrakakis
135 bfe7ba3c Christos Stavrakakis
    @wraps(func)
136 bfe7ba3c Christos Stavrakakis
    def wrapper(*args, **kwargs):
137 bfe7ba3c Christos Stavrakakis
        try:
138 bfe7ba3c Christos Stavrakakis
            serials = []
139 bfe7ba3c Christos Stavrakakis
            ret = func(serials, *args, **kwargs)
140 bfe7ba3c Christos Stavrakakis
            if serials:
141 bfe7ba3c Christos Stavrakakis
                accept_commission(serials)
142 bfe7ba3c Christos Stavrakakis
            return ret
143 e8f2d02d Christos Stavrakakis
        except CallError:
144 bfe7ba3c Christos Stavrakakis
            log.exception("Unexpected error")
145 b14f55b5 Christos Stavrakakis
            raise
146 bfe7ba3c Christos Stavrakakis
        except:
147 bfe7ba3c Christos Stavrakakis
            if serials:
148 bfe7ba3c Christos Stavrakakis
                reject_commission(serials=serials)
149 bfe7ba3c Christos Stavrakakis
            raise
150 bfe7ba3c Christos Stavrakakis
    return wrapper
151 bfe7ba3c Christos Stavrakakis
152 bfe7ba3c Christos Stavrakakis
153 bfe7ba3c Christos Stavrakakis
## FIXME: Wrap the following two functions inside transaction ?
154 11a54cb9 Christos Stavrakakis
def accept_commission(serials, update_db=True):
155 bfe7ba3c Christos Stavrakakis
    """Accept a list of pending commissions.
156 bfe7ba3c Christos Stavrakakis

157 bfe7ba3c Christos Stavrakakis
    @param serials: List of QuotaHolderSerial objects
158 bfe7ba3c Christos Stavrakakis

159 bfe7ba3c Christos Stavrakakis
    """
160 11a54cb9 Christos Stavrakakis
    if update_db:
161 11a54cb9 Christos Stavrakakis
        for s in serials:
162 11a54cb9 Christos Stavrakakis
            if s.pending:
163 11a54cb9 Christos Stavrakakis
                s.accepted = True
164 11a54cb9 Christos Stavrakakis
                s.save()
165 bfe7ba3c Christos Stavrakakis
166 bfe7ba3c Christos Stavrakakis
    with get_quota_holder() as qh:
167 bfe7ba3c Christos Stavrakakis
        qh.accept_commission(context={},
168 bfe7ba3c Christos Stavrakakis
                             clientkey='cyclades',
169 bfe7ba3c Christos Stavrakakis
                             serials=[s.serial for s in serials])
170 bfe7ba3c Christos Stavrakakis
171 bfe7ba3c Christos Stavrakakis
172 11a54cb9 Christos Stavrakakis
def reject_commission(serials, update_db=True):
173 bfe7ba3c Christos Stavrakakis
    """Reject a list of pending commissions.
174 bfe7ba3c Christos Stavrakakis

175 bfe7ba3c Christos Stavrakakis
    @param serials: List of QuotaHolderSerial objects
176 bfe7ba3c Christos Stavrakakis

177 bfe7ba3c Christos Stavrakakis
    """
178 11a54cb9 Christos Stavrakakis
    if update_db:
179 11a54cb9 Christos Stavrakakis
        for s in serials:
180 11a54cb9 Christos Stavrakakis
            if s.pending:
181 11a54cb9 Christos Stavrakakis
                s.rejected = True
182 11a54cb9 Christos Stavrakakis
                s.save()
183 bfe7ba3c Christos Stavrakakis
184 bfe7ba3c Christos Stavrakakis
    with get_quota_holder() as qh:
185 bfe7ba3c Christos Stavrakakis
        qh.reject_commission(context={},
186 bfe7ba3c Christos Stavrakakis
                             clientkey='cyclades',
187 bfe7ba3c Christos Stavrakakis
                             serials=[s.serial for s in serials])
188 bfe7ba3c Christos Stavrakakis
189 bfe7ba3c Christos Stavrakakis
190 bfe7ba3c Christos Stavrakakis
def issue_commission(**commission_info):
191 bfe7ba3c Christos Stavrakakis
    """Issue a new commission to the quotaholder.
192 bfe7ba3c Christos Stavrakakis

193 bfe7ba3c Christos Stavrakakis
    Issue a new commission to the quotaholder, and create the
194 bfe7ba3c Christos Stavrakakis
    corresponing QuotaHolderSerial object in DB.
195 bfe7ba3c Christos Stavrakakis

196 bfe7ba3c Christos Stavrakakis
    """
197 bfe7ba3c Christos Stavrakakis
198 bfe7ba3c Christos Stavrakakis
    with get_quota_holder() as qh:
199 bfe7ba3c Christos Stavrakakis
        try:
200 bfe7ba3c Christos Stavrakakis
            serial = qh.issue_commission(**commission_info)
201 5a70b1a3 Christos Stavrakakis
        except (NoCapacityError, NoQuantityError) as e:
202 5a70b1a3 Christos Stavrakakis
            msg, details = render_quotaholder_exception(e)
203 5a70b1a3 Christos Stavrakakis
            raise OverLimit(msg, details=details)
204 e8f2d02d Christos Stavrakakis
        except CallError as e:
205 5a70b1a3 Christos Stavrakakis
            log.exception("Unexpected error")
206 6dbd90c0 Christos Stavrakakis
            raise
207 bfe7ba3c Christos Stavrakakis
208 b14f55b5 Christos Stavrakakis
    if serial:
209 b14f55b5 Christos Stavrakakis
        return QuotaHolderSerial.objects.create(serial=serial)
210 718a601d root
    elif not CYCLADES_USE_QUOTAHOLDER:
211 b14f55b5 Christos Stavrakakis
        return DummySerial()
212 b14f55b5 Christos Stavrakakis
    else:
213 b14f55b5 Christos Stavrakakis
        raise Exception("No serial")
214 bfe7ba3c Christos Stavrakakis
215 bfe7ba3c Christos Stavrakakis
216 bfe7ba3c Christos Stavrakakis
# Wrapper functions for issuing commissions for each resource type.  Each
217 bfe7ba3c Christos Stavrakakis
# functions creates the `commission_info` dictionary as expected by the
218 bfe7ba3c Christos Stavrakakis
# `issue_commision` function. Commissions for deleting a resource, are the same
219 bfe7ba3c Christos Stavrakakis
# as for creating the same resource, but with negative resource sizes.
220 bfe7ba3c Christos Stavrakakis
221 bfe7ba3c Christos Stavrakakis
222 bfe7ba3c Christos Stavrakakis
def issue_vm_commission(user, flavor, delete=False):
223 bfe7ba3c Christos Stavrakakis
    resources = get_server_resources(flavor)
224 bfe7ba3c Christos Stavrakakis
    commission_info = create_commission(user, resources, delete)
225 bfe7ba3c Christos Stavrakakis
226 bfe7ba3c Christos Stavrakakis
    return issue_commission(**commission_info)
227 bfe7ba3c Christos Stavrakakis
228 bfe7ba3c Christos Stavrakakis
229 bfe7ba3c Christos Stavrakakis
def get_server_resources(flavor):
230 bfe7ba3c Christos Stavrakakis
    return {'vm': 1,
231 bfe7ba3c Christos Stavrakakis
            'cpu': flavor.cpu,
232 457a8ada Christos Stavrakakis
            'disk': 1073741824 * flavor.disk,  # flavor.disk is in GB
233 bfe7ba3c Christos Stavrakakis
            # 'public_ip': 1,
234 bfe7ba3c Christos Stavrakakis
            #'disk_template': flavor.disk_template,
235 5805fbb1 Christos Stavrakakis
            'ram': 1048576 * flavor.ram}  # flavor.ram is in MB
236 bfe7ba3c Christos Stavrakakis
237 bfe7ba3c Christos Stavrakakis
238 bfe7ba3c Christos Stavrakakis
def issue_network_commission(user, delete=False):
239 bfe7ba3c Christos Stavrakakis
    resources = get_network_resources()
240 bfe7ba3c Christos Stavrakakis
    commission_info = create_commission(user, resources, delete)
241 bfe7ba3c Christos Stavrakakis
242 bfe7ba3c Christos Stavrakakis
    return issue_commission(**commission_info)
243 bfe7ba3c Christos Stavrakakis
244 bfe7ba3c Christos Stavrakakis
245 bfe7ba3c Christos Stavrakakis
def get_network_resources():
246 bfe7ba3c Christos Stavrakakis
    return {"network.private": 1}
247 bfe7ba3c Christos Stavrakakis
248 bfe7ba3c Christos Stavrakakis
249 bfe7ba3c Christos Stavrakakis
def invert_resources(resources_dict):
250 bfe7ba3c Christos Stavrakakis
    return dict((r, -s) for r, s in resources_dict.items())
251 bfe7ba3c Christos Stavrakakis
252 bfe7ba3c Christos Stavrakakis
253 bfe7ba3c Christos Stavrakakis
def create_commission(user, resources, delete=False):
254 bfe7ba3c Christos Stavrakakis
    if delete:
255 bfe7ba3c Christos Stavrakakis
        resources = invert_resources(resources)
256 4ac68aaf Christos Stavrakakis
    provisions = [('cyclades', 'cyclades.' + r, s)
257 bfe7ba3c Christos Stavrakakis
                  for r, s in resources.items()]
258 68b952f9 Christos Stavrakakis
    return {"context": {},
259 68b952f9 Christos Stavrakakis
            "target": user,
260 68b952f9 Christos Stavrakakis
            "key": "1",
261 68b952f9 Christos Stavrakakis
            "clientkey": "cyclades",
262 68b952f9 Christos Stavrakakis
            #"owner":      "",
263 68b952f9 Christos Stavrakakis
            #"ownerkey":   "1",
264 68b952f9 Christos Stavrakakis
            "name": "",
265 68b952f9 Christos Stavrakakis
            "provisions": provisions}
266 11a54cb9 Christos Stavrakakis
267 11a54cb9 Christos Stavrakakis
##
268 11a54cb9 Christos Stavrakakis
## Reconcile pending commissions
269 11a54cb9 Christos Stavrakakis
##
270 11a54cb9 Christos Stavrakakis
271 11a54cb9 Christos Stavrakakis
272 11a54cb9 Christos Stavrakakis
def accept_commissions(accepted):
273 11a54cb9 Christos Stavrakakis
    with get_quota_holder() as qh:
274 11a54cb9 Christos Stavrakakis
        qh.accept_commission(context={},
275 11a54cb9 Christos Stavrakakis
                             clientkey='cyclades',
276 11a54cb9 Christos Stavrakakis
                             serials=accepted)
277 11a54cb9 Christos Stavrakakis
278 11a54cb9 Christos Stavrakakis
279 11a54cb9 Christos Stavrakakis
def reject_commissions(rejected):
280 11a54cb9 Christos Stavrakakis
    with get_quota_holder() as qh:
281 11a54cb9 Christos Stavrakakis
            qh.reject_commission(context={},
282 11a54cb9 Christos Stavrakakis
                                 clientkey='cyclades',
283 11a54cb9 Christos Stavrakakis
                                 serials=rejected)
284 11a54cb9 Christos Stavrakakis
285 11a54cb9 Christos Stavrakakis
286 11a54cb9 Christos Stavrakakis
def fix_pending_commissions():
287 11a54cb9 Christos Stavrakakis
    (accepted, rejected) = resolve_pending_commissions()
288 11a54cb9 Christos Stavrakakis
289 11a54cb9 Christos Stavrakakis
    with get_quota_holder() as qh:
290 11a54cb9 Christos Stavrakakis
        if accepted:
291 11a54cb9 Christos Stavrakakis
            qh.accept_commission(context={},
292 11a54cb9 Christos Stavrakakis
                                 clientkey='cyclades',
293 11a54cb9 Christos Stavrakakis
                                 serials=accepted)
294 11a54cb9 Christos Stavrakakis
        if rejected:
295 11a54cb9 Christos Stavrakakis
            qh.reject_commission(context={},
296 11a54cb9 Christos Stavrakakis
                                 clientkey='cyclades',
297 11a54cb9 Christos Stavrakakis
                                 serials=rejected)
298 11a54cb9 Christos Stavrakakis
299 11a54cb9 Christos Stavrakakis
300 11a54cb9 Christos Stavrakakis
def resolve_pending_commissions():
301 11a54cb9 Christos Stavrakakis
    """Resolve quotaholder pending commissions.
302 11a54cb9 Christos Stavrakakis

303 11a54cb9 Christos Stavrakakis
    Get pending commissions from the quotaholder and resolve them
304 11a54cb9 Christos Stavrakakis
    to accepted and rejected, according to the state of the
305 11a54cb9 Christos Stavrakakis
    QuotaHolderSerial DB table. A pending commission in the quotaholder
306 11a54cb9 Christos Stavrakakis
    can exist in the QuotaHolderSerial table and be either accepted or
307 11a54cb9 Christos Stavrakakis
    rejected, or can not exist in this table, so it is rejected.
308 11a54cb9 Christos Stavrakakis

309 11a54cb9 Christos Stavrakakis
    """
310 11a54cb9 Christos Stavrakakis
311 11a54cb9 Christos Stavrakakis
    qh_pending = get_quotaholder_pending()
312 11a54cb9 Christos Stavrakakis
    if not qh_pending:
313 11a54cb9 Christos Stavrakakis
        return ([], [])
314 11a54cb9 Christos Stavrakakis
315 11a54cb9 Christos Stavrakakis
    qh_pending.sort()
316 11a54cb9 Christos Stavrakakis
    min_ = qh_pending[0]
317 11a54cb9 Christos Stavrakakis
318 11a54cb9 Christos Stavrakakis
    serials = QuotaHolderSerial.objects.filter(serial__gte=min_, pending=False)
319 11a54cb9 Christos Stavrakakis
    accepted = serials.filter(accepted=True).values_list('serial', flat=True)
320 11a54cb9 Christos Stavrakakis
    accepted = filter(lambda x: x in qh_pending, accepted)
321 11a54cb9 Christos Stavrakakis
322 11a54cb9 Christos Stavrakakis
    rejected = list(set(qh_pending) - set(accepted))
323 11a54cb9 Christos Stavrakakis
324 11a54cb9 Christos Stavrakakis
    return (accepted, rejected)
325 11a54cb9 Christos Stavrakakis
326 11a54cb9 Christos Stavrakakis
327 11a54cb9 Christos Stavrakakis
def get_quotaholder_pending():
328 11a54cb9 Christos Stavrakakis
    with get_quota_holder() as qh:
329 11a54cb9 Christos Stavrakakis
        pending_serials = qh.get_pending_commissions(context={},
330 11a54cb9 Christos Stavrakakis
                                                     clientkey='cyclades')
331 11a54cb9 Christos Stavrakakis
    return pending_serials
332 5a70b1a3 Christos Stavrakakis
333 5a70b1a3 Christos Stavrakakis
334 5a70b1a3 Christos Stavrakakis
def render_quotaholder_exception(e):
335 5a70b1a3 Christos Stavrakakis
    resource_name = {"vm": "Virtual Machine",
336 5a70b1a3 Christos Stavrakakis
                     "cpu": "CPU",
337 5a70b1a3 Christos Stavrakakis
                     "ram": "RAM",
338 5a70b1a3 Christos Stavrakakis
                     "network.private": "Private Network"}
339 5a70b1a3 Christos Stavrakakis
    res = e.resource.replace("cyclades.", "", 1)
340 5a70b1a3 Christos Stavrakakis
    try:
341 5a70b1a3 Christos Stavrakakis
        resource = resource_name[res]
342 5a70b1a3 Christos Stavrakakis
    except KeyError:
343 5a70b1a3 Christos Stavrakakis
        resource = res
344 5a70b1a3 Christos Stavrakakis
345 5a70b1a3 Christos Stavrakakis
    requested = e.requested
346 5a70b1a3 Christos Stavrakakis
    current = e.current
347 5a70b1a3 Christos Stavrakakis
    limit = e.limit
348 5a70b1a3 Christos Stavrakakis
    msg = "Resource Limit Exceeded for your account."
349 5a70b1a3 Christos Stavrakakis
    details = "Limit for resource '%s' exceeded for your account."\
350 5a70b1a3 Christos Stavrakakis
              " Current value: %s, Limit: %s, Requested: %s"\
351 5a70b1a3 Christos Stavrakakis
              % (resource, current, limit, requested)
352 5a70b1a3 Christos Stavrakakis
    return msg, details